"""每日学习时段 — 人格建立后 0:00–1:00 技能自学窗口。"""

from __future__ import annotations

from datetime import datetime
from typing import Any
from zoneinfo import ZoneInfo


def _parse_hhmm(value: str) -> tuple[int, int]:
    raw = str(value or "00:00").strip()
    parts = raw.split(":")
    hour = int(parts[0]) if parts else 0
    minute = int(parts[1]) if len(parts) > 1 else 0
    return max(0, min(23, hour)), max(0, min(59, minute))


def local_now(timezone: str) -> datetime:
    try:
        tz = ZoneInfo(timezone)
    except Exception:
        tz = ZoneInfo("Asia/Shanghai")
    return datetime.now(tz)


def in_daily_window(
    now: datetime,
    *,
    window_start: str = "00:00",
    window_end: str = "01:00",
) -> bool:
    """窗口 [start, end)；end <= start 时表示跨午夜（如 22:00–06:00）。"""
    sh, sm = _parse_hhmm(window_start)
    eh, em = _parse_hhmm(window_end)
    start_m = sh * 60 + sm
    end_m = eh * 60 + em
    cur_m = now.hour * 60 + now.minute
    if end_m <= start_m:
        return cur_m >= start_m or cur_m < end_m
    return start_m <= cur_m < end_m


def schedule_gate(
    schedule: dict[str, Any] | None,
    *,
    manual: bool,
    bootstrap_complete: bool,
    now: datetime | None = None,
) -> tuple[bool, str]:
    """manual=True 跳过时段（Console 手动跑批）；bootstrap 未完成时技能轨不自动跑。"""
    if manual:
        return True, "manual"
    sched = schedule or {}
    mode = str(sched.get("mode") or "daily_window")
    if mode == "bootstrap_free":
        return True, "bootstrap_free"
    if not bootstrap_complete:
        return False, "bootstrap_pending"
    if mode != "daily_window":
        return True, "ok"
    tz = str(sched.get("timezone") or "Asia/Shanghai")
    now_local = now if now is not None else local_now(tz)
    if not in_daily_window(
        now_local,
        window_start=str(sched.get("window_start") or "00:00"),
        window_end=str(sched.get("window_end") or "01:00"),
    ):
        return False, "outside_window"
    return True, "ok"


def minutes_budget_left(
    schedule: dict[str, Any] | None,
    *,
    learning_minutes_today: int,
) -> int:
    sched = schedule or {}
    cap = int(sched.get("duration_minutes") or 60)
    return max(0, cap - int(learning_minutes_today or 0))


def validate_daily_window(window_start: str, window_end: str) -> None:
    """校验 HH:MM 格式；允许任意时段与跨午夜，开始与结束不可相同。"""
    sh, sm = _parse_hhmm(window_start)
    eh, em = _parse_hhmm(window_end)
    start_m = sh * 60 + sm
    end_m = eh * 60 + em
    if start_m == end_m:
        raise ValueError("window_start 与 window_end 不能相同")
