"""Run full `process v2` flow in the v4 harness.

This module adapts the existing v3 `V2ProcessAdapter` so pipeline_setup_v4 can
execute the real route -> retrieval -> evidence -> workflow LLM chain without
duplicating runtime logic.
"""

from __future__ import annotations

from tests.pipeline_setup_v3.core.models import CaseExpectations, CaseInput, V3Case
from tests.pipeline_setup_v3.runtime.v2_process_adapter import V2ProcessAdapter
from tests.pipeline_setup_v4.core.models import ExecutionPayload, V4Case


class ProcessV2FullChainExecutor:
    def __init__(self) -> None:
        self._adapter = V2ProcessAdapter(workflow_llm_enabled=False)

    def execute(self, case: V4Case) -> ExecutionPayload:
        if not case.rag_session_id:
            raise ValueError(f"Case '{case.case_id}' requires rag_session_id")
        payload = self._adapter.execute(self._build_case(case), case.rag_session_id)
        route = dict(payload.details.get("router_result") or {})
        retrieval_plan = dict(payload.details.get("retrieval_plan") or {})
        rows = list(payload.details.get("rows") or [])
        rag_summary = _summarize_rows(rows)
        pipeline_steps = list(payload.details.get("pipeline_steps") or [])
        pipeline_summary = {
            "answer_mode": str(payload.actual.get("answer_mode") or ""),
            "workflow_llm_enabled": False,
            "step_count": len(pipeline_steps),
            "steps": [str(step.get("step") or "") for step in pipeline_steps if str(step.get("step") or "").strip()],
        }
        answer = str(payload.details.get("answer") or payload.actual.get("llm_answer") or "")
        actual = {
            "domain": payload.actual.get("domain"),
            "intent": payload.actual.get("intent"),
            "sub_intent": payload.actual.get("sub_intent"),
            "profile": retrieval_plan.get("profile"),
            "layers": list(retrieval_plan.get("layers") or []),
            "limit": retrieval_plan.get("limit"),
            "filters": dict(retrieval_plan.get("filters") or {}),
            "answer_mode": payload.actual.get("answer_mode"),
            "route": {
                "routing_domain": route.get("routing_domain"),
                "intent": route.get("intent"),
                "subintent": route.get("subintent"),
                "target_terms": list(route.get("target_terms") or []),
                "anchors": dict(route.get("anchors") or {}),
            },
            "retrieval_plan": {
                "profile": retrieval_plan.get("profile"),
                "layers": list(retrieval_plan.get("layers") or []),
                "limit": retrieval_plan.get("limit"),
                "filters": dict(retrieval_plan.get("filters") or {}),
            },
            "rag": rag_summary,
            "pipeline": pipeline_summary,
            "llm": {
                "answer": answer,
                "non_empty": bool(answer.strip()),
                "length": len(answer),
            },
        }
        details = {
            "query": case.query,
            "rag_session_id": case.rag_session_id,
            "route": route,
            "retrieval_plan": actual["retrieval_plan"],
            "rag": {
                **rag_summary,
                "rows": rows[:20],
            },
            "pipeline": pipeline_summary,
            "answer": answer,
            "pipeline_steps": pipeline_steps,
            "logs": list(payload.details.get("logs") or []),
            "evidence": dict(payload.details.get("evidence") or {}),
        }
        return ExecutionPayload(actual=actual, details=details)

    def _build_case(self, case: V4Case) -> V3Case:
        return V3Case(
            case_id=case.case_id,
            runner="process_v2",
            mode="full_chain",
            query=case.query,
            source_file=case.source_file,
            input=CaseInput(rag_session_id=case.rag_session_id),
            expectations=CaseExpectations(),
            notes=case.notes,
            tags=case.tags,
        )


def _summarize_rows(rows: list[dict]) -> dict[str, object]:
    paths: list[str] = []
    layers: list[str] = []
    metadata_domains: list[str] = []
    metadata_subdomains: list[str] = []
    for row in rows:
        path = str(row.get("path") or "").strip()
        layer = str(row.get("layer") or "").strip()
        metadata = dict(row.get("metadata") or {})
        domain = str(row.get("metadata_domain") or metadata.get("domain") or "").strip()
        subdomain = str(row.get("metadata_subdomain") or metadata.get("subdomain") or "").strip()
        if path and path not in paths:
            paths.append(path)
        if layer and layer not in layers:
            layers.append(layer)
        if domain and domain not in metadata_domains:
            metadata_domains.append(domain)
        if subdomain and subdomain not in metadata_subdomains:
            metadata_subdomains.append(subdomain)
    return {
        "row_count": len(rows),
        "paths": paths,
        "layers": layers,
        "metadata_domains": metadata_domains,
        "metadata_subdomains": metadata_subdomains,
    }
