"""Display utilities for normal mode output."""

import logging
import re
from rich.panel import Panel
from common.render import render_review_panel

logger = logging.getLogger(__name__)

NORMAL_SECTION_ORDER = [
    ("structure", "구조·복잡도"),
    ("error_handling", "예외·에러 처리"),
    ("logging", "로깅·관측성"),
    ("test_gap", "테스트"),
    ("doc_gap", "문서·주석"),
]


def _extract_anchor_tokens(text: str | object, max_tokens: int = 3) -> list[str]:
    if not text:
        return []
    if not isinstance(text, str):
        text = " ".join(map(str, text)) if isinstance(text, (list, tuple, set)) else str(text)
    candidates = re.findall(r"[A-Za-z_][A-Za-z0-9_]*", text)
    seen: set[str] = set()
    tokens: list[str] = []
    for token in candidates:
        if token in seen:
            continue
        seen.add(token)
        tokens.append(token)
        if len(tokens) >= max_tokens:
            break
    return tokens


def _map_normal_section(finding) -> str | None:
    category = getattr(finding, "category", "")
    subtype = getattr(finding, "subtype", "")
    if category == "structure":
        return "structure"
    if category == "operation":
        if subtype == "error_handling":
            return "error_handling"
        if subtype == "logging":
            return "logging"
    if category == "test_doc":
        if subtype == "test_gap":
            return "test_gap"
        if subtype == "doc_gap":
            return "doc_gap"
    return None


def _build_normal_sections(findings: list) -> dict[str, list[tuple[str, str]]]:
    sections = {key: [] for key, _label in NORMAL_SECTION_ORDER}
    for f in findings:
        section_key = _map_normal_section(f)
        if not section_key:
            continue
        evidence = getattr(f, "evidence", "")
        anchors = _extract_anchor_tokens(evidence)
        if not anchors:
            continue
        file_path = _short_path(getattr(f, "file_path", "unknown"))
        location = f"{file_path}:{anchors[0]}"
        message = (getattr(f, "message", "") or "").strip()
        fix = (getattr(f, "min_fix", "") or "").strip()
        if not message or not fix:
            continue
        anchor_text = ", ".join(anchors)
        risk_line = f"{location} — {message} (anchor: {anchor_text})"
        sections[section_key].append((risk_line, fix))
    return sections


def build_normal_panel(result: dict) -> Panel:
    files = result.get("files_analyzed", [])
    if files:
        summary = ", ".join([_short_path(str(p)) for p in files[:3]])
        if len(files) > 3:
            summary += f" ... (+{len(files) - 3})"
        header = f"{summary}"
    else:
        header = "no files"
    status = result.get("status", "unknown")
    findings = result.get("findings", [])
    sections = _build_normal_sections(findings) if status == "success" else {k: [] for k, _ in NORMAL_SECTION_ORDER}
    notice = None if status == "success" else (result.get("message") or "분석 결과를 생성하지 못했습니다.")
    return render_review_panel(
        mode="normal",
        file_summary=header,
        section_order=NORMAL_SECTION_ORDER,
        sections=sections,
        title="Normal Review",
        notice=notice,
    )


def _short_path(path: str) -> str:
    """Get short version of file path."""
    if not path:
        return "unknown"
    parts = path.split("/")
    if len(parts) > 3:
        return "/".join(parts[-3:])
    return path
