import numpy as np

from backend.app.models.activity import DataPoint

# Coggan 7-zone power model (% of FTP)
POWER_ZONES = [
    {"zone": 1, "name": "Active Recovery", "min_pct": 0, "max_pct": 55},
    {"zone": 2, "name": "Endurance", "min_pct": 55, "max_pct": 75},
    {"zone": 3, "name": "Tempo", "min_pct": 75, "max_pct": 90},
    {"zone": 4, "name": "Threshold", "min_pct": 90, "max_pct": 105},
    {"zone": 5, "name": "VO2max", "min_pct": 105, "max_pct": 120},
    {"zone": 6, "name": "Anaerobic", "min_pct": 120, "max_pct": 150},
    {"zone": 7, "name": "Neuromuscular", "min_pct": 150, "max_pct": 10000},
]

# 5-zone HR model (% of LTHR)
HR_ZONES = [
    {"zone": 1, "name": "Recovery", "min_pct": 0, "max_pct": 81},
    {"zone": 2, "name": "Aerobic", "min_pct": 81, "max_pct": 90},
    {"zone": 3, "name": "Tempo", "min_pct": 90, "max_pct": 95},
    {"zone": 4, "name": "Threshold", "min_pct": 95, "max_pct": 100},
    {"zone": 5, "name": "Anaerobic", "min_pct": 100, "max_pct": 10000},
]


def calculate_power_zones(
    data_points: list[DataPoint],
    ftp: float,
) -> list[dict]:
    """Calculate time-in-zone distribution for power."""
    powers = np.array([dp.power for dp in data_points if dp.power is not None], dtype=float)
    if len(powers) == 0 or ftp <= 0:
        return []

    total = len(powers)
    result = []
    for z in POWER_ZONES:
        low = ftp * z["min_pct"] / 100
        high = ftp * z["max_pct"] / 100
        seconds = int(np.sum((powers >= low) & (powers < high)))
        result.append({
            "zone": z["zone"],
            "name": z["name"],
            "min_watts": round(low),
            "max_watts": round(high) if z["max_pct"] < 10000 else None,
            "seconds": seconds,
            "percentage": round(seconds / total * 100, 1) if total > 0 else 0,
        })
    return result


def calculate_hr_zones(
    data_points: list[DataPoint],
    lthr: int,
) -> list[dict]:
    """Calculate time-in-zone distribution for heart rate."""
    hrs = np.array([dp.heart_rate for dp in data_points if dp.heart_rate is not None], dtype=float)
    if len(hrs) == 0 or lthr <= 0:
        return []

    total = len(hrs)
    result = []
    for z in HR_ZONES:
        low = lthr * z["min_pct"] / 100
        high = lthr * z["max_pct"] / 100
        seconds = int(np.sum((hrs >= low) & (hrs < high)))
        result.append({
            "zone": z["zone"],
            "name": z["name"],
            "min_bpm": round(low),
            "max_bpm": round(high) if z["max_pct"] < 10000 else None,
            "seconds": seconds,
            "percentage": round(seconds / total * 100, 1) if total > 0 else 0,
        })
    return result
