from __future__ import annotations

import pathlib
from dataclasses import dataclass, field
from datetime import datetime, time
from typing import Any
from zoneinfo import ZoneInfo

import yaml

from server.settings import settings


@dataclass
class Med:
    name: str
    dose: str


@dataclass
class Slot:
    id: str
    time: time
    label: str
    meds: list[Med]
    reminder_window_minutes: int = 90


@dataclass
class MedsConfig:
    timezone: ZoneInfo
    slots: list[Slot] = field(default_factory=list)


_config: MedsConfig | None = None


def load_meds_config(path: str | None = None) -> MedsConfig:
    global _config
    if _config is not None:
        return _config
    p = pathlib.Path(path or settings.meds_path)
    raw = yaml.safe_load(p.read_text(encoding="utf-8"))
    tz = ZoneInfo(raw.get("timezone", "Europe/Berlin"))
    slots: list[Slot] = []
    for item in raw.get("slots", []):
        h, m = str(item["time"]).split(":")
        slots.append(
            Slot(
                id=item["id"],
                time=time(int(h), int(m)),
                label=item.get("label", item["id"]),
                meds=[Med(**m) for m in item.get("meds", [])],
                reminder_window_minutes=int(item.get("reminder_window_minutes", 90)),
            )
        )
    _config = MedsConfig(timezone=tz, slots=slots)
    return _config


def reload_meds_config() -> MedsConfig:
    global _config
    _config = None
    return load_meds_config()


def slot_datetime(day: datetime, slot: Slot, tz: ZoneInfo) -> datetime:
    local = day.astimezone(tz) if day.tzinfo else day.replace(tzinfo=tz)
    return local.replace(hour=slot.time.hour, minute=slot.time.minute, second=0, microsecond=0)


def today_str(tz: ZoneInfo) -> str:
    return datetime.now(tz).strftime("%Y-%m-%d")


def slot_to_dict(slot: Slot) -> dict[str, Any]:
    return {
        "id": slot.id,
        "time": slot.time.strftime("%H:%M"),
        "label": slot.label,
        "meds": [{"name": m.name, "dose": m.dose} for m in slot.meds],
        "reminder_window_minutes": slot.reminder_window_minutes,
    }
