from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, status

from app.api.deps import RequestContext, get_request_context
from app.models.scan import ScanJob, ScanRequest, ScanResult
from app.services.scanner import ScannerError, execute_scan
from app.services import scanner_jobs

router = APIRouter()


@router.post("", response_model=ScanResult)
async def run_scan(
    payload: ScanRequest,
    ctx: RequestContext = Depends(get_request_context),
) -> ScanResult:
    try:
        return execute_scan(payload, user_id=ctx.user_id)
    except ScannerError as exc:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc)) from exc
    except Exception as exc:  # pragma: no cover
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(exc)) from exc


@router.post("/jobs", response_model=ScanJob, status_code=status.HTTP_202_ACCEPTED)
async def enqueue_scan_job(
    payload: ScanRequest,
    background_tasks: BackgroundTasks,
    ctx: RequestContext = Depends(get_request_context),
) -> ScanJob:
    try:
        job = scanner_jobs.enqueue_scan(payload, user_id=ctx.user_id)
    except ScannerError as exc:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc)) from exc
    background_tasks.add_task(scanner_jobs.process_scan_job, job.job_id)
    return job


@router.get("/jobs/{job_id}", response_model=ScanJob)
async def get_scan_job(
    job_id: str,
    ctx: RequestContext = Depends(get_request_context),
) -> ScanJob:
    try:
        return scanner_jobs.get_job(job_id, user_id=ctx.user_id)
    except ScannerError as exc:
        message = str(exc)
        status_code = status.HTTP_403_FORBIDDEN if message.lower().startswith("not authorized") else status.HTTP_404_NOT_FOUND
        raise HTTPException(status_code=status_code, detail=message) from exc
    except Exception as exc:  # pragma: no cover
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(exc)) from exc
