#!/usr/bin/env python3
"""
utils/context_summarizer.py — 규칙 기반 컨텍스트 요약

LLM 호출 없이 Goal/Progress/Decisions/Files/NextSteps 구조로
중간 구역 turns를 요약한다.

Usage:
    from utils.context_summarizer import generate_summary, serialize_for_summary

    summary = generate_summary(turns, prev_summary="...")
"""

from __future__ import annotations

import os

from utils.logger import get_logger

logger = get_logger(__name__)

_LLM_SUMMARY_MODEL = "claude-haiku-4-5-20251001"


def serialize_for_summary(turns: list[dict]) -> str:
    """turns를 요약용 텍스트로 직렬화한다.

    tool_calls 이름과 tool 결과를 레이블 텍스트로 변환한다.

    Args:
        turns: 메시지 dict 목록

    Returns:
        직렬화된 텍스트 문자열
    """
    lines: list[str] = []
    for msg in turns:
        role = msg.get("role", "unknown")
        content = msg.get("content") or ""
        tool_calls = msg.get("tool_calls")
        tool_call_id = msg.get("tool_call_id")

        if tool_calls:
            names = [tc.get("function", {}).get("name", "?") for tc in tool_calls if isinstance(tc, dict)]
            lines.append(f"[{role}] tool_calls: {', '.join(names)}")
            if content:
                lines.append(f"  content: {content[:200]}")
        elif tool_call_id:
            snippet = content[:200] if content else "(empty)"
            lines.append(f"[{role}] tool_result({tool_call_id}): {snippet}")
        else:
            snippet = content[:300] if content else "(empty)"
            lines.append(f"[{role}] {snippet}")
    return "\n".join(lines)


def _try_llm_summary(turns: list[dict], prev_summary: str | None) -> str | None:
    """Anthropic API (haiku)를 사용하여 구조화 요약을 생성한다.

    API 키 미설정, 네트워크 오류 등 모든 실패 시 None을 반환한다.

    Args:
        turns: 요약할 메시지 dict 목록
        prev_summary: 이전 요약 텍스트

    Returns:
        LLM 생성 요약 문자열 또는 None
    """
    api_key = os.environ.get("ANTHROPIC_API_KEY")
    if not api_key:
        logger.debug("ANTHROPIC_API_KEY 미설정, LLM 요약 스킵")
        return None

    try:
        import anthropic

        client = anthropic.Anthropic(api_key=api_key)

        serialized = serialize_for_summary(turns)
        prompt_parts = ["아래 대화 내용을 구조화 요약하세요.\n형식: Goal / Progress / Decisions / Files / NextSteps\n"]
        if prev_summary:
            prompt_parts.append(f"이전 요약:\n{prev_summary}\n")
        prompt_parts.append(f"대화 내용:\n{serialized}")

        response = client.messages.create(
            model=_LLM_SUMMARY_MODEL,
            max_tokens=1024,
            messages=[{"role": "user", "content": "\n".join(prompt_parts)}],
        )

        if response.content and len(response.content) > 0:
            text = getattr(response.content[0], "text", None)
            if text:
                result = text.strip()
                if result:
                    return f"[LLM 요약]\n{result}"
    except Exception as e:
        logger.warning("LLM 요약 생성 실패: %s", e)

    return None


def generate_summary(turns: list[dict], prev_summary: str | None = None, *, use_llm: bool = False) -> str | None:
    """중간 구역 turns를 구조화 요약 문자열로 반환한다.

    use_llm=False: 규칙 기반 (Goal/Progress/Decisions/Files/NextSteps).
    use_llm=True: Anthropic API (haiku)로 구조화 요약 생성. 실패 시 규칙 기반 fallback.
    빈 turns이면 None 반환.

    Args:
        turns: 요약할 메시지 dict 목록
        prev_summary: 이전 압축 시 생성된 요약 (iterative 누적용)
        use_llm: True이면 LLM 요약 시도 (기본값: False)

    Returns:
        구조화 요약 문자열 또는 None
    """
    if not turns:
        return None

    if use_llm:
        llm_result = _try_llm_summary(turns, prev_summary)
        if llm_result is not None:
            return llm_result
        logger.info("LLM 요약 실패, 규칙 기반 fallback 사용")

    # 역할별 분류
    user_msgs: list[str] = []
    assistant_msgs: list[str] = []
    tool_names: list[str] = []
    file_refs: list[str] = []

    for msg in turns:
        role = msg.get("role", "")
        content = msg.get("content") or ""
        tool_calls = msg.get("tool_calls")

        if role == "user" and content:
            user_msgs.append(content[:200])
        elif role == "assistant":
            if content:
                assistant_msgs.append(content[:200])
            if tool_calls:
                for tc in tool_calls:
                    if isinstance(tc, dict):
                        fn = tc.get("function", {})
                        name = fn.get("name", "")
                        args = fn.get("arguments", "")
                        tool_names.append(name)
                        # 파일 경로 추출 (간단 휴리스틱)
                        if "path" in args or "file" in args.lower():
                            import re

                            found = re.findall(r'["\']([^"\']+\.[a-z]{2,4})["\']', args)
                            file_refs.extend(found[:3])

    # 구조화 요약 조립
    sections: list[str] = ["[압축 요약]"]

    if prev_summary:
        sections.append(f"이전 요약:\n{prev_summary.strip()}")

    if user_msgs:
        goals = "; ".join(user_msgs[:3])
        sections.append(f"Goal: {goals}")

    if assistant_msgs:
        progress = "; ".join(assistant_msgs[:3])
        sections.append(f"Progress: {progress}")

    if tool_names:
        unique_tools = list(dict.fromkeys(tool_names))  # 순서 유지 중복 제거
        sections.append(f"Actions: {', '.join(unique_tools[:10])}")

    if file_refs:
        unique_files = list(dict.fromkeys(file_refs))
        sections.append(f"Files: {', '.join(unique_files[:10])}")

    turn_count = len(turns)
    sections.append(f"(압축된 턴 수: {turn_count})")

    return "\n".join(sections)
