"""Model Version Endpoints."""

import logging
from typing import Annotated

from fastapi import APIRouter, HTTPException, Query, Request

from backend.web.core.auth import AdminTokenDep, ModelVersionRepoDep
from backend.web.schemas.admin import (
    ModelVersionCreateRequest,
    ModelVersionUpdateRequest,
    ModelVersionItem,
    ModelVersionListResponse,
    ModelVersionDetailResponse,
    ModelVersionResponse,
    ActiveModelResponse,
)

from ._utils import _validate_uuid

logger = logging.getLogger(__name__)


def register_model_routes(router: APIRouter) -> None:
    """Register model version endpoints on the router."""

    @router.post(
        "/models",
        response_model=ModelVersionResponse,
        summary="Create model version",
        description="Register a new model version for deployment.",
    )
    async def create_model_version(
        request: ModelVersionCreateRequest,
        admin_token: AdminTokenDep,
        models: ModelVersionRepoDep,
    ) -> ModelVersionResponse:
        """Create a new model version."""
        if request.task_id:
            _validate_uuid(request.task_id, "task_id")
        if request.dataset_id:
            _validate_uuid(request.dataset_id, "dataset_id")

        model = models.create(
            version=request.version,
            name=request.name,
            model_path=request.model_path,
            description=request.description,
            task_id=request.task_id,
            dataset_id=request.dataset_id,
            metrics_mAP=request.metrics_mAP,
            metrics_precision=request.metrics_precision,
            metrics_recall=request.metrics_recall,
            document_count=request.document_count,
            training_config=request.training_config,
            file_size=request.file_size,
            trained_at=request.trained_at,
        )

        return ModelVersionResponse(
            version_id=str(model.version_id),
            status=model.status,
            message="Model version created successfully",
        )

    @router.get(
        "/models",
        response_model=ModelVersionListResponse,
        summary="List model versions",
    )
    async def list_model_versions(
        admin_token: AdminTokenDep,
        models: ModelVersionRepoDep,
        status: Annotated[str | None, Query(description="Filter by status")] = None,
        limit: Annotated[int, Query(ge=1, le=100)] = 20,
        offset: Annotated[int, Query(ge=0)] = 0,
    ) -> ModelVersionListResponse:
        """List model versions with optional status filter."""
        model_list, total = models.get_paginated(status=status, limit=limit, offset=offset)
        return ModelVersionListResponse(
            total=total,
            limit=limit,
            offset=offset,
            models=[
                ModelVersionItem(
                    version_id=str(m.version_id),
                    version=m.version,
                    name=m.name,
                    status=m.status,
                    is_active=m.is_active,
                    model_type=getattr(m, "model_type", "base"),
                    base_model_version_id=str(m.base_model_version_id) if getattr(m, "base_model_version_id", None) else None,
                    gating_status=getattr(m, "gating_status", "pending"),
                    metrics_mAP=m.metrics_mAP,
                    document_count=m.document_count,
                    trained_at=m.trained_at,
                    activated_at=m.activated_at,
                    created_at=m.created_at,
                )
                for m in model_list
            ],
        )

    @router.get(
        "/models/active",
        response_model=ActiveModelResponse,
        summary="Get active model",
        description="Get the currently active model for inference.",
    )
    async def get_active_model(
        admin_token: AdminTokenDep,
        models: ModelVersionRepoDep,
    ) -> ActiveModelResponse:
        """Get the currently active model version."""
        model = models.get_active()
        if not model:
            return ActiveModelResponse(has_active_model=False, model=None)

        return ActiveModelResponse(
            has_active_model=True,
            model=ModelVersionItem(
                version_id=str(model.version_id),
                version=model.version,
                name=model.name,
                status=model.status,
                is_active=model.is_active,
                model_type=getattr(model, "model_type", "base"),
                base_model_version_id=str(model.base_model_version_id) if getattr(model, "base_model_version_id", None) else None,
                gating_status=getattr(model, "gating_status", "pending"),
                metrics_mAP=model.metrics_mAP,
                document_count=model.document_count,
                trained_at=model.trained_at,
                activated_at=model.activated_at,
                created_at=model.created_at,
            ),
        )

    @router.get(
        "/models/{version_id}",
        response_model=ModelVersionDetailResponse,
        summary="Get model version detail",
    )
    async def get_model_version(
        version_id: str,
        admin_token: AdminTokenDep,
        models: ModelVersionRepoDep,
    ) -> ModelVersionDetailResponse:
        """Get detailed model version information."""
        _validate_uuid(version_id, "version_id")
        model = models.get(version_id)
        if not model:
            raise HTTPException(status_code=404, detail="Model version not found")

        return ModelVersionDetailResponse(
            version_id=str(model.version_id),
            version=model.version,
            name=model.name,
            description=model.description,
            model_path=model.model_path,
            status=model.status,
            is_active=model.is_active,
            model_type=getattr(model, "model_type", "base"),
            base_model_version_id=str(model.base_model_version_id) if getattr(model, "base_model_version_id", None) else None,
            base_training_dataset_id=str(model.base_training_dataset_id) if getattr(model, "base_training_dataset_id", None) else None,
            gating_status=getattr(model, "gating_status", "pending"),
            task_id=str(model.task_id) if model.task_id else None,
            dataset_id=str(model.dataset_id) if model.dataset_id else None,
            metrics_mAP=model.metrics_mAP,
            metrics_precision=model.metrics_precision,
            metrics_recall=model.metrics_recall,
            document_count=model.document_count,
            training_config=model.training_config,
            file_size=model.file_size,
            trained_at=model.trained_at,
            activated_at=model.activated_at,
            created_at=model.created_at,
            updated_at=model.updated_at,
        )

    @router.patch(
        "/models/{version_id}",
        response_model=ModelVersionResponse,
        summary="Update model version",
    )
    async def update_model_version(
        version_id: str,
        request: ModelVersionUpdateRequest,
        admin_token: AdminTokenDep,
        models: ModelVersionRepoDep,
    ) -> ModelVersionResponse:
        """Update model version metadata."""
        _validate_uuid(version_id, "version_id")
        model = models.update(
            version_id=version_id,
            name=request.name,
            description=request.description,
            status=request.status,
        )
        if not model:
            raise HTTPException(status_code=404, detail="Model version not found")

        return ModelVersionResponse(
            version_id=str(model.version_id),
            status=model.status,
            message="Model version updated successfully",
        )

    @router.post(
        "/models/{version_id}/activate",
        response_model=ModelVersionResponse,
        summary="Activate model version",
        description="Activate a model version for inference (deactivates all others).",
    )
    async def activate_model_version(
        version_id: str,
        request: Request,
        admin_token: AdminTokenDep,
        models: ModelVersionRepoDep,
    ) -> ModelVersionResponse:
        """Activate a model version for inference."""
        _validate_uuid(version_id, "version_id")

        # Check gating status before activation (for fine-tuned models)
        pre_check = models.get(version_id)
        if not pre_check:
            raise HTTPException(status_code=404, detail="Model version not found")
        model_type = getattr(pre_check, "model_type", "base")
        gating_status = getattr(pre_check, "gating_status", "skipped")
        if model_type == "finetune":
            if gating_status == "reject":
                raise HTTPException(
                    status_code=400,
                    detail="Model failed deployment gating validation. Cannot activate a rejected model.",
                )
            if gating_status == "pending":
                raise HTTPException(
                    status_code=400,
                    detail="Model gating validation not yet completed. Wait for validation to finish.",
                )

        model = models.activate(version_id)
        if not model:
            raise HTTPException(status_code=404, detail="Model version not found")

        # Trigger model reload in inference service
        inference_service = getattr(request.app.state, "inference_service", None)
        model_reloaded = False
        if inference_service:
            try:
                model_reloaded = inference_service.reload_model()
                if model_reloaded:
                    logger.info(f"Inference model reloaded to version {model.version}")
            except Exception as e:
                logger.warning(f"Failed to reload inference model: {e}")

        message = "Model version activated for inference"
        if model_reloaded:
            message += " (model reloaded)"
        if gating_status == "review":
            message += " (WARNING: gating status is REVIEW - manual inspection recommended)"

        return ModelVersionResponse(
            version_id=str(model.version_id),
            status=model.status,
            message=message,
        )

    @router.post(
        "/models/{version_id}/deactivate",
        response_model=ModelVersionResponse,
        summary="Deactivate model version",
    )
    async def deactivate_model_version(
        version_id: str,
        admin_token: AdminTokenDep,
        models: ModelVersionRepoDep,
    ) -> ModelVersionResponse:
        """Deactivate a model version."""
        _validate_uuid(version_id, "version_id")
        model = models.deactivate(version_id)
        if not model:
            raise HTTPException(status_code=404, detail="Model version not found")

        return ModelVersionResponse(
            version_id=str(model.version_id),
            status=model.status,
            message="Model version deactivated",
        )

    @router.post(
        "/models/{version_id}/archive",
        response_model=ModelVersionResponse,
        summary="Archive model version",
    )
    async def archive_model_version(
        version_id: str,
        admin_token: AdminTokenDep,
        models: ModelVersionRepoDep,
    ) -> ModelVersionResponse:
        """Archive a model version."""
        _validate_uuid(version_id, "version_id")
        model = models.archive(version_id)
        if not model:
            raise HTTPException(
                status_code=400,
                detail="Model version not found or cannot archive active model",
            )

        return ModelVersionResponse(
            version_id=str(model.version_id),
            status=model.status,
            message="Model version archived",
        )

    @router.delete(
        "/models/{version_id}",
        summary="Delete model version",
    )
    async def delete_model_version(
        version_id: str,
        admin_token: AdminTokenDep,
        models: ModelVersionRepoDep,
    ) -> dict:
        """Delete a model version."""
        _validate_uuid(version_id, "version_id")
        success = models.delete(version_id)
        if not success:
            raise HTTPException(
                status_code=400,
                detail="Model version not found or cannot delete active model",
            )

        return {"message": "Model version deleted"}

    @router.post(
        "/models/reload",
        summary="Reload inference model",
        description="Reload the inference model from the currently active model version.",
    )
    async def reload_inference_model(
        request: Request,
        admin_token: AdminTokenDep,
    ) -> dict:
        """Reload the inference model from active version."""
        inference_service = getattr(request.app.state, "inference_service", None)
        if not inference_service:
            raise HTTPException(
                status_code=500,
                detail="Inference service not available",
            )

        try:
            model_reloaded = inference_service.reload_model()
            if model_reloaded:
                logger.info("Inference model manually reloaded")
                return {"message": "Model reloaded successfully", "reloaded": True}
            else:
                return {"message": "Model already up to date", "reloaded": False}
        except Exception as e:
            logger.error(f"Failed to reload model: {e}")
            raise HTTPException(
                status_code=500,
                detail=f"Failed to reload model: {e}",
            )
