"""Router for End-to-End reconciliation endpoints."""

from fastapi import APIRouter, Depends, HTTPException, Query, 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.end_to_end import EndToEndClose, EndToEndCreate
from app.services import end_to_end_service

router = APIRouter(
    prefix="/spbus/{spbu_id}/end-to-end",
    tags=["rekonsiliasi"],
)


def _service_error(e: ValueError | PermissionError) -> HTTPException:
    """Convert service-layer ValueError → 400 and PermissionError → 403."""
    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_cycles(
    spbu_id: int,
    tangki_id: int | None = Query(default=None),
    status_filter: str | None = Query(default=None, alias="status"),
    skip: int = Query(default=0, ge=0),
    limit: int = Query(default=50, ge=1, le=200),
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_spbu_access),
) -> dict:
    """List E2E cycles for an SPBU, optionally filtered by tangki and status."""
    try:
        rows, total = await end_to_end_service.list_cycles(
            db, spbu_id, tangki_id=tangki_id, status=status_filter,
            skip=skip, limit=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 start_cycle(
    spbu_id: int,
    data: EndToEndCreate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_spbu_access),
) -> dict:
    """Start a new E2E cycle for a tank. Tank must not have an existing open cycle."""
    try:
        cycle = await end_to_end_service.start_cycle(db, spbu_id, current_user.id, data)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": cycle.model_dump(), "message": "Siklus End-to-End berhasil dimulai"}


@router.get("/{cycle_id}", response_model=dict)
async def get_cycle_detail(
    spbu_id: int,
    cycle_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_spbu_access),
) -> dict:
    """Get detail of an E2E cycle. Open cycles include live running totals."""
    try:
        detail = await end_to_end_service.get_cycle_detail(db, spbu_id, cycle_id)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": detail.model_dump()}


@router.patch("/{cycle_id}/close", response_model=dict)
async def close_cycle(
    spbu_id: int,
    cycle_id: int,
    data: EndToEndClose,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_spbu_access),
) -> dict:
    """Close an open E2E cycle. Freezes totals and calculates actual losses."""
    try:
        detail = await end_to_end_service.close_cycle(
            db, spbu_id, cycle_id, current_user.id, data
        )
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": detail.model_dump(), "message": "Siklus End-to-End berhasil ditutup"}
