"""Cross-Group Analyst Agent — detects blind spots between multiple teams."""

import logging
from backend.providers import call_llm
from backend.db.chroma import get_all_signals, get_group_ids
from backend.db.models import CrossGroupInsight
from backend.agents.json_utils import extract_json_object

logger = logging.getLogger("thirdeye.agents.cross_group_analyst")

SYSTEM_PROMPT = """You are the Cross-Group Intelligence Analyst for ThirdEye. This is the MOST IMPORTANT analysis.

You receive intelligence summaries from MULTIPLE Telegram groups. Your job is to find BLIND SPOTS — information in one group that should be in another.

Detect:
- blocked_handoff: Team A waiting for something from Team B, but Team B doesn't know
- conflicting_decision: Team A decided X, Team B decided the opposite
- information_silo: Critical info in Group A never reached Group B
- promise_reality_gap: Promise made in one group, but another group shows it's blocked
- duplicated_effort: Two teams working on similar things unknowingly

Respond ONLY with valid JSON (no markdown):
{"insights": [{"type": "insight_type", "description": "SPECIFIC description naming the groups, people, and topics", "group_a": {"name": "group_name", "evidence": "what was said"}, "group_b": {"name": "group_name", "evidence": "what was said or NOT said"}, "severity": "warning|critical", "recommendation": "Specific action"}]}

If no cross-group issues: {"insights": []}
Be SPECIFIC. Name the groups, people, topics, and exact conflicts."""


def _heuristic_cross_group_insights(
    group_summaries: dict[str, list[dict]],
) -> list[CrossGroupInsight]:
    """Generate best-effort cross-group insights when LLM output is unavailable."""
    insights: list[CrossGroupInsight] = []

    normalized = {}
    for group_name, signals in group_summaries.items():
        docs = [str(s.get("document", "")) for s in signals]
        combined = " ".join(docs).lower()
        signal_types = []
        for s in signals:
            signal_types.append(
                str(s.get("metadata", {}).get("type", "unknown")).lower()
            )
        normalized[group_name] = {
            "text": combined,
            "signals": signals,
            "types": signal_types,
        }

    group_names = list(normalized.keys())
    for i in range(len(group_names)):
        for j in range(i + 1, len(group_names)):
            group_a = group_names[i]
            group_b = group_names[j]
            text_a = normalized[group_a]["text"]
            text_b = normalized[group_b]["text"]
            types_a = set(normalized[group_a]["types"])
            types_b = set(normalized[group_b]["types"])

            # Detect a likely blocked handoff around design/spec dependencies.
            a_waiting = any(
                k in text_a for k in ["waiting", "blocked", "design spec", "specs"]
            )
            b_mentions_specs = any(
                k in text_b for k in ["design spec", "specs", "design"]
            )
            if a_waiting and not b_mentions_specs:
                insights.append(
                    CrossGroupInsight(
                        type="blocked_handoff",
                        description=(
                            f"{group_a} indicates dependency blockage (design/spec inputs), "
                            f"but {group_b} has no corresponding discussion of that dependency."
                        ),
                        group_a={
                            "name": group_a,
                            "evidence": "Contains waiting/blocked language tied to specs or design dependency.",
                        },
                        group_b={
                            "name": group_b,
                            "evidence": "No clear mention of design specs/dependency handoff in available signals.",
                        },
                        severity="warning",
                        recommendation=(
                            f"Create a shared handoff item between {group_a} and {group_b} for design/spec ownership "
                            "with an explicit due date."
                        ),
                    )
                )

            # Detect likely promise vs execution mismatch.
            b_promises = any(
                k in text_b
                for k in ["demo", "friday", "promised", "told the client", "ready by"]
            )
            a_blocked = any(
                k in text_a
                for k in ["blocked", "waiting", "can't proceed", "cannot proceed"]
            )
            if b_promises and a_blocked:
                insights.append(
                    CrossGroupInsight(
                        type="promise_reality_gap",
                        description=(
                            f"{group_b} signals delivery promises while {group_a} reports blockers that may prevent those commitments."
                        ),
                        group_a={
                            "name": group_a,
                            "evidence": "Signals include active blockers/waiting dependencies.",
                        },
                        group_b={
                            "name": group_b,
                            "evidence": "Signals include explicit client/demo commitments and timelines.",
                        },
                        severity="critical",
                        recommendation="Run a joint risk review and re-baseline commitments before the next client update.",
                    )
                )

            # Type-based silo detection when lexical cues are weak.
            a_operational_risk = bool(
                types_a.intersection(
                    {"recurring_bug", "workaround", "tech_debt", "deployment_risk"}
                )
            )
            b_planning_focus = bool(
                types_b.intersection(
                    {
                        "feature_request",
                        "roadmap_drift",
                        "priority_conflict",
                        "user_pain_point",
                    }
                )
            )
            if a_operational_risk and b_planning_focus:
                insights.append(
                    CrossGroupInsight(
                        type="information_silo",
                        description=(
                            f"{group_a} shows operational risk signals while {group_b} is focused on planning/user demands, "
                            "suggesting risk context is not shared across groups."
                        ),
                        group_a={
                            "name": group_a,
                            "evidence": f"Operational risk signal types: {sorted(types_a.intersection({'recurring_bug', 'workaround', 'tech_debt', 'deployment_risk'}))}",
                        },
                        group_b={
                            "name": group_b,
                            "evidence": f"Planning-focused signal types: {sorted(types_b.intersection({'feature_request', 'roadmap_drift', 'priority_conflict', 'user_pain_point'}))}",
                        },
                        severity="warning",
                        recommendation="Add a weekly cross-functional risk sync so product planning reflects current engineering constraints.",
                    )
                )

            # Check reverse direction as well.
            b_operational_risk = bool(
                types_b.intersection(
                    {"recurring_bug", "workaround", "tech_debt", "deployment_risk"}
                )
            )
            a_planning_focus = bool(
                types_a.intersection(
                    {
                        "feature_request",
                        "roadmap_drift",
                        "priority_conflict",
                        "user_pain_point",
                    }
                )
            )
            if b_operational_risk and a_planning_focus:
                insights.append(
                    CrossGroupInsight(
                        type="information_silo",
                        description=(
                            f"{group_b} shows operational risk signals while {group_a} is focused on planning/user demands, "
                            "suggesting risk context is not shared across groups."
                        ),
                        group_a={
                            "name": group_b,
                            "evidence": f"Operational risk signal types: {sorted(types_b.intersection({'recurring_bug', 'workaround', 'tech_debt', 'deployment_risk'}))}",
                        },
                        group_b={
                            "name": group_a,
                            "evidence": f"Planning-focused signal types: {sorted(types_a.intersection({'feature_request', 'roadmap_drift', 'priority_conflict', 'user_pain_point'}))}",
                        },
                        severity="warning",
                        recommendation="Add a weekly cross-functional risk sync so product planning reflects current engineering constraints.",
                    )
                )

    deduped = []
    seen_keys = set()
    for insight in insights:
        key = (insight.type, insight.group_a.get("name"), insight.group_b.get("name"))
        if key in seen_keys:
            continue
        seen_keys.add(key)
        deduped.append(insight)

    return deduped[:5]


async def analyze_cross_group(
    group_summaries: dict[str, list[dict]] = None,
) -> list[CrossGroupInsight]:
    """
    Analyze intelligence across all monitored groups to find blind spots.

    Args:
        group_summaries: Optional pre-built summaries. If None, loads from ChromaDB.
    """
    if group_summaries is None:
        group_ids = get_group_ids()
        if len(group_ids) < 2:
            logger.info("Need at least 2 groups for cross-group analysis")
            return []

        group_summaries = {}
        for gid in group_ids:
            signals = get_all_signals(gid)
            group_summaries[gid] = signals

    if len(group_summaries) < 2:
        return []

    # Format summaries for the LLM
    summary_parts = []
    for group_name, signals in group_summaries.items():
        signal_lines = []
        for s in signals[:30]:  # Limit per group to fit context
            meta = s["metadata"]
            signal_lines.append(f"  - [{meta.get('type', '?')}] {s['document'][:120]}")

        summary_parts.append(
            f"=== GROUP: {group_name} ({len(signals)} total signals) ===\n"
            + "\n".join(signal_lines)
        )

    full_summary = "\n\n".join(summary_parts)

    messages = [
        {"role": "system", "content": SYSTEM_PROMPT},
        {
            "role": "user",
            "content": f"Analyze cross-group intelligence:\n\n{full_summary}",
        },
    ]

    try:
        result = await call_llm(
            "reasoning",
            messages,
            temperature=0.2,
            max_tokens=2000,
            response_format={"type": "json_object"},
        )
        parsed = extract_json_object(result.get("content", ""))
        insights = []
        for i in parsed.get("insights", []):
            insights.append(
                CrossGroupInsight(
                    type=i.get("type", "unknown"),
                    description=i.get("description", ""),
                    group_a=i.get("group_a", {}),
                    group_b=i.get("group_b", {}),
                    severity=i.get("severity", "warning"),
                    recommendation=i.get("recommendation", ""),
                )
            )

        logger.info(f"Cross-group analysis found {len(insights)} insights")
        return insights

    except Exception as e:
        raw = ""
        if "result" in locals() and isinstance(result, dict):
            raw = str(result.get("content", ""))[:300].replace("\n", " ")
        logger.info(f"Cross-group LLM parse issue, using fallback: {e}; raw_head={raw}")
        fallback = _heuristic_cross_group_insights(group_summaries)
        if fallback:
            logger.info(
                f"Cross-group heuristic fallback produced {len(fallback)} insights"
            )
        return fallback
