import re
import uuid

from fastapi import APIRouter, Depends, HTTPException

from app.api.deps import get_current_principal, get_project_or_404, require_role
from app.db.session import get_db
from app.models.org import User, UserRole
from app.models.prompt import Prompt
from app.models.stubs import AIModel, ModelVersion
from app.schemas.model import AIModelOut, CreateModelRequest, ModelVersionOut, OllamaModelOut, PullModelRequest
from app.services import ollama_client
from app.workers.model_tasks import create_model_task, pull_model_task
from sqlalchemy.orm import Session

router = APIRouter(prefix="/models", tags=["models"])


def _sanitize_tag(name: str) -> str:
    slug = re.sub(r"[^a-z0-9._-]+", "-", name.lower()).strip("-")
    return f"jozie-{slug}"


@router.get("/ollama", response_model=list[OllamaModelOut])
def list_ollama_models(current_user: User = Depends(get_current_principal)):
    models = ollama_client.list_models()
    return [
        OllamaModelOut(name=m["name"], size=m.get("size"), modified_at=m.get("modified_at"), digest=m.get("digest"))
        for m in models
    ]


@router.post("/ollama/pull", status_code=202)
def pull_ollama_model(payload: PullModelRequest, current_user: User = Depends(require_role(UserRole.editor))):
    pull_model_task.delay(payload.tag)
    return {"status": "queued", "job_id": f"pull:{payload.tag}"}


@router.post("/ollama/delete", status_code=204)
def delete_ollama_model(payload: PullModelRequest, current_user: User = Depends(require_role(UserRole.admin))):
    try:
        ollama_client.delete_model(payload.tag)
    except Exception as exc:  # noqa: BLE001
        raise HTTPException(status_code=400, detail=f"Could not delete {payload.tag}: {exc}") from exc


@router.post("/create", status_code=202)
def create_model(
    payload: CreateModelRequest,
    db: Session = Depends(get_db),
    current_user: User = Depends(require_role(UserRole.editor)),
):
    get_project_or_404(payload.project_id, db, current_user)

    system_prompt = payload.system_prompt
    if payload.prompt_id:
        prompt = db.get(Prompt, payload.prompt_id)
        if prompt is None or prompt.org_id != current_user.org_id:
            raise HTTPException(status_code=404, detail="Prompt not found")
        system_prompt = prompt.content

    tag = _sanitize_tag(payload.tag or payload.name)
    job_id = f"create:{tag}"
    create_model_task.delay(
        job_id,
        str(payload.project_id),
        payload.name,
        payload.base_model,
        tag,
        system_prompt,
        payload.parameters,
        str(current_user.id),
    )
    return {"status": "queued", "job_id": job_id, "tag": tag}


@router.get("", response_model=list[AIModelOut])
def list_registered_models(
    project_id: uuid.UUID, db: Session = Depends(get_db), current_user: User = Depends(get_current_principal)
):
    get_project_or_404(project_id, db, current_user)
    models = db.query(AIModel).filter(AIModel.project_id == project_id).order_by(AIModel.created_at.desc()).all()

    result = []
    for model in models:
        versions = (
            db.query(ModelVersion).filter(ModelVersion.model_id == model.id).order_by(ModelVersion.created_at.desc()).all()
        )
        result.append(
            AIModelOut(
                id=model.id,
                project_id=model.project_id,
                name=model.name,
                base_model=model.base_model,
                status=model.status,
                versions=[ModelVersionOut.model_validate(v) for v in versions],
            )
        )
    return result
