"""
Route handlers for async validation job submission and status.

Uses the database-backed job queue (no Redis required).
"""

from __future__ import annotations

import logging
from typing import Any

from fastapi import APIRouter, Depends, HTTPException, status
from pydantic import BaseModel, Field

logger = logging.getLogger(__name__)

router = APIRouter(tags=["Validation Jobs"])

# --- Pydantic request/response models ---


class ValidationJobRequest(BaseModel):
    """Request to submit a validation job."""

    contract_name: str = Field(..., description="Data contract name")
    contract_version: str = Field("latest", description="Data contract version")
    data_source: str = Field(
        ..., description="Data source (S3 path, file path, table name)"
    )
    options: dict[str, Any] = Field(None, description="Validation options")
    idempotency_key: str | None = Field(None, description="Idempotency key for dedup")


class ValidationJobResponse(BaseModel):
    """Response for a validation job."""

    job_id: str
    status: str
    contract_name: str | None = None
    contract_version: str | None = None
    result: dict[str, Any] | None = None
    error: str | None = None
    created_at: Any | None = None
    started_at: Any | None = None
    completed_at: Any | None = None
    duration_ms: float | None = None


# --- Dependency ---

_job_manager = None


def get_job_manager():
    """Get or create the database job manager singleton."""
    global _job_manager
    if _job_manager is None:
        from pycharter.api.services.database_job_manager import DatabaseJobManager
        from pycharter.config import get_database_url

        db_url = get_database_url()
        if not db_url:
            raise HTTPException(
                status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
                detail="No database URL configured for job queue.",
            )
        _job_manager = DatabaseJobManager(db_url)
    return _job_manager


# --- Routes ---


@router.post(
    "/validation/jobs",
    response_model=ValidationJobResponse,
    status_code=status.HTTP_202_ACCEPTED,
    summary="Submit async validation job",
)
async def submit_validation_job(
    request: ValidationJobRequest,
    mgr=Depends(get_job_manager),
) -> ValidationJobResponse:
    """Submit a validation job for asynchronous processing."""
    try:
        job_id = await mgr.submit_job_async(
            contract_name=request.contract_name,
            contract_version=request.contract_version,
            data_source=request.data_source,
            options=request.options,
            idempotency_key=request.idempotency_key,
        )
        return ValidationJobResponse(
            job_id=job_id,
            status="queued",
            contract_name=request.contract_name,
            contract_version=request.contract_version,
        )
    except Exception as e:
        logger.error("Failed to submit job: %s", e, exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to submit job: {e}",
        )


@router.get(
    "/validation/jobs",
    response_model=list[ValidationJobResponse],
    summary="List validation jobs",
)
async def list_validation_jobs(
    mgr=Depends(get_job_manager),
    status_filter: str | None = None,
    limit: int = 100,
    offset: int = 0,
) -> list[dict[str, Any]]:
    """List validation jobs with optional status filter."""
    return await mgr.list_jobs_async(status=status_filter, limit=limit, offset=offset)


@router.get(
    "/validation/jobs/stats",
    summary="Get validation job statistics",
)
async def get_validation_job_stats(
    mgr=Depends(get_job_manager),
) -> dict[str, int]:
    """Get counts of jobs by status."""
    return await mgr.get_stats_async()


@router.get(
    "/validation/jobs/{job_id}",
    response_model=ValidationJobResponse,
    summary="Get validation job status",
)
async def get_validation_job_status(
    job_id: str,
    mgr=Depends(get_job_manager),
) -> dict[str, Any]:
    """Get the status and results of a validation job."""
    job = await mgr.get_job_async(job_id)
    if not job:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Job {job_id} not found",
        )
    return job


@router.post(
    "/validation/jobs/{job_id}/cancel",
    summary="Cancel a validation job",
)
async def cancel_validation_job(
    job_id: str,
    mgr=Depends(get_job_manager),
) -> dict[str, str | None]:
    """Cancel a pending or running validation job."""
    ok = await mgr.cancel_job_async(job_id)
    if not ok:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"Cannot cancel job {job_id} (not in cancellable state)",
        )
    return {"job_id": job_id, "status": "cancelled"}


@router.delete(
    "/validation/jobs/{job_id}",
    status_code=status.HTTP_204_NO_CONTENT,
    summary="Delete a validation job",
)
async def delete_validation_job(
    job_id: str,
    mgr=Depends(get_job_manager),
) -> None:
    """Delete a validation job."""
    ok = await mgr.delete_job_async(job_id)
    if not ok:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Job {job_id} not found",
        )
