"""SPBU router — endpoints for SPBU management and all sub-resources."""

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

from app.core.database import get_db
from app.dependencies import get_current_user
from app.models.user import User
from app.schemas.spbu import (
    IslandCreate, IslandResponse, IslandUpdate,
    KalibrasiTangkiItem, KalibrasiTangkiResponse,
    KontrakSewaCreate, KontrakSewaResponse, KontrakSewaUpdate,
    NozzleCreate, NozzleResponse, NozzleUpdate,
    ShiftCreate, ShiftResponse, ShiftUpdate,
    SpbuCreate, SpbuResponse, SpbuUpdate,
    TangkiCreate, TangkiResponse, TangkiUpdate,
    TenantCreate, TenantResponse, TenantUpdate,
)
from app.services import spbu_service


def _service_error(e: ValueError | PermissionError) -> HTTPException:
    """Convert service-layer ValueError → 404 and PermissionError → 403."""
    if isinstance(e, PermissionError):
        return HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=str(e))
    return HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))


router = APIRouter()


@router.get("", response_model=dict)
async def list_spbus(
    skip: int = 0,
    limit: int = 50,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Return a paginated list of SPBUs accessible to the current user."""
    spbus, total = await spbu_service.list_spbus(db, current_user, skip, limit)
    return {
        "data": [SpbuResponse.model_validate(s) for s in spbus],
        "meta": {"total": total, "page": skip // limit + 1, "per_page": limit},
    }


@router.post("", response_model=dict, status_code=status.HTTP_201_CREATED)
async def create_spbu(
    data: SpbuCreate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Create a new SPBU with initial shifts. Restricted to Super Admin."""
    try:
        spbu = await spbu_service.create_spbu(db, data, current_user)
    except PermissionError as e:
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=str(e))
    return {"data": SpbuResponse.model_validate(spbu), "message": "SPBU berhasil dibuat"}


@router.get("/{spbu_id}", response_model=dict)
async def get_spbu(
    spbu_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Return details for a single SPBU, enforcing access control."""
    try:
        spbu = await spbu_service.get_spbu(db, spbu_id, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": SpbuResponse.model_validate(spbu)}


@router.patch("/{spbu_id}", response_model=dict)
async def update_spbu(
    spbu_id: int,
    data: SpbuUpdate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Update scalar settings on an SPBU."""
    try:
        spbu = await spbu_service.update_spbu(db, spbu_id, data, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": SpbuResponse.model_validate(spbu), "message": "SPBU berhasil diupdate"}


@router.delete("/{spbu_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_spbu(
    spbu_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> None:
    """Permanently delete an SPBU. Restricted to Super Admin."""
    try:
        await spbu_service.delete_spbu(db, spbu_id, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)


@router.get("/{spbu_id}/shifts", response_model=dict)
async def list_shifts(
    spbu_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Return all shifts configured for an SPBU."""
    try:
        shifts = await spbu_service.list_shifts(db, spbu_id, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": [ShiftResponse.model_validate(s) for s in shifts]}


@router.post("/{spbu_id}/shifts", response_model=dict, status_code=status.HTTP_201_CREATED)
async def create_shift(
    spbu_id: int,
    data: ShiftCreate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Create a new shift under an SPBU."""
    try:
        shift = await spbu_service.create_shift(db, spbu_id, data, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": ShiftResponse.model_validate(shift), "message": "Shift berhasil dibuat"}


@router.patch("/{spbu_id}/shifts/{shift_id}", response_model=dict)
async def update_shift(
    spbu_id: int,
    shift_id: int,
    data: ShiftUpdate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Update a shift belonging to the given SPBU."""
    try:
        shift = await spbu_service.update_shift(db, spbu_id, shift_id, data, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": ShiftResponse.model_validate(shift), "message": "Shift berhasil diupdate"}


@router.delete("/{spbu_id}/shifts/{shift_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_shift(
    spbu_id: int,
    shift_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> None:
    """Delete a shift belonging to the given SPBU."""
    try:
        await spbu_service.delete_shift(db, spbu_id, shift_id, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)


# --- Islands ---

@router.get("/{spbu_id}/islands", response_model=dict)
async def list_islands(
    spbu_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Return all islands for an SPBU, with their nested nozzles."""
    try:
        islands = await spbu_service.list_islands(db, spbu_id, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    data = []
    for isl in islands:
        isl_dict = IslandResponse.model_validate(isl).model_dump()
        isl_dict["nozzles"] = [NozzleResponse.from_orm_with_names(n).model_dump() for n in isl.nozzles]
        data.append(isl_dict)
    return {"data": data}


@router.post("/{spbu_id}/islands", response_model=dict, status_code=status.HTTP_201_CREATED)
async def create_island(
    spbu_id: int,
    data: IslandCreate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Create a new island under an SPBU."""
    try:
        island = await spbu_service.create_island(db, spbu_id, data, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": IslandResponse.model_validate(island), "message": "Island berhasil dibuat"}


@router.patch("/{spbu_id}/islands/{island_id}", response_model=dict)
async def update_island(
    spbu_id: int,
    island_id: int,
    data: IslandUpdate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Update an island belonging to the given SPBU."""
    try:
        island = await spbu_service.update_island(db, spbu_id, island_id, data, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": IslandResponse.model_validate(island), "message": "Island berhasil diupdate"}


@router.delete("/{spbu_id}/islands/{island_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_island(
    spbu_id: int,
    island_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> None:
    """Delete an island belonging to the given SPBU."""
    try:
        await spbu_service.delete_island(db, spbu_id, island_id, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)


# --- Nozzles ---

@router.post("/{spbu_id}/islands/{island_id}/nozzles", response_model=dict, status_code=status.HTTP_201_CREATED)
async def create_nozzle(
    spbu_id: int,
    island_id: int,
    data: NozzleCreate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Create a new nozzle under an island."""
    try:
        nozzle = await spbu_service.create_nozzle(db, spbu_id, island_id, data, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": NozzleResponse.from_orm_with_names(nozzle).model_dump(), "message": "Nozzle berhasil dibuat"}


@router.patch("/{spbu_id}/nozzles/{nozzle_id}", response_model=dict)
async def update_nozzle(
    spbu_id: int,
    nozzle_id: int,
    data: NozzleUpdate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Update a nozzle belonging to the given SPBU."""
    try:
        nozzle = await spbu_service.update_nozzle(db, spbu_id, nozzle_id, data, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": NozzleResponse.from_orm_with_names(nozzle).model_dump(), "message": "Nozzle berhasil diupdate"}


@router.delete("/{spbu_id}/nozzles/{nozzle_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_nozzle(
    spbu_id: int,
    nozzle_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> None:
    """Delete a nozzle belonging to the given SPBU."""
    try:
        await spbu_service.delete_nozzle(db, spbu_id, nozzle_id, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)


# --- Tangkis ---

@router.get("/{spbu_id}/tangkis", response_model=dict)
async def list_tangkis(
    spbu_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Return all underground tanks for an SPBU."""
    try:
        tangkis = await spbu_service.list_tangkis(db, spbu_id, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": [TangkiResponse.from_orm_with_names(t).model_dump() for t in tangkis]}


@router.post("/{spbu_id}/tangkis", response_model=dict, status_code=status.HTTP_201_CREATED)
async def create_tangki(
    spbu_id: int,
    data: TangkiCreate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Create a new underground tank under an SPBU."""
    try:
        tangki = await spbu_service.create_tangki(db, spbu_id, data, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": TangkiResponse.from_orm_with_names(tangki).model_dump(), "message": "Tangki berhasil dibuat"}


@router.patch("/{spbu_id}/tangkis/{tangki_id}", response_model=dict)
async def update_tangki(
    spbu_id: int,
    tangki_id: int,
    data: TangkiUpdate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Update a tangki belonging to the given SPBU."""
    try:
        tangki = await spbu_service.update_tangki(db, spbu_id, tangki_id, data, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": TangkiResponse.from_orm_with_names(tangki).model_dump(), "message": "Tangki berhasil diupdate"}


@router.delete("/{spbu_id}/tangkis/{tangki_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_tangki(
    spbu_id: int,
    tangki_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> None:
    """Delete a tangki belonging to the given SPBU."""
    try:
        await spbu_service.delete_tangki(db, spbu_id, tangki_id, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)


@router.put("/{spbu_id}/tangkis/{tangki_id}/kalibrasi", response_model=dict)
async def update_kalibrasi(
    spbu_id: int,
    tangki_id: int,
    data: list[KalibrasiTangkiItem],
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Replace the full calibration table for a tangki (delete-all then insert-all)."""
    try:
        rows = await spbu_service.update_kalibrasi(
            db, spbu_id, tangki_id, [r.model_dump() for r in data], current_user
        )
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": [KalibrasiTangkiResponse.model_validate(r) for r in rows], "message": "Kalibrasi berhasil disimpan"}


# --- Tenants & Kontrak ---

@router.get("/{spbu_id}/tenants", response_model=dict)
async def list_tenants(
    spbu_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Return all tenants for an SPBU with their lease contracts."""
    try:
        tenants = await spbu_service.list_tenants(db, spbu_id, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": [TenantResponse.model_validate(t) for t in tenants]}


@router.post("/{spbu_id}/tenants", response_model=dict, status_code=status.HTTP_201_CREATED)
async def create_tenant(
    spbu_id: int,
    data: TenantCreate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Create a new tenant under an SPBU."""
    try:
        tenant = await spbu_service.create_tenant(db, spbu_id, data, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": TenantResponse.model_validate(tenant), "message": "Tenant berhasil dibuat"}


@router.patch("/{spbu_id}/tenants/{tenant_id}", response_model=dict)
async def update_tenant(
    spbu_id: int,
    tenant_id: int,
    data: TenantUpdate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Update a tenant belonging to the given SPBU."""
    try:
        tenant = await spbu_service.update_tenant(db, spbu_id, tenant_id, data, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": TenantResponse.model_validate(tenant), "message": "Tenant berhasil diupdate"}


@router.delete("/{spbu_id}/tenants/{tenant_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_tenant(
    spbu_id: int,
    tenant_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> None:
    """Delete a tenant belonging to the given SPBU."""
    try:
        await spbu_service.delete_tenant(db, spbu_id, tenant_id, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)


@router.post("/{spbu_id}/tenants/{tenant_id}/kontrak", response_model=dict, status_code=status.HTTP_201_CREATED)
async def create_kontrak(
    spbu_id: int,
    tenant_id: int,
    data: KontrakSewaCreate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Create a new lease contract for a tenant."""
    try:
        kontrak = await spbu_service.create_kontrak(db, spbu_id, tenant_id, data, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": KontrakSewaResponse.model_validate(kontrak), "message": "Kontrak berhasil dibuat"}


@router.patch("/{spbu_id}/kontrak/{kontrak_id}", response_model=dict)
async def update_kontrak(
    spbu_id: int,
    kontrak_id: int,
    data: KontrakSewaUpdate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Update a lease contract belonging to the given SPBU."""
    try:
        kontrak = await spbu_service.update_kontrak(db, spbu_id, kontrak_id, data, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
    return {"data": KontrakSewaResponse.model_validate(kontrak), "message": "Kontrak berhasil diupdate"}


@router.delete("/{spbu_id}/kontrak/{kontrak_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_kontrak(
    spbu_id: int,
    kontrak_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> None:
    """Delete a lease contract belonging to the given SPBU."""
    try:
        await spbu_service.delete_kontrak(db, spbu_id, kontrak_id, current_user)
    except (ValueError, PermissionError) as e:
        raise _service_error(e)
