##/app/aroflo_connector_app/zones/overheads/base.py
from __future__ import annotations

from typing import Any, Dict, List, Optional

from ..base import ZoneOperation, ParamSpec

OP_LIST = "list_overheads"
OP_GET = "get_overhead"
OP_SEARCH = "search_overheads"


CATALOG: List[Dict[str, Any]] = [
    # Leave / Payroll
    {"id": "IycqVyEK", "name": "Annual Leave", "group": "leave", "active": True},
    {"id": "IycqVyAK", "name": "Sick Leave/ Personal/Carers Leave", "group": "leave", "active": True},
    {"id": "IycqVywK", "name": "Bereavement Leave", "group": "leave", "active": True},
    {"id": "IydKSywK", "name": "RDO", "group": "leave", "active": True},
    {"id": "IyQ6XyQK", "name": "RDO - Casuals", "group": "leave", "active": True},
    {"id": "IycqVyIK", "name": "Public Holiday", "group": "leave", "active": True},
    {"id": "IyQ6XyUK", "name": "Public Holiday - Casuals", "group": "leave", "active": True},
    {"id": "IydaQyAK", "name": "LWOP - Leave Without Pay", "group": "leave", "active": True},
    {"id": "IyQ6Qy0K", "name": "Sick Leave - Unpaid", "group": "leave", "active": True},
    {"id": "IyQ6UycK", "name": "Time in Lieu", "group": "leave", "active": True},
    {"id": "JCYqSyRRQCAgCg==", "name": "Purchased Annual Leave (EBA)", "group": "leave", "active": True},
    {"id": "JCYqSyVQMCAgCg==", "name": "LSL for salaried staff - Long Service Leave", "group": "leave", "active": True},
    {"id": "JCYqTyNQICAgCg==", "name": "LWOP for LeavePlus LSL - Long Service leave", "group": "leave", "active": True},
    {"id": "JCYqTyxQQCAgCg==", "name": "Casual on leave", "group": "leave", "active": True},

    # WorkCover / Injury
    {"id": "IydaRyYK", "name": "Light Duties under WorkCover - Approval required", "group": "workcover", "active": True},
    {"id": "IyQqXyEK", "name": "Lost Time Injury - Approval required", "group": "workcover", "active": True},
    {"id": "IyQqXyIK", "name": "Medical Treatment Injury - Approval Reqd", "group": "workcover", "active": True},
    {"id": "IyQqXyMK", "name": "WorkCover Claim - Approval Reqd", "group": "workcover", "active": True},

    # Operational overheads
    {"id": "IyQ6UyYK", "name": "Admin Duties", "group": "operational", "active": True},
    {"id": "JCYqTyNRUCAgCg==", "name": "Admin Duties - Telecommunications", "group": "operational", "active": True},
    {"id": "IycqVyMK", "name": "Training", "group": "operational", "active": True},
    {"id": "IyQqRyYK", "name": "Supervisor Audit", "group": "operational", "active": True},
    {"id": "IyQqQyEK", "name": "Project Quoting, Management, Supervision", "group": "operational", "active": True},
    {"id": "JCYqTyJRUCAgCg==", "name": "Planning/Applications", "group": "operational", "active": True},
    {"id": "IyQqQyMK", "name": "Attending Work Sites - Refer JSEA", "group": "operational", "active": True},
    {"id": "IyQqQywK", "name": "Working From Home", "group": "operational", "active": True},
    {"id": "IyQqXyAK", "name": "Onsite Scoping and Notifying", "group": "operational", "active": True},
    {"id": "JCYqTyBRQCAgCg==", "name": "Work Group Meetings", "group": "operational", "active": True},

    # Break
    {"id": "IyQqUyYK", "name": "Lunch break - Unpaid", "group": "break", "active": True},
]


def get_operations() -> List[ZoneOperation]:
    return [
        ZoneOperation(
            code=OP_LIST,
            label="List Overheads",
            description="Lista el catálogo local de overheads/leave types.",
            http_method="LOCAL",
            side_effect="read",
            idempotent=True,
            default_params={"group": None, "active_only": True},
            params=[
                ParamSpec("group", "string", False, "Filtro por grupo: leave/workcover/operational/break."),
                ParamSpec("active_only", "boolean", False, "Si true, solo devuelve activos."),
            ],
            category="overheads",
            use_cases=["Poblar dropdowns en LeaveForm", "Ver lista de overheads disponibles"],
            risk_level="low",
            requires_confirmation=False,
        ),
        ZoneOperation(
            code=OP_GET,
            label="Get Overhead",
            description="Obtiene un overhead por id.",
            http_method="LOCAL",
            side_effect="read",
            idempotent=True,
            default_params={},
            params=[
                ParamSpec("id", "string", True, "ID del overhead."),
            ],
            category="overheads",
            use_cases=["Resolver nombre desde id", "Validar overhead seleccionado"],
            risk_level="low",
            requires_confirmation=False,
        ),
        ZoneOperation(
            code=OP_SEARCH,
            label="Search Overheads",
            description="Busca overheads por texto (case-insensitive) en name y group.",
            http_method="LOCAL",
            side_effect="read",
            idempotent=True,
            default_params={"q": "", "active_only": True},
            params=[
                ParamSpec("q", "string", True, "Texto a buscar."),
                ParamSpec("active_only", "boolean", False, "Si true, solo devuelve activos."),
            ],
            category="overheads",
            use_cases=["Búsqueda rápida para UI", "Autocompletado"],
            risk_level="low",
            requires_confirmation=False,
        ),
    ]


def supports(operation_code: str) -> bool:
    return operation_code in {OP_LIST, OP_GET, OP_SEARCH}


def execute(operation_code: str, client: Any, params: Dict[str, Any]) -> Any:
    # client no se usa (catálogo local), se mantiene firma por consistencia
    active_only = bool(params.get("active_only", True))

    if operation_code == OP_LIST:
        group = params.get("group")
        group = str(group).strip().lower() if group else None

        out: List[Dict[str, Any]] = []
        for item in CATALOG:
            if active_only and not bool(item.get("active", True)):
                continue
            if group and str(item.get("group", "")).lower() != group:
                continue
            out.append(item)
        return {"overheads": out, "count": len(out), "group": group, "active_only": active_only}

    if operation_code == OP_GET:
        oid = str(params["id"]).strip()
        for item in CATALOG:
            if item.get("id") == oid:
                if active_only and not bool(item.get("active", True)):
                    return {"overhead": None, "found": False}
                return {"overhead": item, "found": True}
        return {"overhead": None, "found": False}

    if operation_code == OP_SEARCH:
        q = str(params.get("q", "")).strip().lower()
        if not q:
            return {"overheads": [], "count": 0, "q": q, "active_only": active_only}

        out: List[Dict[str, Any]] = []
        for item in CATALOG:
            if active_only and not bool(item.get("active", True)):
                continue
            hay = f"{item.get('name','')} {item.get('group','')}".lower()
            if q in hay:
                out.append(item)
        return {"overheads": out, "count": len(out), "q": q, "active_only": active_only}

    raise ValueError(f"[Overheads.base] Operación no soportada: {operation_code}")
