from __future__ import annotations

import hmac
import os
from typing import Any

from fastapi import Depends, FastAPI, Header, HTTPException
from pydantic import BaseModel, Field

from .installer import ArtifactInstallError, ArtifactInstaller


class ArtifactComponent(BaseModel):
    component_type: str
    object_key: str
    sha256: str
    size_bytes: int = Field(ge=0)


class InstallRequest(BaseModel):
    job_id: str
    model_group: str
    model_version: str
    components: list[ArtifactComponent]


class UninstallRequest(BaseModel):
    job_id: str
    model_group: str
    model_version: str


app = FastAPI(title="Rail UAV Model Artifact Installer", version="0.1.0")
installer = ArtifactInstaller()


def authorize(x_artifact_token: str | None = Header(default=None)) -> None:
    expected = os.getenv("RAIL_ARTIFACT_INSTALLER_TOKEN", "local-artifact-token")
    if expected and (x_artifact_token is None or not hmac.compare_digest(x_artifact_token, expected)):
        raise HTTPException(status_code=401, detail="安装代理认证失败")


@app.get("/health")
def health() -> dict[str, str]:
    return {"status": "ok"}


@app.get("/api/v1/artifacts/status", dependencies=[Depends(authorize)])
def status() -> dict[str, Any]:
    return installer.status()


@app.post("/api/v1/artifacts/install", dependencies=[Depends(authorize)])
def install(request: InstallRequest) -> dict[str, Any]:
    try:
        return installer.install(
            request.job_id,
            request.model_group,
            request.model_version,
            [item.model_dump() for item in request.components],
        )
    except ArtifactInstallError as exc:
        raise HTTPException(status_code=422, detail=str(exc)) from exc


@app.post("/api/v1/artifacts/uninstall", dependencies=[Depends(authorize)])
def uninstall(request: UninstallRequest) -> dict[str, Any]:
    try:
        return installer.uninstall(request.model_group, request.model_version)
    except ArtifactInstallError as exc:
        raise HTTPException(status_code=409, detail=str(exc)) from exc
