"""Task delegation API endpoints."""

from __future__ import annotations

from fastapi import APIRouter, HTTPException, Request
from pydantic import BaseModel

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


class TaskCreateRequest(BaseModel):
    title: str
    brief: str
    mode: str = "review"
    domain: str = "general"
    project: str | None = None  # Defaults to "personal" when omitted.
    assigned_agent: str | None = None  # Specialist key; surfaces in graph.


class TaskStatusRequest(BaseModel):
    status: str


class TaskProgressRequest(BaseModel):
    note: str


class TaskReassignRequest(BaseModel):
    project: str


class TaskRenameRequest(BaseModel):
    title: str


class TaskFeedbackRequest(BaseModel):
    rating: str  # good | needs_improvement | redo
    note: str = ""


class TaskSummary(BaseModel):
    slug: str
    title: str
    status: str
    mode: str
    domain: str
    project: str
    delegated: str
    due: str
    updated_at: str = ""


class TaskDetail(BaseModel):
    slug: str
    content: str
    metadata: dict


@router.get("")
async def list_tasks(
    request: Request,
    status: str | None = None,
    project: str | None = None,
) -> list[TaskSummary]:
    """List tasks across all projects (or a single project)."""
    task_svc = request.app.state.task_service
    tasks = task_svc.list_tasks(status_filter=status, project=project)
    return [TaskSummary(**t) for t in tasks]


@router.post("")
async def create_task(request: Request, body: TaskCreateRequest) -> dict:
    """Create a new delegated task inside a project.

    Defaults to the auto-created 'personal' project if no project slug is given.
    """
    task_svc = request.app.state.task_service
    try:
        path = task_svc.create_task(
            title=body.title,
            brief=body.brief,
            mode=body.mode,
            domain=body.domain,
            project=body.project,
            assigned_agent=body.assigned_agent,
        )
    except FileNotFoundError as exc:
        raise HTTPException(status_code=404, detail=str(exc)) from exc
    return {"path": path, "status": "delegated"}


@router.get("/{slug}")
async def get_task(request: Request, slug: str) -> TaskDetail:
    """Get a task by slug."""
    task_svc = request.app.state.task_service
    doc = task_svc.get_task(slug)
    if not doc:
        raise HTTPException(status_code=404, detail=f"Task not found: {slug}")
    return TaskDetail(slug=slug, content=doc.content, metadata=doc.metadata)


@router.patch("/{slug}/status")
async def update_task_status(
    request: Request, slug: str, body: TaskStatusRequest
) -> dict:
    """Update a task's status."""
    task_svc = request.app.state.task_service
    try:
        task_svc.update_status(slug, body.status)
    except (FileNotFoundError, ValueError) as exc:
        raise HTTPException(status_code=400, detail=str(exc)) from exc
    return {"slug": slug, "status": body.status}


@router.put("/{slug}/project")
async def reassign_task(
    request: Request, slug: str, body: TaskReassignRequest
) -> dict:
    """Move a task to a different project. Records a user_override event."""
    task_svc = request.app.state.task_service
    try:
        old_project, new_path = task_svc.reassign_project(slug, body.project)
    except (FileNotFoundError, ValueError) as exc:
        raise HTTPException(status_code=400, detail=str(exc)) from exc

    activity = getattr(request.app.state, "activity_logger", None)
    if activity and old_project != body.project:
        activity.log(
            category="user_override",
            action="task_reassigned",
            summary=f"User moved task '{slug}' from '{old_project}' to '{body.project}'",
            details={"slug": slug, "from": old_project, "to": body.project},
            importance="medium",
        )
    return {"slug": slug, "project": body.project, "path": new_path}


@router.post("/{slug}/rename")
async def rename_task(
    request: Request, slug: str, body: TaskRenameRequest
) -> dict:
    """Rename a task: rewrite title and move file if the slug changes."""
    task_svc = request.app.state.task_service
    try:
        result = task_svc.rename_task(slug, body.title)
    except FileNotFoundError as exc:
        raise HTTPException(status_code=404, detail=str(exc)) from exc
    except ValueError as exc:
        raise HTTPException(status_code=400, detail=str(exc)) from exc

    activity = getattr(request.app.state, "activity_logger", None)
    if activity and result["slug"] != slug:
        activity.log(
            category="user_override",
            action="task_renamed",
            summary=f"User renamed task '{slug}' → '{result['slug']}' ('{body.title}')",
            details={"old_slug": slug, "new_slug": result["slug"], "project": result["project"]},
            importance="medium",
        )
    return result


@router.post("/{slug}/progress")
async def add_progress(
    request: Request, slug: str, body: TaskProgressRequest
) -> dict:
    """Add a progress note to a task."""
    task_svc = request.app.state.task_service
    task_svc.add_progress(slug, body.note)
    return {"slug": slug, "status": "ok"}


@router.delete("/{slug}")
async def delete_task(request: Request, slug: str) -> dict:
    """Delete a task permanently."""
    task_svc = request.app.state.task_service
    try:
        project = task_svc.delete_task(slug)
    except FileNotFoundError as exc:
        raise HTTPException(status_code=404, detail=str(exc)) from exc

    activity = getattr(request.app.state, "activity_logger", None)
    if activity:
        activity.log(
            category="user",
            action="task_deleted",
            summary=f"User deleted task '{slug}' from project '{project}'",
            details={"slug": slug, "project": project},
            importance="medium",
        )
    return {"slug": slug, "project": project, "status": "deleted"}


@router.post("/{slug}/feedback")
async def set_feedback(
    request: Request, slug: str, body: TaskFeedbackRequest
) -> dict:
    """Set feedback on a completed task. Triggers trust update."""
    task_svc = request.app.state.task_service
    trust_svc = request.app.state.trust_service

    try:
        feedback = task_svc.set_feedback(slug, body.rating, body.note)
    except (FileNotFoundError, ValueError) as exc:
        raise HTTPException(status_code=400, detail=str(exc)) from exc

    # Feed trust engine
    trust_result = trust_svc.record_feedback(
        domain=feedback["domain"],
        rating=feedback["rating"],
    )

    # Fire-and-forget: refine skills if feedback was negative
    if body.rating != "good":
        import asyncio

        skillschool = request.app.state.skillschool

        async def _refine_skill() -> None:
            try:
                await skillschool.refine_from_feedback(feedback["domain"])
            except Exception:
                pass  # non-critical — don't block response

        asyncio.create_task(_refine_skill())

    return {
        "slug": slug,
        "rating": body.rating,
        "trust_update": trust_result,
    }
