"""Layer 2: Per-lens analytical depth scoring via LLM judge."""

from __future__ import annotations

import re
from typing import Dict

from .llm_client import JudgeLLM
from .prompts import LENS_CRITERIA, LENS_DEPTH_SYSTEM_PROMPT, LENS_DEPTH_USER_PROMPT


def _parse_score(response: str) -> int:
    """Extract integer 1-5 from judge response."""
    m = re.search(r"Score:\s*(\d)", response)
    if m:
        return max(1, min(5, int(m.group(1))))
    # Fallback: first digit
    m = re.search(r"\d", response)
    return max(1, min(5, int(m.group(0)))) if m else 3


async def evaluate_layer2(
    judge: JudgeLLM,
    output: str,
    input_text: str,
    detected_lenses: Dict[str, bool],
    repeat: int = 3,
) -> Dict[str, float]:
    """Score each detected lens for depth (1-5), averaged over *repeat* runs.

    Returns e.g. ``{"Ontoloji": 3.67, "FOL": 4.33, ...}``.
    Lenses not detected get 0.0.
    """
    scores: Dict[str, float] = {}
    for lens, detected in detected_lenses.items():
        if not detected:
            scores[lens] = 0.0
            continue

        lens_scores: list[int] = []
        for _ in range(repeat):
            score = await _judge_one_lens(judge, output, input_text, lens)
            lens_scores.append(score)
        scores[lens] = sum(lens_scores) / len(lens_scores)

    return scores


async def _judge_one_lens(
    judge: JudgeLLM, output: str, input_text: str, lens_name: str
) -> int:
    """Ask judge to rate one lens's depth in the output."""
    criteria = LENS_CRITERIA.get(lens_name, "Evaluate substantive application of this lens.")
    user = LENS_DEPTH_USER_PROMPT.format(
        lens_name=lens_name,
        lens_criteria=criteria,
        input_text=input_text[:2000],
        output=output[:4000],
    )
    response = await judge.judge(LENS_DEPTH_SYSTEM_PROMPT, user)
    return _parse_score(response)
