#!/usr/bin/env python3
"""Export WHOOP history data to JSON for dashboard consumption."""

import json
import sys
from datetime import datetime, timedelta, timezone
from pathlib import Path

# Add src to path
sys.path.insert(0, str(Path(__file__).parent.parent / "src"))

from whoop_mcp.client import WhoopClient


def get_day_name(date_str: str) -> str:
    """Get day name from date string."""
    date = datetime.strptime(date_str, "%Y-%m-%d")
    return date.strftime("%a")


def export_history(days: int = 30):
    """Export WHOOP history to JSON file."""
    client = WhoopClient()

    print(f"Fetching {days} days of WHOOP data...")

    # Fetch data (API limits to ~10 records per call, so we need multiple calls)
    all_recovery = []
    all_sleep = []
    all_strain = []

    # Fetch in batches of 10
    batch_size = 10
    for offset in range(0, days, batch_size):
        batch_days = min(batch_size, days - offset)
        end = datetime.now(timezone.utc) - timedelta(days=offset)
        start = end - timedelta(days=batch_days)

        try:
            recoveries = client.get_recovery_collection(start=start, end=end, limit=batch_size)
            all_recovery.extend(recoveries)
        except Exception as e:
            print(f"  Recovery batch {offset}: {e}")

        try:
            sleeps = client.get_sleep_collection(start=start, end=end, limit=batch_size)
            all_sleep.extend(sleeps)
        except Exception as e:
            print(f"  Sleep batch {offset}: {e}")

        try:
            cycles = client.get_cycle_collection(start=start, end=end, limit=batch_size)
            all_strain.extend(cycles)
        except Exception as e:
            print(f"  Strain batch {offset}: {e}")

    print(f"  Got {len(all_recovery)} recovery, {len(all_sleep)} sleep, {len(all_strain)} strain records")

    # Process and merge data by date
    data_by_date = {}

    # Process recovery
    for r in all_recovery:
        score = r.get("score", {})
        created = r.get("created_at", "")
        date_str = created[:10] if created else None
        if not date_str or score.get("recovery_score") is None:
            continue

        recovery_score = score.get("recovery_score")
        # Skip nap entries (very low scores that duplicate the date)
        if recovery_score <= 1:
            continue

        if date_str not in data_by_date:
            data_by_date[date_str] = {"date": date_str, "day": get_day_name(date_str)}

        data_by_date[date_str].update({
            "recovery": recovery_score,
            "hrv": round(score.get("hrv_rmssd_milli", 0), 1) if score.get("hrv_rmssd_milli") else 0,
            "rhr": round(score.get("resting_heart_rate", 0)) if score.get("resting_heart_rate") else 0,
            "zone": get_zone(recovery_score),
        })

    # Process sleep
    for s in all_sleep:
        score = s.get("score", {})
        stages = score.get("stage_summary", {})
        created = s.get("created_at", "")
        date_str = created[:10] if created else None
        if not date_str:
            continue

        total_sleep_ms = stages.get("total_in_bed_time_milli", 0) - stages.get("total_awake_time_milli", 0)
        sleep_hours = round(total_sleep_ms / (1000 * 60 * 60), 1)

        # Skip naps (very short sleep)
        if sleep_hours < 2:
            continue

        if date_str not in data_by_date:
            data_by_date[date_str] = {"date": date_str, "day": get_day_name(date_str)}

        data_by_date[date_str].update({
            "sleep": sleep_hours,
            "efficiency": round(score.get("sleep_efficiency_percentage", 0), 1) if score.get("sleep_efficiency_percentage") else 0,
            "performance": round(score.get("sleep_performance_percentage", 0), 1) if score.get("sleep_performance_percentage") else 0,
            "deep": round(stages.get("total_slow_wave_sleep_time_milli", 0) / (1000 * 60 * 60), 1),
            "rem": round(stages.get("total_rem_sleep_time_milli", 0) / (1000 * 60 * 60), 1),
        })

    # Process strain
    for c in all_strain:
        score = c.get("score", {})
        created = c.get("created_at", "")
        date_str = created[:10] if created else None
        if not date_str:
            continue

        if date_str not in data_by_date:
            data_by_date[date_str] = {"date": date_str, "day": get_day_name(date_str)}

        data_by_date[date_str].update({
            "strain": round(score.get("strain", 0), 1),
            "calories": round(score.get("kilojoule", 0)),
            "avg_hr": score.get("average_heart_rate", 0),
            "max_hr": score.get("max_heart_rate", 0),
        })

    # Sort by date descending
    sorted_data = sorted(data_by_date.values(), key=lambda x: x["date"], reverse=True)

    # Fill in missing fields with defaults
    for entry in sorted_data:
        entry.setdefault("recovery", 0)
        entry.setdefault("hrv", 0)
        entry.setdefault("rhr", 0)
        entry.setdefault("zone", "red")
        entry.setdefault("sleep", 0)
        entry.setdefault("efficiency", 0)
        entry.setdefault("strain", 0)

    # Output path
    output_path = Path(__file__).parent.parent.parent.parent / "whoop-data.json"

    output = {
        "updated": datetime.now().isoformat(),
        "days": len(sorted_data),
        "data": sorted_data
    }

    with open(output_path, "w") as f:
        json.dump(output, f, indent=2)

    print(f"\nExported {len(sorted_data)} days to {output_path}")
    print(f"Latest: {sorted_data[0]['date']} - Recovery {sorted_data[0]['recovery']}%, Sleep {sorted_data[0]['sleep']}h, Strain {sorted_data[0]['strain']}")

    return output


def get_zone(score: int) -> str:
    """Get recovery zone from score."""
    if score >= 67:
        return "green"
    if score >= 34:
        return "yellow"
    return "red"


if __name__ == "__main__":
    days = int(sys.argv[1]) if len(sys.argv) > 1 else 30
    export_history(days)
