from __future__ import annotations

from fastapi import APIRouter, HTTPException, Query

from api.schemas.pipeline import CreatePipelineRunBody
from api.services.pipeline import (
    cancel_run,
    create_run,
    get_run,
    list_runs,
    pipeline_health,
    resume_run,
    retry_step,
)

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


@router.get("/runs")
def pipeline_runs(
    limit: int = Query(default=50, ge=1, le=200),
    status: str | None = None,
    biz_dt: str | None = Query(default=None, pattern=r"^\d{8}$"),
) -> dict:
    return {"items": list_runs(limit=limit, status=status, biz_dt=biz_dt)}


@router.post("/runs", status_code=202)
def create_pipeline_run(body: CreatePipelineRunBody | None = None) -> dict:
    payload = body or CreatePipelineRunBody()
    return create_run(
        biz_dt=payload.biz_dt,
        source="api",
        reason=payload.reason,
    )


@router.get("/runs/{run_id}")
def pipeline_run_detail(run_id: str) -> dict:
    result = get_run(run_id)
    if result is None:
        raise HTTPException(status_code=404, detail="pipeline run not found")
    return result


@router.get("/runs/{run_id}/steps")
def pipeline_run_steps(run_id: str) -> dict:
    result = get_run(run_id)
    if result is None:
        raise HTTPException(status_code=404, detail="pipeline run not found")
    return {"items": result["steps"]}


@router.post("/runs/{run_id}/resume", status_code=202)
def resume_pipeline_run(run_id: str) -> dict:
    if not resume_run(run_id):
        raise HTTPException(status_code=404, detail="pipeline run not found or not resumable")
    result = get_run(run_id)
    assert result is not None
    return {"accepted": True, "run_id": run_id, "status": result["status"]}


@router.post("/runs/{run_id}/cancel", status_code=202)
def cancel_pipeline_run(run_id: str) -> dict:
    if not cancel_run(run_id):
        raise HTTPException(status_code=404, detail="pipeline run not found")
    result = get_run(run_id)
    assert result is not None
    return {"accepted": True, "run_id": run_id, "status": result["status"]}


@router.post("/runs/{run_id}/steps/{step_key}/retry", status_code=202)
def retry_pipeline_run_step(run_id: str, step_key: str) -> dict:
    if not retry_step(run_id, step_key):
        raise HTTPException(
            status_code=409,
            detail="step is not the first failed step or run is not resumable",
        )
    return {
        "accepted": True,
        "run_id": run_id,
        "step_key": step_key,
        "status": "queued",
    }


@router.get("/health")
def health() -> dict:
    return pipeline_health()
