"""
Session context helpers — tool trace, workflow artifacts, continuity summaries.

Extracted from main.py to keep individual modules manageable.
"""

import json
from datetime import datetime

from backend.response_composers import build_tool_result_details, compact_tool_result_for_context


# ---------------------------------------------------------------------------
# Session tool-trace helpers
# ---------------------------------------------------------------------------

def _task_time_phrase(task_state: dict | None, dutch: bool) -> str:
    task = dict(task_state or {})
    time_filter = str(task.get("time_filter") or "none")
    if time_filter == "today":
        return "voor vandaag" if dutch else "for today"
    if time_filter == "yesterday":
        return "voor gisteren" if dutch else "for yesterday"
    if time_filter == "this_week":
        return "voor deze week" if dutch else "for this week"
    if time_filter == "last_week":
        return "voor vorige week" if dutch else "for last week"
    if time_filter == "this_month":
        return "voor deze maand" if dutch else "for this month"
    days_ahead = int(task.get("days_ahead") or 0)
    if str(task.get("task_type") or "") == "calendar_lookup":
        if days_ahead == 1:
            return "voor vandaag" if dutch else "for today"
        if days_ahead == 2:
            return "voor morgen" if dutch else "for tomorrow"
        if days_ahead == 7:
            return "voor deze week" if dutch else "for this week"
        if days_ahead == 14:
            return "voor volgende week" if dutch else "for next week"
    return ""


def _tool_phrase(tool_name: str, dutch: bool) -> str:
    mapping = {
        "outlook_read_calendar": "in je Outlook-agenda" if dutch else "in your Outlook calendar",
        "google_read_calendar": "in je Google Agenda" if dutch else "in your Google Calendar",
        "outlook_get_inbox": "in je Outlook-mailbox" if dutch else "in your Outlook mailbox",
        "outlook_search_emails": "in je Outlook-mailbox" if dutch else "in your Outlook mailbox",
        "gmail_get_inbox": "in je Gmail" if dutch else "in your Gmail",
        "gmail_search_emails": "in je Gmail" if dutch else "in your Gmail",
        "web_search": "op het web" if dutch else "on the web",
        "fetch_url": "op de opgegeven website" if dutch else "on the requested website",
        "extract_source": "in de opgegeven bron" if dutch else "in the requested source",
    }
    return mapping.get(str(tool_name or "").strip(), "")


def _session_tool_trace(session: dict | None) -> list[dict]:
    trace: list[dict] = []
    source = session or {}
    raw_trace = source.get("last_tool_trace") or []
    if isinstance(raw_trace, list):
        for item in raw_trace:
            if not isinstance(item, dict):
                continue
            tool_name = str(item.get("tool_name") or item.get("tool") or "").strip()
            if not tool_name:
                continue
            trace.append({
                "tool_name": tool_name,
                "tool_result": str(item.get("tool_result") or item.get("result") or ""),
                "tool_details": dict(item.get("tool_details") or {}),
            })
    if trace:
        return trace

    for step in source.get("steps") or []:
        if not isinstance(step, dict):
            continue
        tool_name = str(step.get("tool_name") or "").strip()
        if not tool_name:
            continue
        trace.append({
            "tool_name": tool_name,
            "tool_result": str(step.get("tool_result") or ""),
            "tool_details": dict(step.get("tool_details") or {}),
        })
    if trace:
        return trace

    for item in _workflow_context_artifacts(source):
        tool_name = str(item.get("tool_name") or "").strip()
        if not tool_name:
            continue
        trace.append({
            "tool_name": tool_name,
            "tool_result": str(item.get("tool_result") or ""),
            "tool_details": dict(item.get("tool_details") or {}),
        })
    return trace


def _build_compacted_tool_trace(items: list[tuple[str, str]] | list[dict]) -> list[dict]:
    trace: list[dict] = []
    for item in items:
        if isinstance(item, tuple):
            tool_name = str(item[0] or "").strip()
            tool_result = str(item[1] or "")
            raw_tool_details: dict | None = None
        elif isinstance(item, dict):
            tool_name = str(item.get("tool_name") or item.get("tool") or "").strip()
            tool_result = str(item.get("tool_result") or item.get("result") or "")
            raw_tool_details = dict(item.get("tool_details") or {})
        else:
            continue
        if not tool_name:
            continue
        tool_details = dict(raw_tool_details or build_tool_result_details(tool_name, tool_result))
        trace.append({
            "tool_name": tool_name,
            "tool_result": compact_tool_result_for_context(tool_name, tool_result, tool_details),
            "tool_details": tool_details,
        })
    return trace


def _workflow_context_artifacts(session: dict | None) -> list[dict]:
    source = session or {}
    ctx = source.get("workflow_context") if isinstance(source.get("workflow_context"), dict) else {}
    artifacts = ctx.get("artifacts") if isinstance(ctx.get("artifacts"), list) else []
    return [item for item in artifacts if isinstance(item, dict)]


def _append_workflow_context_artifact(
    session: dict | None,
    *,
    tool_name: str,
    tool_result: str,
    tool_args: dict | None = None,
    tool_details: dict | None = None,
    stage: str = "",
) -> None:
    if not isinstance(session, dict):
        return
    name = str(tool_name or "").strip()
    if not name:
        return

    details = dict(tool_details or {})
    compact_result = compact_tool_result_for_context(name, str(tool_result or ""), details)
    record = {
        "tool_name": name,
        "tool_args": dict(tool_args or {}),
        "tool_result": compact_result,
        "tool_details": details,
        "stage": str(stage or ""),
        "created_at": datetime.now().isoformat(),
    }

    workflow_context = session.get("workflow_context") if isinstance(session.get("workflow_context"), dict) else {}
    artifacts = workflow_context.get("artifacts") if isinstance(workflow_context.get("artifacts"), list) else []
    artifacts.append(record)
    workflow_context["artifacts"] = artifacts[-80:]
    session["workflow_context"] = workflow_context


def _infer_tool_trace_from_task_state(session: dict | None) -> list[dict]:
    source = session or {}
    task = dict(source.get("task_state") or {})
    task_type = str(task.get("task_type") or "")
    provider_scope = str(task.get("provider_scope") or "default")
    tool_names: list[str] = []

    if task_type == "calendar_lookup":
        if provider_scope == "outlook_only":
            tool_names = ["outlook_read_calendar"]
        elif provider_scope == "gmail_only":
            tool_names = ["google_read_calendar"]
        elif provider_scope == "cross_provider":
            tool_names = ["outlook_read_calendar", "google_read_calendar"]
        elif bool(source.get("use_outlook", False)):
            tool_names = ["outlook_read_calendar"]
    elif task_type == "email_lookup":
        if provider_scope == "outlook_only":
            tool_names = ["outlook_get_inbox"]
        elif provider_scope == "gmail_only":
            tool_names = ["gmail_get_inbox"]
        elif provider_scope == "cross_provider":
            tool_names = ["outlook_get_inbox", "gmail_get_inbox"]
        elif bool(source.get("use_outlook", False)):
            tool_names = ["outlook_get_inbox"]

    return [{"tool_name": name, "tool_result": ""} for name in tool_names if name]


def _stable_json(value: object) -> str:
    return json.dumps(value, ensure_ascii=True, sort_keys=True, separators=(",", ":"), default=str)
