from __future__ import annotations

from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from starlette.responses import PlainTextResponse

from api.database import get_session
from api.schemas.recently_on_scope import (
    RecentlyOnScopeGenerate,
    RecentlyOnScopeGeneratedReport,
    RecentlyOnScopeHourlyGenerate,
    RecentlyOnScopeHourlyRun,
    RecentlyOnScopeReportMetadata,
)
from api.services.markitect_templates import MarkitectRenderError, MarkitectUnavailable
from api.services.recently_on_scope import (
    generate_report,
    generate_hourly_reports,
    list_reports,
    read_report,
    resolve_window,
)

router = APIRouter(prefix="/domains/{slug}/recently-on-scope", tags=["recently-on-scope"])
hourly_router = APIRouter(prefix="/recently-on-scope", tags=["recently-on-scope"])


@hourly_router.post("/hourly", response_model=RecentlyOnScopeHourlyRun, status_code=status.HTTP_201_CREATED)
async def generate_hourly_recently_on_scope(
    body: RecentlyOnScopeHourlyGenerate,
    session: AsyncSession = Depends(get_session),
) -> RecentlyOnScopeHourlyRun:
    try:
        window = resolve_window(body.range, body.since, body.until)
        return await generate_hourly_reports(
            session,
            window,
            active_only=body.active_only,
            include_attention=body.include_attention,
        )
    except ValueError as exc:
        raise HTTPException(status_code=422, detail=str(exc)) from exc


@router.post("/", response_model=RecentlyOnScopeGeneratedReport, status_code=status.HTTP_201_CREATED)
async def generate_recently_on_scope(
    slug: str,
    body: RecentlyOnScopeGenerate,
    session: AsyncSession = Depends(get_session),
) -> RecentlyOnScopeGeneratedReport:
    try:
        window = resolve_window(body.range, body.since, body.until)
        metadata, markdown = await generate_report(session, slug, window)
    except ValueError as exc:
        raise HTTPException(status_code=422, detail=str(exc)) from exc
    except MarkitectUnavailable as exc:
        raise HTTPException(status_code=503, detail=str(exc)) from exc
    except MarkitectRenderError as exc:
        raise HTTPException(status_code=500, detail=str(exc)) from exc
    return RecentlyOnScopeGeneratedReport(**metadata.model_dump(), markdown=markdown)


@router.get("/", response_model=list[RecentlyOnScopeReportMetadata])
async def list_recently_on_scope(slug: str) -> list[RecentlyOnScopeReportMetadata]:
    return list_reports(slug)


@router.get("/{report_id}", response_class=PlainTextResponse)
async def get_recently_on_scope_report(slug: str, report_id: str) -> PlainTextResponse:
    try:
        markdown = read_report(slug, report_id)
    except FileNotFoundError as exc:
        raise HTTPException(status_code=404, detail="Report not found") from exc
    return PlainTextResponse(markdown, media_type="text/markdown")
