#/apps/aroflo_connector_app/agent/context_store.py
from __future__ import annotations

import json
import os
import time
from typing import Any, Dict, List, Optional

DEFAULT_CTX_PATH = os.getenv("AROFLO_AGENT_CONTEXT_PATH", "/tmp/aroflo_agent_context.json")
DEFAULT_MAX_ITEMS = int(os.getenv("AROFLO_AGENT_CONTEXT_MAX_ITEMS", "10"))


def _now() -> int:
    return int(time.time())


def load_context(path: str = DEFAULT_CTX_PATH) -> Dict[str, Any]:
    if not os.path.exists(path):
        return {}
    try:
        with open(path, "r", encoding="utf-8") as f:
            obj = json.load(f)
        return obj if isinstance(obj, dict) else {}
    except Exception:
        return {}


def save_context(ctx: Dict[str, Any], path: str = DEFAULT_CTX_PATH) -> None:
    try:
        with open(path, "w", encoding="utf-8") as f:
            json.dump(ctx, f, ensure_ascii=False, indent=2)
    except Exception:
        pass


def _extract_tasks_list(tool_result: Any) -> List[Dict[str, Any]]:
    """
    Intenta extraer una lista de tasks desde respuestas típicas:
    - resp["data"]["zoneresponse"]["tasks"]
    - resp["zoneresponse"]["tasks"]
    - resp["data"]["tasks"]
    """
    if not isinstance(tool_result, dict):
        return []

    data = tool_result.get("data")
    if isinstance(data, dict):
        zr = data.get("zoneresponse")
        if isinstance(zr, dict) and isinstance(zr.get("tasks"), list):
            return zr["tasks"]
        if isinstance(data.get("tasks"), list):
            return data["tasks"]

    zr = tool_result.get("zoneresponse")
    if isinstance(zr, dict) and isinstance(zr.get("tasks"), list):
        return zr["tasks"]

    return []


def remember_tasks_from_result(result: Dict[str, Any]) -> Optional[List[Dict[str, Any]]]:
    """
    Guarda snapshot compacto de tasks para que el usuario pueda referirse por índice (#1..#N).
    Devuelve la lista normalizada si se pudo extraer.
    """
    tasks = _extract_tasks_list(result)
    if not tasks:
        return None

    normalized: List[Dict[str, Any]] = []
    for t in tasks[:DEFAULT_MAX_ITEMS]:
        # Campos defensivos: varían por tenant/join
        taskid = t.get("taskid") or t.get("id")
        clientid = None
        orgid = None

        client = t.get("client")
        if isinstance(client, dict):
            clientid = client.get("clientid") or client.get("id")

        org = t.get("org")
        if isinstance(org, dict):
            orgid = org.get("orgid") or org.get("id")

        normalized.append(
            {
                "taskid": taskid,
                "taskname": t.get("taskname") or t.get("summary") or "",
                "status": t.get("status") or "",
                "createdutc": t.get("createddatetimeutc") or t.get("createdutc") or "",
                "clientid": clientid,
                "orgid": orgid,
            }
        )

    ctx = load_context()
    ctx["tasks_last_list"] = {
        "saved_at": _now(),
        "items": normalized,
    }
    save_context(ctx)
    return normalized


def get_task_by_index(idx_1based: int) -> Optional[Dict[str, Any]]:
    """
    idx_1based: 1..N
    """
    ctx = load_context()
    block = ctx.get("tasks_last_list")
    if not isinstance(block, dict):
        return None
    items = block.get("items")
    if not isinstance(items, list):
        return None

    i = idx_1based - 1
    if i < 0 or i >= len(items):
        return None
    return items[i]

def _extract_users_list(tool_result: Any) -> List[Dict[str, Any]]:
    """
    Intenta extraer una lista de users desde respuestas típicas:
    - resp["data"]["zoneresponse"]["users"]
    - resp["zoneresponse"]["users"]
    - resp["data"]["users"]
    """
    if not isinstance(tool_result, dict):
        return []

    data = tool_result.get("data")
    if isinstance(data, dict):
        zr = data.get("zoneresponse")
        if isinstance(zr, dict) and isinstance(zr.get("users"), list):
            return zr["users"]
        if isinstance(data.get("users"), list):
            return data["users"]

    zr = tool_result.get("zoneresponse")
    if isinstance(zr, dict) and isinstance(zr.get("users"), list):
        return zr["users"]

    return []


def remember_users_from_result(result: Dict[str, Any]) -> Optional[List[Dict[str, Any]]]:
    """
    Guarda snapshot compacto de users para que el usuario pueda referirse por índice (#1..#N).
    Devuelve la lista normalizada si se pudo extraer.
    """
    users = _extract_users_list(result)
    if not users:
        return None

    normalized: List[Dict[str, Any]] = []
    for u in users[:DEFAULT_MAX_ITEMS]:
        userid = u.get("userid") or u.get("id")

        # orgid puede venir como objeto org:{orgid} o como orgid plano
        orgid = u.get("orgid")
        org = u.get("org")
        if orgid is None and isinstance(org, dict):
            orgid = org.get("orgid") or org.get("id")

        normalized.append(
            {
                "userid": userid,
                "username": u.get("username") or "",
                "givennames": u.get("givennames") or "",
                "surname": u.get("surname") or "",
                "email": u.get("email") or "",
                "mobile": u.get("mobile") or "",
                "phone": u.get("phone") or "",
                "archived": u.get("archived") if "archived" in u else None,
                "accesstype": u.get("accesstype") or "",
                "orgid": orgid,
            }
        )

    ctx = load_context()
    ctx["users_last_list"] = {
        "saved_at": _now(),
        "items": normalized,
    }
    save_context(ctx)
    return normalized


def get_user_by_index(idx_1based: int) -> Optional[Dict[str, Any]]:
    """
    idx_1based: 1..N
    """
    ctx = load_context()
    block = ctx.get("users_last_list")
    if not isinstance(block, dict):
        return None
    items = block.get("items")
    if not isinstance(items, list):
        return None

    i = idx_1based - 1
    if i < 0 or i >= len(items):
        return None
    return items[i]

def _extract_businessunits_list(tool_result: Any) -> List[Dict[str, Any]]:
    """
    Intenta extraer una lista de businessunits desde respuestas típicas:
    - resp["data"]["zoneresponse"]["businessunits"]
    - resp["zoneresponse"]["businessunits"]
    - resp["data"]["businessunits"]
    """
    if not isinstance(tool_result, dict):
        return []

    data = tool_result.get("data")
    if isinstance(data, dict):
        zr = data.get("zoneresponse")
        if isinstance(zr, dict) and isinstance(zr.get("businessunits"), list):
            return zr["businessunits"]
        if isinstance(data.get("businessunits"), list):
            return data["businessunits"]

    zr = tool_result.get("zoneresponse")
    if isinstance(zr, dict) and isinstance(zr.get("businessunits"), list):
        return zr["businessunits"]

    return []


def remember_businessunits_from_result(result: Dict[str, Any]) -> Optional[List[Dict[str, Any]]]:
    """
    Guarda snapshot compacto de businessunits (#1..#N).
    """
    items = _extract_businessunits_list(result)
    if not items:
        return None

    normalized: List[Dict[str, Any]] = []
    for bu in items[:DEFAULT_MAX_ITEMS]:
        # Campos defensivos: varían por tenant/join
        buid = bu.get("businessunitid") or bu.get("id") or bu.get("businessunit_id")
        normalized.append(
            {
                "businessunitid": buid,
                "businessunitname": bu.get("businessunitname") or bu.get("name") or "",
                "archived": bu.get("archived") if "archived" in bu else None,
                "orgid": (bu.get("org") or {}).get("orgid") if isinstance(bu.get("org"), dict) else bu.get("orgid"),
            }
        )

    ctx = load_context()
    ctx["businessunits_last_list"] = {
        "saved_at": _now(),
        "items": normalized,
    }
    save_context(ctx)
    return normalized


def get_businessunit_by_index(idx_1based: int) -> Optional[Dict[str, Any]]:
    ctx = load_context()
    block = ctx.get("businessunits_last_list")
    if not isinstance(block, dict):
        return None
    items = block.get("items")
    if not isinstance(items, list):
        return None

    i = idx_1based - 1
    if i < 0 or i >= len(items):
        return None
    return items[i]
