#/apps/aroflo_connector_app/agent/cheap/zone_resolvers/businessunits.py
from __future__ import annotations

from typing import Any, Dict, Set, List

from ..plan import Plan, MissingParam
from ..extractors import (
    extract_page_and_pagesize,
    extract_where_tail,
    extract_join,
    extract_kv_params,
    normalize_join_keyword,
)

JOINABLE = {"locations", "priorities"}


def _choose_join_op(join: str, available_ops: Set[str]) -> str:
    j = normalize_join_keyword(join)
    if j in JOINABLE:
        candidate = f"get_businessunits_with_{j}"
        if candidate in available_ops:
            return candidate
    return "list_businessunits"


def build_plan(*, question: str, intent: str, available_ops: Set[str]) -> Plan:
    q = question or ""
    t = q.lower()

    missing: List[MissingParam] = []
    params: Dict[str, Any] = {}

    # Default: list
    op_code = intent if intent in available_ops else "list_businessunits"
    side_effect = "read"

    kv = extract_kv_params(q)

    READ_KEYS = {"page", "pageSize", "pagesize", "where", "order", "join", "raw"}
    for k, v in kv.items():
        if k in READ_KEYS:
            params[k] = v

    # Normaliza pageSize
    if "pagesize" in params and "pageSize" not in params:
        params["pageSize"] = params["pagesize"]

    # where=...
    where = extract_where_tail(q)
    if where:
        params["where"] = where

    # Heurística: "archived" => where default
    if (" archived" in f" {t}" or t.startswith("archived")) and not params.get("where"):
        params["where"] = "and|archived|=|true"

    # join
    join = extract_join(q) or (params.get("join") if isinstance(params.get("join"), str) else None)
    if join:
        op_code = _choose_join_op(join, available_ops)
        params["join"] = normalize_join_keyword(join)

    # page/pagesize por lenguaje natural
    page, pagesize = extract_page_and_pagesize(q)
    if page is not None:
        params["page"] = page
    if pagesize is not None:
        params["pageSize"] = pagesize

    if "raw" not in params:
        params["raw"] = False

    # Safety: never invent ops
    if op_code not in available_ops:
        op_code = "list_businessunits"

    summary = f"businessunits.{op_code} (read)"
    if join:
        summary += f" join={join}"

    return Plan(
        zone_code="businessunits",
        op_code=op_code,
        params=params,
        side_effect=side_effect,  # type: ignore[arg-type]
        needs_confirmation=False,
        summary=summary,
        missing=missing,
    )
