"""Router for penebusan (BBM procurement) endpoints."""

from datetime import date

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

from app.core.database import get_db
from app.dependencies import get_current_user, get_spbu_access
from app.models.penebusan import StatusPenebusan
from app.models.user import User
from app.schemas.penebusan import (
    PenebusanCreate,
    PenebusanUpdate,
    SetSORequest,
)
from app.services import penebusan_service

router = APIRouter(
    prefix="/spbus/{spbu_id}/penebusan",
    tags=["penebusan"],
)


def _service_error(e: ValueError | PermissionError) -> HTTPException:
    if isinstance(e, PermissionError):
        return HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=str(e))
    return HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))


@router.get("", response_model=dict)
async def list_penebusan(
    spbu_id: int,
    tanggal: date | None = Query(default=None),
    penebusan_status: StatusPenebusan | None = Query(default=None, alias="status"),
    booking_code: str | None = Query(default=None),
    skip: int = Query(default=0, ge=0),
    limit: int = Query(default=20, ge=1, le=100),
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_spbu_access),
) -> dict:
    try:
        rows, total = await penebusan_service.list_penebusan(
            db, spbu_id, tanggal, penebusan_status, booking_code, skip, limit
        )
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {
        "data": [r.model_dump() for r in rows],
        "meta": {"total": total, "page": skip // limit + 1, "per_page": limit},
    }


@router.post("", response_model=dict, status_code=status.HTTP_201_CREATED)
async def create_penebusan(
    spbu_id: int,
    data: PenebusanCreate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_spbu_access),
) -> dict:
    try:
        result = await penebusan_service.create_penebusan(
            db, spbu_id, data, current_user.id
        )
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": result.model_dump(), "message": "Penebusan berhasil disimpan"}


@router.get("/{penebusan_id}", response_model=dict)
async def get_penebusan_detail(
    spbu_id: int,
    penebusan_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_spbu_access),
) -> dict:
    try:
        result = await penebusan_service.get_penebusan_detail(db, spbu_id, penebusan_id)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": result.model_dump()}


@router.patch("/{penebusan_id}", response_model=dict)
async def update_penebusan(
    spbu_id: int,
    penebusan_id: int,
    data: PenebusanUpdate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_spbu_access),
) -> dict:
    try:
        result = await penebusan_service.update_penebusan(db, spbu_id, penebusan_id, data)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": result.model_dump(), "message": "Penebusan berhasil diupdate"}


@router.delete("/{penebusan_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_penebusan(
    spbu_id: int,
    penebusan_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_spbu_access),
) -> None:
    try:
        await penebusan_service.delete_penebusan(db, spbu_id, penebusan_id)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)


@router.post("/parse-pdf", response_model=dict)
async def parse_pdf(
    spbu_id: int,
    file: UploadFile,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_spbu_access),
) -> dict:
    if not file.filename or not file.filename.lower().endswith(".pdf"):
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="File harus berformat PDF",
        )
    content = await file.read()
    if len(content) > 10 * 1024 * 1024:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Ukuran file maksimal 10 MB",
        )
    try:
        result = await penebusan_service.parse_pdf(db, content)
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
    return {"data": result.model_dump()}


@router.post("/{penebusan_id}/upload-do", response_model=dict)
async def upload_do(
    spbu_id: int,
    penebusan_id: int,
    file: UploadFile,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_spbu_access),
) -> dict:
    content = await file.read()
    if len(content) > 10 * 1024 * 1024:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Ukuran file maksimal 10 MB",
        )
    try:
        result = await penebusan_service.upload_file(
            db, spbu_id, penebusan_id, content, file.filename or "do.pdf", "do"
        )
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": result.model_dump(), "message": "File DO berhasil diupload"}


@router.post("/{penebusan_id}/upload-bukti", response_model=dict)
async def upload_bukti(
    spbu_id: int,
    penebusan_id: int,
    file: UploadFile,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_spbu_access),
) -> dict:
    content = await file.read()
    if len(content) > 10 * 1024 * 1024:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Ukuran file maksimal 10 MB",
        )
    try:
        result = await penebusan_service.upload_file(
            db, spbu_id, penebusan_id, content, file.filename or "bukti.pdf", "bukti"
        )
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": result.model_dump(), "message": "Bukti pembayaran berhasil diupload"}


@router.patch("/{penebusan_id}/set-so", response_model=dict)
async def set_so(
    spbu_id: int,
    penebusan_id: int,
    data: SetSORequest,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_spbu_access),
) -> dict:
    try:
        result = await penebusan_service.set_so(db, spbu_id, penebusan_id, data.no_so)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": result.model_dump(), "message": "SO berhasil diset"}
