"""skills/comparador_finalistas.py — COMPARADOR (estación 5)

Cruza candidatos vs ganador. Selecciona 5 SIMILARES + 1 ARRIESGADO.
Skill canónica: comparador-finalistas.

Backend: claude CLI subprocess (LLM Opus 4.7 para scoring multidimensional).
"""
from __future__ import annotations
import json
from skills._lib import SkillContext, SkillResult


def run(inputs: dict, context: SkillContext) -> SkillResult:
    caja = context.read_caja()
    analyze = caja.get('sections', {}).get('analizar') or {}
    busc = caja.get('sections', {}).get('buscar') or {}
    combo = analyze.get('combo_completo') or {}
    candidates = busc.get('candidates_validated') or []

    if not combo:
        return SkillResult(ok=False, errors=['caja.analizar.combo_completo vacío'])
    if len(candidates) < 6:
        return SkillResult(ok=False, errors=[f'Necesitamos ≥6 candidatos, hay {len(candidates)} — relanzar buscadores'])

    prompt = build_compare_prompt(combo, candidates)
    res = context.claude_cli(prompt, model='claude-opus-4-7', timeout_s=240)
    if not res.get('ok'):
        return SkillResult(ok=False, errors=[f'claude CLI falló: {res.get("stderr") or res.get("error")}'])

    try:
        parsed = json.loads(extract_json(res.get('stdout', '')))
    except Exception as e:
        return SkillResult(ok=False, errors=[f'JSON parse error: {e}', res.get('stdout', '')[:500]])

    finalistas = parsed.get('finalistas') or []
    similares = [f for f in finalistas if f.get('tipo') == 'similar']
    arriesgados = [f for f in finalistas if f.get('tipo') == 'arriesgado']

    if len(similares) != 5 or len(arriesgados) != 1:
        return SkillResult(ok=False, errors=[
            f'Esperaba 5 similares + 1 arriesgado, recibí {len(similares)}+{len(arriesgados)}'
        ])

    context.write_section('comparador', parsed, mode='replace', actor='comparador-finalistas')
    return SkillResult(ok=True, output={'count_similares': 5, 'count_arriesgados': 1})


def build_compare_prompt(combo: dict, candidates: list) -> str:
    combo_s = json.dumps(combo, ensure_ascii=False, indent=2)
    cand_s = json.dumps(candidates[:30], ensure_ascii=False, indent=2)  # cap 30 para prompt
    return f"""Eres el agente COMPARADOR del flow Factory v4 escalado de formato.
Tu tarea: de los candidatos abajo, elegir EXACTAMENTE 6 finalistas: 5 similares + 1 arriesgado.

COMBO COMPLETO DEL GANADOR:
{combo_s}

CANDIDATOS (de los 4 buscadores paralelos):
{cand_s}

CRITERIO scoring (multidim, pesos):
  awareness 0.20, sof 0.15, jergas 0.10, deseo 0.15, avatar 0.15,
  temporalidad 0.10, fuerza_cambio 0.10, formato 0.05.

REGLAS DURAS:
- 5+1 OBLIGATORIO. Nunca 6 similares ni 4 similares.
- 5 SIMILARES = top 5 por score · score ≥ 0.65.
- 1 ARRIESGADO = score 0.65-0.85 con UN diferenciador claro (formato distinto, avatar lateral, ángulo nuevo).
- En mercado saturado: rechazar UGC talking-head básico problem→solution.

Devuelve JSON estricto:
{{
  "finalistas": [
    {{
      "rank": 1, "tipo": "similar", "video_url": "...", "video_id": "...",
      "match_score": 0.92,
      "match_breakdown": {{"awareness": 1.0, "sof": 1.0, "jergas": 0.85, "deseo": 1.0, "avatar": 0.90, "temporalidad": 1.0, "fuerza_cambio": 0.88, "formato": 0.95}},
      "por_que_similar": "..."
    }},
    ... 4 más similares ...,
    {{
      "rank": 6, "tipo": "arriesgado", "video_url": "...", "match_score": 0.74,
      "diferenciador": "..."
    }}
  ],
  "rejected_count": <int>,
  "rejected_reasons_summary": {{...}}
}}

Responde SOLO con el JSON."""


def extract_json(stdout: str) -> str:
    s = stdout.strip()
    if s.startswith('```'):
        parts = s.split('```', 2)
        if len(parts) >= 2:
            s = parts[1]
            if s.startswith('json'):
                s = s[4:].strip()
    try:
        first = s.index('{')
        last = s.rindex('}')
        return s[first:last+1]
    except Exception:
        return s
