"""Agente principal: orquesta Xiaomi + decisiones + calendario."""
import os
import signal
import sys
from datetime import datetime, timedelta

import yaml

from notification_scheduler import process_due, schedule_message


BASE_DIR = os.path.dirname(os.path.abspath(__file__))
CONFIG_PATH = os.path.abspath(os.path.join(BASE_DIR, "..", "config", "health_config.yaml"))


def _load_config(path=CONFIG_PATH):
    with open(path, "r", encoding="utf-8") as f:
        return yaml.safe_load(f)


def _parse_time(today, hhmm):
    h, m = [int(x) for x in hhmm.split(":")]
    return today.replace(hour=h, minute=m, second=0, microsecond=0)


def _get_now():
    override = os.environ.get("NOW")
    if override:
        dt = datetime.fromisoformat(override)
        if dt.tzinfo is None:
            dt = dt.replace(tzinfo=datetime.now().astimezone().tzinfo)
        return dt
    return datetime.now().astimezone()


def _iter_schedule(start_dt, end_dt, interval_min):
    cursor = start_dt
    delta = timedelta(minutes=interval_min)
    while cursor <= end_dt:
        yield cursor
        cursor = cursor + delta


def generate_base_reminders(now, cfg):
    reminders_cfg = cfg.get("reminders", {})
    active = reminders_cfg.get("active_hours", {})
    start = _parse_time(now, active.get("start", "08:00"))
    end = _parse_time(now, active.get("end", "22:30"))
    window_min = int(reminders_cfg.get("generation_window_min", 180))
    window_end = min(end, now + timedelta(minutes=window_min))

    # Evitar programar en el pasado (o demasiado cerca)
    safe_now = now + timedelta(minutes=1)
    window_start = max(safe_now, start)
    if window_end < window_start:
        return []

    items = []

    # Movement breaks
    move_interval = int(reminders_cfg.get("movement_break_interval_min", 60))
    for when in _iter_schedule(window_start, window_end, move_interval):
        items.append(
            {
                "when": when,
                "message": "🚶 Pausa activa: levantate y elongá 2 min.",
                "type": "movement_break",
            }
        )

    # Water reminders
    water_interval = int(reminders_cfg.get("water_interval_min", 90))
    for when in _iter_schedule(window_start, window_end, water_interval):
        items.append(
            {
                "when": when,
                "message": "💧 Tomá un vaso de agua.",
                "type": "water",
            }
        )

    # Morning walk
    walk_time = reminders_cfg.get("walk_morning_time")
    if walk_time:
        walk_dt = _parse_time(now, walk_time)
        if window_start <= walk_dt <= window_end:
            items.append(
                {
                    "when": walk_dt,
                    "message": "🚶‍♂️ Caminata matutina: 15–20 min para arrancar el día.",
                    "type": "morning_walk",
                }
            )

    # Meal reminders (protein)
    for t in reminders_cfg.get("meal_times", []):
        meal_dt = _parse_time(now, t)
        if window_start <= meal_dt <= window_end:
            items.append(
                {
                    "when": meal_dt,
                    "message": "🍽️ Comida: calculá tu proteína y priorizá calidad.",
                    "type": "meal_protein",
                }
            )

    # Screen cutoff (single reminder)
    cutoff = reminders_cfg.get("screen_cutoff_time")
    if cutoff:
        cutoff_dt = _parse_time(now, cutoff)
        if window_start <= cutoff_dt <= window_end:
            items.append(
                {
                    "when": cutoff_dt,
                    "message": "🌙 Pantallas off en 10 min. Cerrá el día y no uses el teléfono.",
                    "type": "screen_cutoff",
                }
            )

    items.sort(key=lambda x: x["when"])
    return items


def _timeout_handler(_signum, _frame):
    print("health_agent: timeout reached; exiting", flush=True)
    sys.exit(0)


def run_health_check():
    # Hard guard to prevent hung runs
    signal.signal(signal.SIGALRM, _timeout_handler)
    signal.alarm(int(os.environ.get("HEALTH_AGENT_TIMEOUT_S", "20")))

    quiet = os.environ.get("HEALTH_AGENT_QUIET", "").lower() in {"1", "true", "yes"}

    try:
        cfg = _load_config()

        # MVP: solo recordatorios base (sin calendar real ni xiaomi real)
        now = _get_now()
        items = generate_base_reminders(now, cfg)
        if not quiet:
            print(f"health_agent: scheduling {len(items)} reminders @ {now.isoformat()}", flush=True)
        for item in items:
            schedule_message(item["when"].isoformat(), item["message"], name=item["type"])

        # Placeholder: procesamiento legado (no-op en cron)
        process_due()
        if not quiet:
            print("health_agent: done", flush=True)
    finally:
        signal.alarm(0)
        sys.exit(0)


def run_once():
    run_health_check()


if __name__ == "__main__":
    # Por defecto: una sola corrida (ideal para cron)
    run_once()
