import uuid

from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session

from app.api.deps import get_current_principal, require_role
from app.db.session import get_db
from app.models.org import User, UserRole
from app.models.prompt import Prompt, PromptVersion
from app.schemas.prompt import PromptCreate, PromptOut, PromptUpdate, PromptVersionOut

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


def _get_prompt_or_404(prompt_id: uuid.UUID, db: Session, current_user: User) -> Prompt:
    prompt = db.get(Prompt, prompt_id)
    if prompt is None or prompt.org_id != current_user.org_id:
        raise HTTPException(status_code=404, detail="Prompt not found")
    return prompt


@router.get("", response_model=list[PromptOut])
def list_prompts(
    domain: str | None = Query(default=None),
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_principal),
):
    q = db.query(Prompt).filter(Prompt.org_id == current_user.org_id, Prompt.is_active.is_(True))
    if domain:
        q = q.filter(Prompt.domain == domain)
    return q.order_by(Prompt.updated_at.desc()).all()


@router.post("", response_model=PromptOut, status_code=201)
def create_prompt(
    payload: PromptCreate,
    db: Session = Depends(get_db),
    current_user: User = Depends(require_role(UserRole.editor)),
):
    prompt = Prompt(
        org_id=current_user.org_id,
        name=payload.name,
        domain=payload.domain,
        description=payload.description,
        content=payload.content,
        current_version=1,
        created_by=current_user.id,
    )
    db.add(prompt)
    db.flush()
    db.add(PromptVersion(prompt_id=prompt.id, version=1, content=payload.content, created_by=current_user.id))
    db.commit()
    db.refresh(prompt)
    return prompt


@router.get("/{prompt_id}", response_model=PromptOut)
def get_prompt(prompt_id: uuid.UUID, db: Session = Depends(get_db), current_user: User = Depends(get_current_principal)):
    return _get_prompt_or_404(prompt_id, db, current_user)


@router.patch("/{prompt_id}", response_model=PromptOut)
def update_prompt(
    prompt_id: uuid.UUID,
    payload: PromptUpdate,
    db: Session = Depends(get_db),
    current_user: User = Depends(require_role(UserRole.editor)),
):
    prompt = _get_prompt_or_404(prompt_id, db, current_user)

    if payload.name is not None:
        prompt.name = payload.name
    if payload.domain is not None:
        prompt.domain = payload.domain
    if payload.description is not None:
        prompt.description = payload.description
    if payload.is_active is not None:
        prompt.is_active = payload.is_active

    if payload.content is not None and payload.content != prompt.content:
        prompt.content = payload.content
        prompt.current_version += 1
        db.add(
            PromptVersion(
                prompt_id=prompt.id, version=prompt.current_version, content=payload.content, created_by=current_user.id
            )
        )

    db.commit()
    db.refresh(prompt)
    return prompt


@router.get("/{prompt_id}/versions", response_model=list[PromptVersionOut])
def list_versions(prompt_id: uuid.UUID, db: Session = Depends(get_db), current_user: User = Depends(get_current_principal)):
    _get_prompt_or_404(prompt_id, db, current_user)
    return db.query(PromptVersion).filter(PromptVersion.prompt_id == prompt_id).order_by(PromptVersion.version.desc()).all()


@router.delete("/{prompt_id}", status_code=204)
def delete_prompt(
    prompt_id: uuid.UUID, db: Session = Depends(get_db), current_user: User = Depends(require_role(UserRole.admin))
):
    prompt = _get_prompt_or_404(prompt_id, db, current_user)
    db.delete(prompt)
    db.commit()
