"""Champion/Challenger Model Registry with Manual Promotion Governance."""
from __future__ import annotations

import json
import uuid
from datetime import datetime, timezone
from typing import Any, Optional

from backend.app.audit.logger import audit_logger
from backend.app.database.session import db_manager


class ModelRegistry:
    """Manages AI model lifecycle, metadata, performance history, and promotion governance."""

    def __init__(self) -> None:
        self._init_default_models()

    def _init_default_models(self) -> None:
        """Seed registry with initial Champion and Challenger models if not present."""
        existing = db_manager.execute_read_one("SELECT id FROM models WHERE version = ?", ("champion_v1.0",))
        if not existing:
            now = datetime.now(timezone.utc).isoformat()
            metrics = {
                "accuracy": 0.584,
                "brier_score": 0.221,
                "sharpe": 1.42,
                "features": ["rsi_14", "macd_hist", "ema_9_diff", "atr_pct", "bb_bandwidth"],
            }
            db_manager.execute_write(
                """
                INSERT INTO models (id, version, algorithm, status, brier_score, val_accuracy, metrics_json, artifact_path, trained_at, promoted_at)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                """,
                (
                    str(uuid.uuid4()),
                    "champion_v1.0",
                    "LogisticRegression_Calibrated",
                    "CHAMPION",
                    0.221,
                    0.584,
                    json.dumps(metrics),
                    "models/champion_v1.0.joblib",
                    now,
                    now,
                ),
            )

    def get_champion(self) -> Optional[dict[str, Any]]:
        """Fetch active production champion model."""
        return db_manager.execute_read_one("SELECT * FROM models WHERE status = 'CHAMPION'")

    def list_models(self) -> list[dict[str, Any]]:
        """List all registered models across Champion, Challenger, and Retired statuses."""
        return db_manager.execute_read_all("SELECT * FROM models ORDER BY trained_at DESC")

    def register_challenger(
        self,
        version: str,
        algorithm: str,
        brier_score: float,
        val_accuracy: float,
        metrics: dict[str, Any],
        artifact_path: str,
    ) -> str:
        """Register a newly trained model candidate as a CHALLENGER (never automatically promoted)."""
        model_id = str(uuid.uuid4())
        now = datetime.now(timezone.utc).isoformat()
        db_manager.execute_write(
            """
            INSERT INTO models (id, version, algorithm, status, brier_score, val_accuracy, metrics_json, artifact_path, trained_at, promoted_at)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            """,
            (
                model_id,
                version,
                algorithm,
                "CHALLENGER",
                brier_score,
                val_accuracy,
                json.dumps(metrics),
                artifact_path,
                now,
                None,
            ),
        )
        audit_logger.info("Registered new model CHALLENGER: %s (Brier: %s)", version, brier_score)
        return model_id

    def promote_challenger(self, version: str, authorized_by: str = "ADMIN") -> bool:
        """Promote a challenger to champion with mandatory human administrator approval."""
        challenger = db_manager.execute_read_one("SELECT * FROM models WHERE version = ?", (version,))
        if not challenger:
            raise ValueError(f"Model version {version} not found.")

        if challenger["status"] == "CHAMPION":
            return True

        now = datetime.now(timezone.utc).isoformat()
        # Retire previous champion
        db_manager.execute_write(
            "UPDATE models SET status = 'RETIRED' WHERE status = 'CHAMPION'"
        )
        # Promote candidate
        db_manager.execute_write(
            "UPDATE models SET status = 'CHAMPION', promoted_at = ? WHERE version = ?",
            (now, version),
        )
        audit_logger.critical("MODEL PROMOTED TO CHAMPION: %s by %s at %s", version, authorized_by, now)
        return True

    def rollback(self, previous_version: str, authorized_by: str = "ADMIN") -> bool:
        """Rollback production model to an earlier retired version."""
        return self.promote_challenger(previous_version, authorized_by=f"ROLLBACK_{authorized_by}")


model_registry = ModelRegistry()
