from datetime import date, timedelta

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

from app.api.deps import require_session
from app.services.tenant_store import (
    MarineAssetCreatePayload,
    MarineAssetUpdatePayload,
    MarineBookingCheckoutPayload,
    MarineBookingCreatePayload,
    MarineBookingReturnPayload,
    MarineBookingUpdatePayload,
    MarineSeasonCalendarPayload,
    MarineSettingsPayload,
    SessionIdentity,
    TenantStaffUserCreatePayload,
    get_tenant_store,
)


router = APIRouter()


def _raise_marine_error(exc: ValueError) -> None:
    detail = str(exc)
    normalized_detail = detail.lower()
    status_code = (
        status.HTTP_403_FORBIDDEN
        if "non puo" in normalized_detail or "solo l'admin" in normalized_detail
        else status.HTTP_400_BAD_REQUEST
    )
    raise HTTPException(status_code=status_code, detail=detail) from exc


@router.get("/assets")
def list_assets(session: SessionIdentity = Depends(require_session)) -> dict[str, object]:
    try:
        return get_tenant_store().list_marine_assets(session)
    except ValueError as exc:
        _raise_marine_error(exc)


@router.post("/assets")
def create_asset(
    payload: MarineAssetCreatePayload,
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        return get_tenant_store().create_marine_asset(session, payload)
    except ValueError as exc:
        _raise_marine_error(exc)


@router.patch("/assets/{asset_id}")
def update_asset(
    asset_id: str,
    payload: MarineAssetUpdatePayload,
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        return get_tenant_store().update_marine_asset(session, asset_id, payload)
    except KeyError as exc:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=exc.args[0] if exc.args else str(exc)) from exc
    except ValueError as exc:
        _raise_marine_error(exc)


@router.delete("/assets/{asset_id}")
def delete_asset(
    asset_id: str,
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        return get_tenant_store().delete_marine_asset(session, asset_id)
    except KeyError as exc:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=exc.args[0] if exc.args else str(exc)) from exc
    except ValueError as exc:
        _raise_marine_error(exc)


@router.put("/season-calendar")
def update_season_calendar(
    payload: MarineSeasonCalendarPayload,
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        return get_tenant_store().update_marine_season_calendar(session, payload)
    except ValueError as exc:
        _raise_marine_error(exc)


@router.put("/settings")
def update_settings(
    payload: MarineSettingsPayload,
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        return get_tenant_store().update_marine_settings(session, payload)
    except ValueError as exc:
        _raise_marine_error(exc)


@router.get("/bookings")
def list_bookings(
    start_date: str | None = Query(default=None),
    end_date: str | None = Query(default=None),
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    today = date.today()
    start = start_date or today.isoformat()
    end = end_date or (today + timedelta(days=14)).isoformat()
    try:
        return get_tenant_store().list_marine_bookings(session, start_date=start, end_date=end)
    except ValueError as exc:
        _raise_marine_error(exc)


@router.get("/fiscal-summary")
def fiscal_summary(
    start_date: str = Query(...),
    end_date: str = Query(...),
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        return get_tenant_store().marine_fiscal_summary(
            session,
            start_date=start_date,
            end_date=end_date,
        )
    except ValueError as exc:
        _raise_marine_error(exc)


@router.post("/bookings")
def create_booking(
    payload: MarineBookingCreatePayload,
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        return get_tenant_store().create_marine_booking(session, payload)
    except KeyError as exc:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=exc.args[0] if exc.args else str(exc)) from exc
    except ValueError as exc:
        _raise_marine_error(exc)


@router.patch("/bookings/{booking_id}")
def update_booking(
    booking_id: str,
    payload: MarineBookingUpdatePayload,
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        return get_tenant_store().update_marine_booking(session, booking_id, payload)
    except KeyError as exc:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=exc.args[0] if exc.args else str(exc)) from exc
    except ValueError as exc:
        _raise_marine_error(exc)


@router.post("/bookings/{booking_id}/checkout")
def checkout_booking(
    booking_id: str,
    payload: MarineBookingCheckoutPayload,
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        return get_tenant_store().checkout_marine_booking(session, booking_id, payload)
    except KeyError as exc:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=exc.args[0] if exc.args else str(exc)) from exc
    except ValueError as exc:
        _raise_marine_error(exc)


@router.post("/bookings/{booking_id}/return")
def return_booking(
    booking_id: str,
    payload: MarineBookingReturnPayload,
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        return get_tenant_store().return_marine_booking(session, booking_id, payload)
    except KeyError as exc:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=exc.args[0] if exc.args else str(exc)) from exc
    except ValueError as exc:
        _raise_marine_error(exc)


@router.get("/users")
def list_users(session: SessionIdentity = Depends(require_session)) -> dict[str, object]:
    try:
        return get_tenant_store().list_marine_users(session)
    except ValueError as exc:
        _raise_marine_error(exc)


@router.post("/users")
def create_user(
    payload: TenantStaffUserCreatePayload,
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        user = get_tenant_store().create_marine_user(session, payload)
    except ValueError as exc:
        _raise_marine_error(exc)
    return {"user": user}
