"""Condition 2: SCAFFOLD_FULL — Full MCP pipeline with all 7 lenses.

Calls ``dusun_tool()`` exactly as an MCP client would — full 7-lens
pipeline, structured scoring, hints extraction, the works.
The LLM then produces a direct multi-lens analysis of the TEXT,
guided by dusun's computed findings as analytical scaffolding.
"""

from __future__ import annotations

import json
from typing import Any, Dict, List

from fw_server.server import dusun_tool
from fw_server.session import reset_ledger

from .base import ConditionOutput, ConditionRunner

SYNTHESIS_PROMPT = """\
You are an expert analyst. A structured 7-lens analytical framework has
pre-analyzed the text below and produced the findings shown under
ANALYTICAL SCAFFOLDING. Use these computed findings — lens relevance
scores, detected patterns, and analytical directives — as a starting
point and guide for your own deep analysis OF THE TEXT ITSELF.

Do NOT describe the framework's metrics or scores as your analysis.
Instead, use them to inform where to look and what to emphasize.

=== ANALYTICAL SCAFFOLDING (computed by structured framework) ===
Domain path: {path}
Lenses fired: {fire_plan}
Lens relevance scores: {lens_scores_fmt}

Detected patterns and their analytical significance:
{pattern_directives_fmt}

Analytical guidance: {path_guidance}
{anomaly_note}
=== END SCAFFOLDING ===

Analyze the following text through these 7 analytical perspectives.
For each perspective, provide substantive analysis (not just mention).
Pay special attention to lenses with higher relevance scores and the
detected patterns above.

1. **Ontological Analysis**: Identify the core entities, their categories,
   hierarchical relations, and constitutive dependencies.

2. **Mereological Analysis**: Identify whole-part structures, teleological
   relations between parts, and how parts relate to the whole.

3. **Formal Logic (FOL)**: Identify premises, conclusions, logical structure.
   Formalize key arguments. Check for validity and soundness.

4. **Bayesian Analysis**: Identify hypotheses, evidence, prior probabilities.
   Show how evidence updates beliefs. Quantify where possible.

5. **Game-Theoretic Analysis**: Identify agents/players, strategies, payoffs,
   equilibria. What incentive structures are at play?

6. **Category-Theoretic Analysis**: Identify objects, morphisms, functors.
   What structural transformations preserve essential properties?

7. **Topological/Holographic Analysis**: Identify dimensional structure,
   continuity properties, seed-whole relationships, fractal patterns.

After analyzing each lens, synthesize: How do the lenses connect?
What does the combination reveal that no single lens shows alone?

Text:
{text}
"""


def _format_scaffolding(result: dict) -> dict:
    """Extract analytically useful parts from dusun result for the prompt."""
    lens_scores = result.get("lens_scores", {})
    lens_scores_fmt = ", ".join(
        f"{k}: {v:.2f}" for k, v in lens_scores.items()
    )

    sd = result.get("shaping_directives") or {}
    pattern_dirs: List[dict] = sd.get("pattern_directives", [])
    if pattern_dirs:
        lines = [f"  - {pd['pattern']}: {pd['apply']}" for pd in pattern_dirs]
        pattern_directives_fmt = "\n".join(lines)
    else:
        patterns = result.get("patterns_applied", [])
        pattern_directives_fmt = (
            ", ".join(patterns) if patterns else "(none detected)"
        )

    path_guidance = sd.get("path_guidance", "")

    anomalies = result.get("anomalies", [])
    if anomalies:
        anomaly_note = "Anomalies noted: " + "; ".join(anomalies[:3])
    else:
        anomaly_note = ""

    return {
        "path": result.get("path", "unknown"),
        "fire_plan": ", ".join(result.get("fire_plan", [])),
        "lens_scores_fmt": lens_scores_fmt,
        "pattern_directives_fmt": pattern_directives_fmt,
        "path_guidance": path_guidance,
        "anomaly_note": anomaly_note,
    }


class ScaffoldFullRunner(ConditionRunner):
    """Condition 2 — full dusun 7-lens MCP pipeline."""

    def __init__(self, llm_client=None):
        self.llm_client = llm_client

    def condition_id(self) -> str:
        return "SCAFFOLD_FULL"

    async def run(self, text: str, text_id: str) -> ConditionOutput:
        reset_ledger()

        raw = await dusun_tool(
            text=text,
            ctx=None,
            context=None,
            mode="analyze",
        )
        result: Dict[str, Any] = json.loads(raw)

        narrative = await self._synthesize_narrative(text, result)

        return ConditionOutput(
            condition_id="SCAFFOLD_FULL",
            text_id=text_id,
            raw_output=narrative,
            metadata={
                "structured_result": result,
                "composite_score": result.get("composite_score"),
                "grade": result.get("grade"),
                "fire_plan": result.get("fire_plan"),
                "lens_scores": result.get("lens_scores"),
                "kavaid": result.get("kavaid"),
                "patterns_applied": result.get("patterns_applied"),
            },
        )

    # ------------------------------------------------------------------

    async def _synthesize_narrative(self, text: str, result: dict) -> str:
        """Produce multi-lens analysis of TEXT, scaffolded by dusun findings."""
        if self.llm_client is None:
            return json.dumps(result, indent=2, ensure_ascii=False)
        scaffolding = _format_scaffolding(result)
        prompt = SYNTHESIS_PROMPT.format(text=text, **scaffolding)
        return await self.llm_client.generate(prompt)
