import os
from typing import Any
from datetime import datetime

from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel

from app.auth.keycloak_dependencies import get_current_keycloak_username
from app.services.leakage_identifier import (
    get_leakage_identify_scheme_detail,
    list_leakage_identify_schemes,
    run_leakage_identification,
)

router = APIRouter()
DEFAULT_N_WORKERS = max(1, min((os.cpu_count() or 1) - 1, 4))


class LeakageIdentifyRequest(BaseModel):
    network: str
    observed_pressure_data: str | dict[str, list[Any]] | list[dict[str, Any]] | None = (
        None
    )
    start_time: float = 0
    duration: float = 24
    timestep: float = 5
    q_sum: float = 0.2
    q_sum_unit: str = "m3/s"
    output_dir: str = "db_inp"
    pop_size: int = 50
    max_gen: int = 100
    n_workers: int = DEFAULT_N_WORKERS
    output_flow_unit: str = "m3/s"
    dma_count: int | None = None
    scada_start: datetime | None = None
    scada_end: datetime | None = None
    sensor_nodes: list[str] | None = None
    scheme_name: str | None = None


@router.post("/identify/")
async def identify_leakage(
    data: LeakageIdentifyRequest,
    username: str = Depends(get_current_keycloak_username),
) -> dict[str, Any]:
    try:
        return run_leakage_identification(**data.model_dump(), username=username)
    except Exception as exc:
        raise HTTPException(status_code=400, detail=str(exc))


@router.get("/schemes/")
async def query_leakage_schemes(
    network: str, query_date: datetime | None = None
) -> list[dict[str, Any]]:
    try:
        return list_leakage_identify_schemes(network=network, query_date=query_date)
    except Exception as exc:
        raise HTTPException(status_code=400, detail=str(exc))


@router.get("/schemes/{scheme_name}")
async def query_leakage_scheme_detail(network: str, scheme_name: str) -> dict[str, Any]:
    try:
        return get_leakage_identify_scheme_detail(
            network=network, scheme_name=scheme_name
        )
    except Exception as exc:
        raise HTTPException(status_code=400, detail=str(exc))
