"""Manifest domain — HTTP routes."""
from __future__ import annotations

from typing import Any, Optional
from uuid import UUID

from fastapi import APIRouter, Depends, Query
from sqlalchemy.ext.asyncio import AsyncSession

from src.core.database import get_db
from src.core.dependencies import require_active_billing_for_project_id
from src.domain.auth.models import User
from src.domain.auth.router import get_current_user
from src.domain.manifest.repository import ManifestRunRepository
from src.domain.manifest.schemas import (
    CompleteRunRequest,
    FailRunRequest,
    ManifestResponse,
    ManifestRunResponse,
    RunTokenResponse,
    StartRunRequest,
)
from src.domain.manifest.service import ManifestService

router = APIRouter(
    prefix="/api/projects/{project_id}",
    tags=["manifest"],
)


def _get_service(db: AsyncSession = Depends(get_db)) -> ManifestService:
    return ManifestService(db=db, run_repo=ManifestRunRepository(db))


# ── Manifest endpoints ────────────────────────────────────────────────────────

@router.get("/manifest", response_model=ManifestResponse)
async def get_manifest(
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    sections: Optional[str] = Query(None, description="Comma-separated section names"),
    compact: bool = Query(False),
    svc: ManifestService = Depends(_get_service),
) -> ManifestResponse:
    section_list = [s.strip() for s in sections.split(",")] if sections else None
    return await svc.get_manifest(project_id, sections=section_list, compact=compact)


@router.get("/manifest/diff", response_model=dict)
async def get_manifest_diff(
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    since: UUID = Query(..., description="Run ID to diff against"),
    svc: ManifestService = Depends(_get_service),
) -> Any:
    return await svc.get_manifest_diff(project_id, since)


# ── Codegen Run endpoints ─────────────────────────────────────────────────────

@router.post("/codegen-runs", response_model=RunTokenResponse, status_code=201)
async def start_run(
    body: StartRunRequest,
    project_id: UUID = Depends(require_active_billing_for_project_id),
    user: User = Depends(get_current_user),
    svc: ManifestService = Depends(_get_service),
) -> RunTokenResponse:
    return await svc.start_run(project_id, user.id, body.requested_scopes)


@router.get("/codegen-runs", response_model=list[ManifestRunResponse])
async def list_runs(
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    limit: int = Query(20, ge=1, le=100),
    offset: int = Query(0, ge=0),
    svc: ManifestService = Depends(_get_service),
) -> list[ManifestRunResponse]:
    return await svc.list_runs(project_id, limit=limit, offset=offset)


@router.post("/codegen-runs/{run_id}/complete", response_model=ManifestRunResponse)
async def complete_run(
    run_id: UUID,
    body: CompleteRunRequest,
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    svc: ManifestService = Depends(_get_service),
) -> ManifestRunResponse:
    return await svc.complete_run(project_id, run_id, body.manifest_snapshot_hash)


@router.post("/codegen-runs/{run_id}/fail", response_model=ManifestRunResponse)
async def fail_run(
    run_id: UUID,
    body: FailRunRequest,
    project_id: UUID = Depends(require_active_billing_for_project_id),
    _: User = Depends(get_current_user),
    svc: ManifestService = Depends(_get_service),
) -> ManifestRunResponse:
    return await svc.fail_run(project_id, run_id, body.reason)
