from __future__ import annotations

import copy
from typing import TYPE_CHECKING, Any

from fastapi import APIRouter
from pydantic import BaseModel, Field

if TYPE_CHECKING:
    from niannian.client import NianNian


class ConfigPatch(BaseModel):
    api: dict[str, Any] | None = None
    chat: dict[str, Any] | None = None
    trace: dict[str, Any] | None = None
    runtime: dict[str, Any] | None = None
    vault: dict[str, Any] | None = None


def _deep_update(target: dict[str, Any], patch: dict[str, Any]) -> None:
    for key, val in patch.items():
        if isinstance(val, dict) and isinstance(target.get(key), dict):
            _deep_update(target[key], val)
        else:
            target[key] = val


def create_config_router(nn: NianNian) -> APIRouter:
    router = APIRouter(prefix="/v1/config", tags=["config"])

    @router.get("")
    def get_config():
        cfg = copy.deepcopy(nn._config)
        return cfg

    @router.patch("")
    def patch_config(payload: ConfigPatch):
        updated: dict[str, Any] = {}
        for key in ("api", "chat", "trace", "runtime", "vault"):
            val = getattr(payload, key)
            if val is not None:
                if key == "vault":
                    nn._config.setdefault("vault", {})
                    _deep_update(nn._config["vault"], val)
                else:
                    nn._config.setdefault(key, {}).update(val)
                updated[key] = val
        return {"updated": updated, "config": nn._config}

    @router.get("/providers")
    def get_providers():
        from niannian.config import load_providers_config

        raw = load_providers_config()
        masked = _mask_providers(raw)
        return masked

    return router


def _mask_providers(data: dict[str, Any]) -> dict[str, Any]:
    out: dict[str, Any] = {}
    for k, v in data.items():
        if isinstance(v, dict):
            out[k] = {sk: _mask_value(sv) for sk, sv in v.items()}
        else:
            out[k] = _mask_value(v)
    return out


def _mask_value(val: Any) -> Any:
    if isinstance(val, str) and len(val) > 8:
        return val[:4] + "***" + val[-2:]
    return val
