"""Instructions and prompts - FastAPI router."""
from typing import Optional
from uuid import UUID

from fastapi import APIRouter, Depends, Path, Response

from pydantic import BaseModel
from sqlalchemy.ext.asyncio import AsyncSession

from src.core.database import get_db
from src.core.dependencies import (
    add_deprecation_header,
    get_productive_access_policy,
    require_active_billing_for_project,
)
from src.domain.auth.models import User
from src.domain.auth.router import get_current_user
from src.domain.billing.productive_access_policy import ProductiveAccessPolicy
from src.domain.instructions.repository import InstructionRepository, PromptRepository, PromptSessionRepository
from src.domain.instructions.disk_mirror import mirror_instruction_to_meta
from src.domain.projects.repository import ProjectRepository
from src.domain.workspaces.repository import MembershipRepository, WorkspaceRepository
from src.domain.workspaces.facades import WorkspaceFacadeImpl

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


async def get_workspace_facade(db: AsyncSession = Depends(get_db)) -> WorkspaceFacadeImpl:
    return WorkspaceFacadeImpl(WorkspaceRepository(db), MembershipRepository(db))


async def check_project_access(project_id: UUID, user_id: UUID, db: AsyncSession) -> bool:
    facade = WorkspaceFacadeImpl(WorkspaceRepository(db), MembershipRepository(db))
    proj = await ProjectRepository(db).get_by_id(project_id)
    return proj and await facade.check_permission(proj.workspace_id, user_id, "instructions.manage")


@router.get("/projects/{project}/instructions")
async def get_instructions(
    project: UUID = Depends(require_active_billing_for_project),
    user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """Get current instruction content."""
    if not await check_project_access(project, user.id, db):
        from src.core.exceptions import ForbiddenError
        raise ForbiddenError()
    content = await InstructionRepository(db).get_current_content(project)
    return {"content": content}


class InstructionVersionCreate(BaseModel):
    content: str


@router.post("/projects/{project}/instructions/versions")
async def create_instruction_version(
    body: InstructionVersionCreate,
    project: UUID = Depends(require_active_billing_for_project),
    user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """Create new instruction version."""
    if not await check_project_access(project, user.id, db):
        from src.core.exceptions import ForbiddenError
        raise ForbiddenError()
    repo = InstructionRepository(db)
    v = await repo.create_version(project, body.content, user.id)
    await repo.set_current(project, v.id)
    proj_row = await ProjectRepository(db).get_by_id(project)
    if proj_row:
        mirror_instruction_to_meta(proj_row.workspace_id, project, body.content)
    return {"id": str(v.id), "version_number": v.version_number}


class PromptCreate(BaseModel):
    content: str
    context: Optional[dict] = None


@router.post("/projects/{project}/prompt-sessions")
async def create_prompt_session(
    project: UUID = Depends(require_active_billing_for_project),
    title: Optional[str] = None,
    user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """Create prompt session."""
    if not await check_project_access(project, user.id, db):
        from src.core.exceptions import ForbiddenError
        raise ForbiddenError()
    s = await PromptSessionRepository(db).create(project, user.id, title)
    return {"id": str(s.id), "project_id": str(s.project_id), "title": s.title}


@router.post(
    "/prompt-sessions/{session}/prompts",
    deprecated=True,
    summary="Deprecated: use POST /api/projects/{project_id}/prompt/submit",
)
async def add_prompt(
    response: Response,
    body: PromptCreate,
    session: UUID = Path(...),
    user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
    policy: ProductiveAccessPolicy = Depends(get_productive_access_policy),
):
    """Add prompt to session. Deprecated: prefer project-rooted prompt/submit."""
    add_deprecation_header(response, "POST /api/projects/{project_id}/prompt/submit")
    sess = await PromptSessionRepository(db).get_by_id(session)
    if not sess:
        from src.core.exceptions import NotFoundError
        raise NotFoundError("Session not found")
    proj = await ProjectRepository(db).get_by_id(sess.project_id)
    if not proj:
        raise NotFoundError("Project not found")
    await policy.require_for_workspace(proj.workspace_id, user.id)
    if not await check_project_access(sess.project_id, user.id, db):
        from src.core.exceptions import ForbiddenError
        raise ForbiddenError()
    p = await PromptRepository(db).create(session, body.content, user.id, body.context)
    return {"id": str(p.id), "content": p.content, "context": p.context}


@router.get(
    "/prompt-sessions/{session}",
    deprecated=True,
    summary="Deprecated: use GET /api/projects/{project_id}/workspace",
)
async def get_prompt_session(
    response: Response,
    session: UUID = Path(...),
    user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
    policy: ProductiveAccessPolicy = Depends(get_productive_access_policy),
):
    """Get session with prompts. Deprecated: prefer workspace hydrate."""
    add_deprecation_header(response, "GET /api/projects/{project_id}/workspace")
    sess = await PromptSessionRepository(db).get_by_id(session)
    if not sess:
        from src.core.exceptions import NotFoundError
        raise NotFoundError("Session not found")
    proj = await ProjectRepository(db).get_by_id(sess.project_id)
    if not proj:
        raise NotFoundError("Project not found")
    await policy.require_for_workspace(proj.workspace_id, user.id)
    if not await check_project_access(sess.project_id, user.id, db):
        from src.core.exceptions import ForbiddenError
        raise ForbiddenError()
    prompts = await PromptRepository(db).list_for_session(session)
    return {
        "id": str(sess.id),
        "project_id": str(sess.project_id),
        "prompts": [{"id": str(p.id), "content": p.content, "context": p.context} for p in prompts],
    }
