from __future__ import annotations

from pathlib import Path
from typing import Optional

import yaml

from .config_schema import RateLimits, TakumiConfig, TierPlan
from .settings import get_gateway_settings


class ConfigStore:
    def __init__(self, path: Optional[str] = None):
        path_value = path if path is not None else get_gateway_settings().config.tiers_path
        self.path = Path(path_value)
        self._cfg: TakumiConfig = self._load()
        self._tiers: dict[str, TierPlan] = {t.name: t for t in self._cfg.tiers}
        self._org_to_tier: dict[str, str] = {o.org_id: o.tier for o in self._cfg.orgs}

    def _load(self) -> TakumiConfig:
        try:
            raw = self.path.read_text(encoding="utf-8")
        except FileNotFoundError as exc:
            raise FileNotFoundError(f"Tier configuration file not found at '{self.path}'.") from exc

        data = yaml.safe_load(raw)
        if not data:
            raise ValueError(f"Tier configuration '{self.path}' is empty or invalid.")

        return TakumiConfig.model_validate(data)

    def reload(self) -> None:
        self._cfg = self._load()
        self._tiers = {t.name: t for t in self._cfg.tiers}
        self._org_to_tier = {o.org_id: o.tier for o in self._cfg.orgs}

    def as_dict(self) -> dict[str, object]:
        return self._cfg.model_dump()

    def tier_for_org(self, org_id: str, default: str = "T1") -> str:
        return self._org_to_tier.get(org_id, default)

    def limits_for(
        self, tier_name: str, provider: Optional[str], model: Optional[str]
    ) -> RateLimits:
        tier = self._tiers.get(tier_name)
        if not tier:
            return RateLimits()
        if provider and model:
            for ov in tier.overrides:
                if ov.provider == provider and ov.model == model:
                    return _merge_limits(tier.defaults, ov.limits)
        return tier.defaults


def _merge_limits(base: RateLimits, override: RateLimits) -> RateLimits:
    return RateLimits(
        rpm=override.rpm if override.rpm is not None else base.rpm,
        tpm=override.tpm if override.tpm is not None else base.tpm,
        itpm=override.itpm if override.itpm is not None else base.itpm,
        otpm=override.otpm if override.otpm is not None else base.otpm,
        concurrency=override.concurrency if override.concurrency is not None else base.concurrency,
    )
