from __future__ import annotations

from typing import TYPE_CHECKING, Any

from fastapi import APIRouter
from pydantic import BaseModel

if TYPE_CHECKING:
    from niannian.client import NianNian

from niannian.storage.cloud_tier import CloudTierRouter
from niannian.storage.local_degraded import PendingUploadQueue
from niannian.storage.ops_error_log import OpsErrorLog
from niannian.storage.reconcile_report import ReconcileReporter, read_report


class ReconcileAckBody(BaseModel):
    acknowledged: bool = True


class OpsErrorAckBody(BaseModel):
    error_id: str | None = None
    code: str | None = None
    ack_all: bool = False


def _tier_router(nn: NianNian) -> CloudTierRouter | None:
    cloud = nn._store.cloud
    return cloud if isinstance(cloud, CloudTierRouter) else None


def create_tier_ops_router(nn: NianNian) -> APIRouter:
    router = APIRouter(prefix="/v1/tier", tags=["tier-ops"])
    cfg = nn._config
    ops_cfg = ((cfg.get("storage") or {}).get("tier") or {}).get("ops") or {}
    preview_limit = int(ops_cfg.get("expose_queue_preview", 20))

    @router.get("/ops")
    def tier_ops() -> dict[str, Any]:
        cloud = _tier_router(nn)
        reporter = ReconcileReporter(nn._home, cfg)
        queue = PendingUploadQueue(nn._home)
        preview = []
        for row in queue.read_all()[:preview_limit]:
            preview.append(
                {
                    "rel_path": row.get("rel_path"),
                    "at": row.get("at"),
                    "size": len(str(row.get("data_b64") or "")),
                }
            )
        tier = {}
        if cloud is not None:
            from niannian.storage.cloud_mirror import read_mirror_state

            tier = cloud.tier_summary(read_mirror_state(nn._home), live_probe=False)
        return {
            "tier": {
                "active_role": tier.get("active_role"),
                "pending_uploads": queue.pending_count(),
                "queue_path": "sync/pending_uploads.jsonl",
                "queue_preview": preview,
            },
            "reconcile": reporter.health_summary(),
            "ops_errors": OpsErrorLog(nn._home, config=cfg).summary(),
        }

    @router.get("/ops/errors")
    def tier_ops_errors(limit: int = 50, unresolved_only: bool = False) -> dict[str, Any]:
        log = OpsErrorLog(nn._home, config=cfg)
        return {
            "summary": log.summary(),
            "errors": log.recent(limit=min(limit, 200), unresolved_only=unresolved_only),
        }

    @router.post("/ops/errors/ack")
    def tier_ops_errors_ack(body: OpsErrorAckBody) -> dict[str, Any]:
        log = OpsErrorLog(nn._home, config=cfg)
        if body.ack_all:
            count = log.acknowledge_all()
        else:
            count = log.acknowledge(error_id=body.error_id, code=body.code)
        return {"ok": True, "acknowledged": count, "summary": log.summary()}

    @router.get("/reconcile")
    def tier_reconcile_report() -> dict[str, Any]:
        return read_report(nn._home, cfg)

    @router.post("/reconcile/ack")
    def tier_reconcile_ack(body: ReconcileAckBody) -> dict[str, Any]:
        reporter = ReconcileReporter(nn._home, cfg)
        if body.acknowledged:
            report = reporter.acknowledge()
            return {"ok": True, "reconcile": report}
        return {"ok": False, "error": "only acknowledged=true supported"}

    @router.post("/pending/drain")
    def tier_pending_drain() -> dict[str, Any]:
        cloud = _tier_router(nn)
        if cloud is None:
            return {"ok": False, "error": "not_tiered_mode"}
        report = cloud.pending_queue.drain(cloud)
        return {"ok": report.ok, "drained": report.drained, "errors": report.errors or []}

    return router
