"""API проектов M1."""

from fastapi import APIRouter, HTTPException, Query, Response
from sqlalchemy import select

from app.dependencies import DbDep, UserDep
from app.models import CoinEvent, Project
from app.realtime import publish
from app.schemas import ProjectCreate, ProjectOut, ProjectUpdate
from app.services.xp import coins_for_create, grant_create_xp

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

# «Закрыт» (archived) больше нет — вместо него архив (ТЗ 3.8.1)
VALID_RELEVANCE = {"active", "paused"}


@router.post("", response_model=ProjectOut)
async def create_project(
    schema: ProjectCreate, db: DbDep, user: UserDep, response: Response
) -> Project:
    exists = db.scalars(select(Project).where(Project.name == schema.name)).first()
    if exists is not None:
        raise HTTPException(status_code=409, detail="Project name already exists")
    project = Project(name=schema.name, priority=schema.priority, note=schema.note)
    db.add(project)
    db.flush()
    # Микронаграда за создание (ТЗ 3.13): чуть больше XP, чем за задачу
    grant_create_xp(db, "create_project")
    db.add(CoinEvent(source="create_project", amount=coins_for_create("create_project")))
    response.headers["X-Created-XP"] = "5"
    response.headers["X-Created-Coins"] = "2"
    db.commit()
    publish(str(user["user_id"]), "project.changed", {"id": project.id})
    publish(str(user["user_id"]), "xp.changed", {"celebrate": False})
    return project


@router.get("", response_model=list[ProjectOut])
async def list_projects(db: DbDep, user: UserDep, archived: bool = Query(False)) -> list[Project]:
    """Активные проекты; archived=true — список архива (история)."""
    return list(
        db.scalars(
            select(Project).where(Project.is_archived == archived).order_by(Project.id)
        ).all()
    )


@router.get("/{project_id}", response_model=ProjectOut)
async def get_project(project_id: int, db: DbDep, user: UserDep) -> Project:
    project = db.get(Project, project_id)
    if project is None:
        raise HTTPException(status_code=404, detail="Project not found")
    return project


@router.patch("/{project_id}", response_model=ProjectOut)
async def update_project(
    project_id: int, schema: ProjectUpdate, db: DbDep, user: UserDep
) -> Project:
    project = db.get(Project, project_id)
    if project is None:
        raise HTTPException(status_code=404, detail="Project not found")
    data = schema.model_dump(exclude_unset=True)
    if "relevance_status" in data and data["relevance_status"] not in VALID_RELEVANCE:
        raise HTTPException(
            status_code=422, detail=f"Unknown relevance_status: {data['relevance_status']}"
        )
    for field, value in data.items():
        setattr(project, field, value)
    db.commit()
    publish(str(user["user_id"]), "project.changed", {"id": project.id})
    return project


@router.post("/{project_id}/archive", response_model=ProjectOut)
async def archive_project(project_id: int, db: DbDep, user: UserDep) -> Project:
    """Отправить проект в архив — вместе со всеми его задачами (ТЗ 3.8.1)."""
    project = db.get(Project, project_id)
    if project is None:
        raise HTTPException(status_code=404, detail="Project not found")
    project.is_archived = True
    db.commit()
    publish(str(user["user_id"]), "project.changed", {"id": project.id})
    return project


@router.post("/{project_id}/restore", response_model=ProjectOut)
async def restore_project(project_id: int, db: DbDep, user: UserDep) -> Project:
    """Вернуть проект из архива — со всеми задачами и историей."""
    project = db.get(Project, project_id)
    if project is None:
        raise HTTPException(status_code=404, detail="Project not found")
    project.is_archived = False
    db.commit()
    publish(str(user["user_id"]), "project.changed", {"id": project.id})
    return project


@router.delete("/{project_id}")
async def delete_project(project_id: int, db: DbDep, user: UserDep) -> dict[str, bool]:
    project = db.get(Project, project_id)
    if project is None:
        raise HTTPException(status_code=404, detail="Project not found")
    db.delete(project)
    db.commit()
    publish(str(user["user_id"]), "project.deleted", {"id": project_id})
    return {"ok": True}
