"""Router for penerimaan (BBM receipt) endpoints."""

from datetime import date
from decimal import Decimal

from fastapi import APIRouter, Depends, Form, 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.user import User
from app.schemas.penerimaan import PenerimaanCreate, ReviewRequest, UnlockRequest
from app.services import penerimaan_service, stock_service

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

MAX_FILE_SIZE = 10 * 1024 * 1024  # 10 MB


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("/calculate-volume", response_model=dict)
async def calculate_volume(
    spbu_id: int,
    tangki_id: int = Query(...),
    height_mm: Decimal = Query(...),
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_spbu_access),
) -> dict:
    """Calculate volume (litres) from dipstick height using the tank's calibration table."""
    try:
        volume = await stock_service.calculate_volume_for_tank(db, spbu_id, tangki_id, height_mm)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": {"volume_liter": str(volume)}}


@router.get("", response_model=dict)
async def list_penerimaan(
    spbu_id: int,
    tanggal: date | None = Query(default=None),
    penebusan_id: int | 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),
):
    rows, total = await penerimaan_service.list_penerimaan(
        db, spbu_id, tanggal=tanggal, penebusan_id=penebusan_id, skip=skip, limit=limit,
    )
    return {
        "data": [r.model_dump() for r in rows],
        "meta": {"total": total, "skip": skip, "limit": limit},
    }


@router.post("", response_model=dict, status_code=status.HTTP_201_CREATED)
async def create_penerimaan(
    spbu_id: int,
    body: PenerimaanCreate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_spbu_access),
):
    try:
        result = await penerimaan_service.create_penerimaan(db, spbu_id, body, current_user.id)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": result.model_dump(), "message": "Penerimaan berhasil dicatat"}


@router.get("/{penerimaan_id}", response_model=dict)
async def get_penerimaan(
    spbu_id: int,
    penerimaan_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_spbu_access),
):
    try:
        result = await penerimaan_service.get_penerimaan_detail(db, spbu_id, penerimaan_id)
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
    return {"data": result.model_dump()}


@router.delete("/{penerimaan_id}", response_model=dict)
async def delete_penerimaan(
    spbu_id: int,
    penerimaan_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_spbu_access),
):
    try:
        await penerimaan_service.delete_penerimaan(db, spbu_id, penerimaan_id)
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
    return {"message": "Penerimaan berhasil dihapus"}


@router.post("/{penerimaan_id}/fotos", response_model=dict)
async def upload_foto(
    spbu_id: int,
    penerimaan_id: int,
    file: UploadFile,
    tipe: str = Query(..., description="Tipe foto: truck|stick_t3|compartment_buka|compartment_kosong|surat_jalan|stick_awal|stick_akhir"),
    item_id: int | None = Query(default=None, description="penerimaan_item_id — required for stick_awal/stick_akhir"),
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_spbu_access),
):
    file_bytes = await file.read()
    if len(file_bytes) > MAX_FILE_SIZE:
        raise HTTPException(status_code=400, detail="File terlalu besar (max 10 MB)")
    try:
        result = await penerimaan_service.add_foto(
            db, spbu_id, penerimaan_id, item_id, tipe, file_bytes, file.filename or "foto"
        )
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": result.model_dump(), "message": "Foto berhasil diupload"}


@router.post("/{penerimaan_id}/submit", response_model=dict)
async def submit_penerimaan(
    spbu_id: int,
    penerimaan_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_spbu_access),
):
    try:
        p = await penerimaan_service.submit_penerimaan(db, spbu_id, penerimaan_id, current_user.id)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": p.model_dump(), "message": "Penerimaan berhasil di-submit"}


@router.post("/{penerimaan_id}/review", response_model=dict)
async def review_penerimaan(
    spbu_id: int,
    penerimaan_id: int,
    body: ReviewRequest,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_spbu_access),
):
    try:
        p = await penerimaan_service.review_penerimaan(db, spbu_id, penerimaan_id, current_user, body.action, body.catatan)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": p.model_dump(), "message": "Penerimaan berhasil di-review"}


@router.post("/{penerimaan_id}/unlock", response_model=dict)
async def unlock_penerimaan(
    spbu_id: int,
    penerimaan_id: int,
    body: UnlockRequest,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_spbu_access),
):
    try:
        p = await penerimaan_service.unlock_penerimaan(db, spbu_id, penerimaan_id, current_user, body.alasan)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": p.model_dump(), "message": "Penerimaan berhasil di-unlock"}


@router.delete("/{penerimaan_id}/fotos/{foto_id}", response_model=dict)
async def delete_foto(
    spbu_id: int,
    penerimaan_id: int,
    foto_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_spbu_access),
):
    try:
        result = await penerimaan_service.delete_foto(db, spbu_id, penerimaan_id, foto_id)
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
    return {"data": result.model_dump(), "message": "Foto berhasil dihapus"}


@router.get("/{penerimaan_id}/bast-pdf")
async def download_bast_penerimaan(
    spbu_id: int,
    penerimaan_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_spbu_access),
):
    """Download BAST PDF for an approved penerimaan. Requires: penerimaan:view permission."""
    from fastapi.responses import Response as FastAPIResponse
    from app.utils.bast_pdf import generate_bast

    try:
        result = await penerimaan_service.get_penerimaan_detail(db, spbu_id, penerimaan_id)
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
    if result.status != "approved":
        raise HTTPException(400, detail="BAST hanya tersedia untuk penerimaan yang sudah Approved")
    from app.models.spbu import Spbu
    from sqlalchemy import select as sa_select
    spbu = (await db.execute(sa_select(Spbu).where(Spbu.id == spbu_id))).scalar_one_or_none()
    spbu_name = spbu.name if spbu else f"SPBU {spbu_id}"
    details = [
        ("Tanggal", str(result.tanggal)),
        ("No. Polisi", result.no_polisi or "-"),
        ("Nama Pengemudi", result.nama_pengemudi or "-"),
        ("Total Volume Diterima", f"{result.total_volume_diterima} L"),
        ("Jumlah Produk", str(len(result.items))),
    ]
    pdf_bytes = generate_bast(
        modul="Penerimaan BBM", record_id=penerimaan_id,
        spbu_name=spbu_name, tanggal=str(result.tanggal),
        submitter_name=result.submitted_by_name or "-",
        submitter_at=result.submitted_at,
        approver_name=result.reviewed_by_name or "-",
        approver_at=result.reviewed_at,
        details=details,
    )
    filename = f"BAST-Penerimaan-{spbu_id}-{result.tanggal}-{penerimaan_id}.pdf"
    return FastAPIResponse(content=pdf_bytes, media_type="application/pdf",
                    headers={"Content-Disposition": f'attachment; filename="{filename}"'})
