from datetime import date

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

from app.api.deps import require_session
from app.core.config import get_settings
from app.services.google_workspace_drive import upsert_text_file_to_drive
from app.services.google_workspace_session import get_active_google_workspace_connection
from app.services.tenant_store import (
    HomemadePreparationWritePayload,
    HomemadeRecipeWritePayload,
    HomemadeStockSettingsPayload,
    HomemadeStockWritePayload,
    InventorySessionCreatePayload,
    InventoryWarehouseCreatePayload,
    SessionIdentity,
    get_tenant_store,
)


router = APIRouter()


def _raise_homemade_error(exc: ValueError) -> None:
    detail = str(exc)
    lowered = detail.lower()
    status_code = (
        status.HTTP_403_FORBIDDEN
        if "non puo" in lowered or "superadmin" in lowered
        else status.HTTP_400_BAD_REQUEST
    )
    raise HTTPException(status_code=status_code, detail=detail) from exc


@router.get("/status")
def homemade_status(session: SessionIdentity = Depends(require_session)) -> dict[str, object]:
    try:
        payload = get_tenant_store().list_homemade_recipes(session)
    except ValueError as exc:
        _raise_homemade_error(exc)
    return {
        "mode": "active",
        "status": "ready",
        "total_count": int(payload.get("total_count") or 0),
        "can_manage": bool(payload.get("can_manage")),
    }


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


@router.get("/stock/warehouses")
def list_homemade_stock_warehouses(session: SessionIdentity = Depends(require_session)) -> dict[str, object]:
    try:
        return get_tenant_store().list_homemade_stock_warehouses(session)
    except ValueError as exc:
        _raise_homemade_error(exc)


@router.get("/stock/totals")
def list_homemade_stock_totals(session: SessionIdentity = Depends(require_session)) -> dict[str, object]:
    try:
        return get_tenant_store().list_homemade_stock_totals(session)
    except ValueError as exc:
        _raise_homemade_error(exc)


@router.get("/stock/understock")
def get_homemade_stock_understock(session: SessionIdentity = Depends(require_session)) -> dict[str, object]:
    try:
        return get_tenant_store().get_homemade_stock_understock(session)
    except ValueError as exc:
        _raise_homemade_error(exc)


@router.patch("/stock/settings")
def update_homemade_stock_settings(
    payload: HomemadeStockSettingsPayload,
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        return get_tenant_store().update_homemade_stock_settings(session, payload)
    except ValueError as exc:
        _raise_homemade_error(exc)


@router.post("/stock/warehouses")
def create_homemade_stock_warehouse(
    payload: InventoryWarehouseCreatePayload,
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        return get_tenant_store().create_homemade_stock_warehouse(session, payload)
    except ValueError as exc:
        _raise_homemade_error(exc)


@router.patch("/stock/warehouses/{warehouse_id}")
def update_homemade_stock_warehouse(
    warehouse_id: str,
    payload: InventoryWarehouseCreatePayload,
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        return get_tenant_store().update_homemade_stock_warehouse(session, warehouse_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_homemade_error(exc)


@router.delete("/stock/warehouses/{warehouse_id}")
def delete_homemade_stock_warehouse(
    warehouse_id: str,
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        return get_tenant_store().delete_homemade_stock_warehouse(session, warehouse_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_homemade_error(exc)


@router.get("/stock/warehouses/{warehouse_id}")
def get_homemade_stock_warehouse_detail(
    warehouse_id: str,
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        return get_tenant_store().get_homemade_stock_warehouse_detail(session, warehouse_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_homemade_error(exc)


@router.get("/stock/warehouses/{warehouse_id}/sessions")
def list_homemade_stock_warehouse_sessions(
    warehouse_id: str,
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        return get_tenant_store().list_homemade_stock_warehouse_sessions(session, warehouse_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_homemade_error(exc)


@router.get("/stock/warehouses/{warehouse_id}/sessions/{session_id}")
def get_homemade_stock_warehouse_session_detail(
    warehouse_id: str,
    session_id: str,
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        return get_tenant_store().get_homemade_stock_warehouse_session_detail(session, warehouse_id, session_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_homemade_error(exc)


@router.post("/stock/warehouses/{warehouse_id}/sessions/{session_id}/load")
def load_homemade_stock_warehouse_session_into_stock(
    warehouse_id: str,
    session_id: str,
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        return get_tenant_store().load_homemade_stock_warehouse_session_into_stock(session, warehouse_id, session_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_homemade_error(exc)


@router.delete("/stock/warehouses/{warehouse_id}/sessions/{session_id}")
def delete_homemade_stock_warehouse_session(
    warehouse_id: str,
    session_id: str,
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        return get_tenant_store().delete_homemade_stock_warehouse_session(session, warehouse_id, session_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_homemade_error(exc)


@router.post("/stock/warehouses/{warehouse_id}/sessions")
def create_homemade_stock_warehouse_session(
    warehouse_id: str,
    payload: InventorySessionCreatePayload,
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        return get_tenant_store().create_homemade_stock_warehouse_session(session, warehouse_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_homemade_error(exc)


@router.post("/stock/warehouses/{warehouse_id}/stock/reset")
def reset_homemade_stock_warehouse_stock(
    warehouse_id: str,
    area: str | None = None,
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        return get_tenant_store().reset_homemade_stock_warehouse_stock(session, warehouse_id, usage_scope=area)
    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_homemade_error(exc)


@router.post("/stock/warehouses/{warehouse_id}/stock")
def add_homemade_stock(
    warehouse_id: str,
    payload: HomemadeStockWritePayload,
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        return get_tenant_store().add_homemade_stock(session, warehouse_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_homemade_error(exc)


@router.get("/stock/recipes/search")
def search_homemade_stock_recipes(
    q: str | None = None,
    area: str | None = None,
    limit: int = 20,
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        return get_tenant_store().search_homemade_stock_recipes(session, query=q, usage_scope=area, limit=limit)
    except ValueError as exc:
        _raise_homemade_error(exc)


@router.get("/recipes/{recipe_id}")
def get_homemade_recipe(
    recipe_id: str,
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        return get_tenant_store().get_homemade_recipe(session, recipe_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_homemade_error(exc)


@router.post("/recipes")
def create_homemade_recipe(
    payload: HomemadeRecipeWritePayload,
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        return get_tenant_store().create_homemade_recipe(session, payload)
    except ValueError as exc:
        _raise_homemade_error(exc)


@router.put("/recipes/{recipe_id}")
def update_homemade_recipe(
    recipe_id: str,
    payload: HomemadeRecipeWritePayload,
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        return get_tenant_store().update_homemade_recipe(session, recipe_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_homemade_error(exc)


@router.delete("/recipes/{recipe_id}")
def delete_homemade_recipe(
    recipe_id: str,
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        return get_tenant_store().delete_homemade_recipe(session, recipe_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_homemade_error(exc)


@router.put("/recipes/{recipe_id}/preparation")
async def update_homemade_preparation_date(
    recipe_id: str,
    payload: HomemadePreparationWritePayload,
    session: SessionIdentity = Depends(require_session),
) -> dict[str, object]:
    try:
        prepared_on = date.fromisoformat(payload.prepared_on).isoformat()
    except ValueError as exc:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Data preparazione non valida.") from exc

    try:
        current_recipe = get_tenant_store().get_homemade_recipe(session, recipe_id)["recipe"]
    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_homemade_error(exc)

    recipe_name = str(current_recipe.get("name") or "").strip()
    if not recipe_name:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Ricetta homemade non valida.")

    try:
        recipes_payload = get_tenant_store().list_homemade_recipes(session)
    except ValueError as exc:
        _raise_homemade_error(exc)

    recipes = recipes_payload.get("recipes") if isinstance(recipes_payload, dict) else []
    file_name = "Date Preparazioni"
    rows: list[tuple[str, str]] = []
    for item in recipes if isinstance(recipes, list) else []:
        if not isinstance(item, dict):
            continue
        name = str(item.get("name") or "").strip()
        if not name:
            continue
        item_prepared_on = prepared_on if str(item.get("id") or "") == recipe_id else str(item.get("preparation_date") or "").strip()
        item_label = date.fromisoformat(item_prepared_on).strftime("%d/%m/%Y") if item_prepared_on else "-"
        rows.append((name, item_label))

    rows.sort(key=lambda entry: entry[0].casefold())
    file_content = "\n".join(
        ["Date Preparazioni", ""]
        + [f"{name}: {label}" for name, label in rows]
    )

    try:
        connection = await get_active_google_workspace_connection(session)
    except HTTPException:
        raise

    drive_reference = f"{session.tenant_name.upper()}-HOMEMADE"
    settings = get_settings()

    try:
        async with httpx.AsyncClient(timeout=settings.google_workspace_request_timeout_seconds) as client:
            drive_file = await upsert_text_file_to_drive(
                client,
                access_token=connection.access_token,
                filename=file_name,
                text_content=file_content,
                folder_reference=drive_reference,
                existing_file_id=None,
            )
    except httpx.HTTPError as exc:
        raise HTTPException(status_code=502, detail=f"Salvataggio file Homemade su Drive fallito: {exc}") from exc
    except ValueError as exc:
        raise HTTPException(status_code=400, detail=str(exc)) from exc

    try:
        return get_tenant_store().set_homemade_recipe_preparation(
            session,
            recipe_id,
            prepared_on=prepared_on,
            drive_file_id=drive_file.get("file_id"),
            drive_web_url=drive_file.get("web_url"),
        )
    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_homemade_error(exc)
