"""
提醒计划生成器。

从事件列表生成提醒计划，处理全天事件、已过期提醒等边界情况。
"""

from __future__ import annotations

import logging
import sys
from dataclasses import dataclass
from datetime import datetime, timedelta, timezone
from pathlib import Path

sys.path.insert(0, str(Path(__file__).parent.parent))

import yaml

from compat import ZoneInfo, make_aware
from gcal.models import CalendarEvent
from .event_classifier import EventClassifier

logger = logging.getLogger(__name__)

_DEFAULT_RULES_PATH = Path(__file__).parent.parent / "config" / "reminder_rules.yaml"
_DEFAULT_TZ = "Asia/Shanghai"

_BUILTIN_LEAD = {"sport": 15, "meal": 15, "family": 15, "medical": 30, "appointment": 10}
_BUILTIN_DEFAULT_LEAD = 10


def _load_lead_minutes(path: Path) -> tuple[dict[str, int], int]:
    try:
        with open(path, encoding="utf-8") as f:
            data = yaml.safe_load(f) or {}
        lead    = {k: int(v) for k, v in data.get("lead_minutes", {}).items()}
        default = int(data.get("default_lead_minutes", _BUILTIN_DEFAULT_LEAD))
        return lead or _BUILTIN_LEAD, default
    except Exception as e:
        logger.warning(f"加载提醒规则失败，使用内置: {e}")
        return _BUILTIN_LEAD, _BUILTIN_DEFAULT_LEAD


@dataclass
class ReminderPlan:
    event:           CalendarEvent
    event_type:      str       # sport / meal / family / medical / appointment
    lead_minutes:    int       # 提前多少分钟
    remind_at:       datetime  # 北京时间（aware）
    remind_at_utc:   datetime  # UTC（aware）
    should_schedule: bool      # False = 提醒时间已过，跳过创建

    def reminder_message(self) -> str:
        t_start   = self.event.start.strftime("%H:%M")
        t_end     = self.event.end.strftime("%H:%M") if self.event.end else ""
        time_range = f"{t_start}–{t_end}" if t_end and t_end != t_start else t_start

        lines = [f"⏰ **{self.event.summary}** 将在 {self.lead_minutes} 分钟后开始"]
        lines.append(f"🕐 {time_range}（共 {self.event.duration_minutes()} 分钟）")
        if self.event.location:
            lines.append(f"📍 {self.event.location}")
        if self.event.description:
            first_line = self.event.description.split("\n")[0].strip()
            if first_line and len(first_line) <= 60:
                lines.append(f"📝 {first_line}")
        return "\n".join(lines)


def plan_reminders(
    events: list[CalendarEvent],
    now: datetime | None = None,
    rules_path: Path | None = None,
    classifier: EventClassifier | None = None,
    tz: str = _DEFAULT_TZ,
) -> list[ReminderPlan]:
    """
    从事件列表生成提醒计划列表。

    跳过：
      - 全天事件（is_all_day=True）
      - start 为空的事件
    标记 should_schedule=False（不跳过，但不创建 cron 任务）：
      - 提醒时间早于 now
    """
    zone = ZoneInfo(tz)
    if now is None:
        now = datetime.now(zone)
    if now.tzinfo is None:
        now = now.replace(tzinfo=zone)

    lead_map, default_lead = _load_lead_minutes(rules_path or _DEFAULT_RULES_PATH)
    clf = classifier or EventClassifier(rules_path)

    plans: list[ReminderPlan] = []
    for event in events:
        if event.is_all_day:
            logger.debug(f"跳过全天事件: {event.summary}")
            continue
        if event.start is None:
            logger.debug(f"跳过无开始时间事件: {event.summary}")
            continue

        event_type = clf.classify(event.summary, event.description)
        lead       = lead_map.get(event_type, default_lead)
        remind_at  = event.start - timedelta(minutes=lead)

        plans.append(ReminderPlan(
            event           = event,
            event_type      = event_type,
            lead_minutes    = lead,
            remind_at       = remind_at,
            remind_at_utc   = remind_at.astimezone(timezone.utc),
            should_schedule = remind_at >= now,
        ))

    return plans
