"""변경 로그 관리 모듈"""

import json
import os
from datetime import datetime, timezone
from pathlib import Path
from typing import Any, Optional

_WORKSPACE_ROOT = os.environ.get(
    "WORKSPACE_ROOT", str(Path(__file__).resolve().parent.parent.parent)
)


def create_log(skill_name: str) -> dict[str, Any]:
    """새로운 changelog 구조 생성.

    Returns:
        {
            "skill": str,
            "started_at": ISO timestamp,
            "rounds": [],
            "final_score": 0,
            "total_rounds": 0,
            "kept": 0,
            "reverted": 0,
        }
    """
    return {
        "skill": skill_name,
        "started_at": datetime.now(tz=timezone.utc).isoformat(),
        "rounds": [],
        "final_score": 0,
        "total_rounds": 0,
        "kept": 0,
        "reverted": 0,
    }


def add_round(
    log: dict[str, Any],
    round_num: int,
    mutation_type: str,
    mutation_description: str,
    score_before: float,
    score_after: float,
    items_detail: list[Any],
    decision: str,
    input_tokens: int = 0,
    output_tokens: int = 0,
    mutation_input_tokens: int = 0,
    mutation_output_tokens: int = 0,
    execution_input_tokens: int = 0,
    execution_output_tokens: int = 0,
    judge_input_tokens: int = 0,
    judge_output_tokens: int = 0,
) -> dict[str, Any]:
    """라운드 결과를 로그에 추가.

    Args:
        log: 현재 changelog dict
        round_num: 라운드 번호
        mutation_type: 변경 유형 (예: "rewrite", "append")
        mutation_description: 변경 내용 설명
        score_before: 변경 전 점수
        score_after: 변경 후 점수
        items_detail: 개별 항목 점수 리스트
        decision: "kept" 또는 "reverted"
        input_tokens: 사용된 입력 토큰 수 (전체 합산)
        output_tokens: 사용된 출력 토큰 수 (전체 합산)
        mutation_input_tokens: 뮤테이션 단계 입력 토큰 수
        mutation_output_tokens: 뮤테이션 단계 출력 토큰 수
        execution_input_tokens: 실행 단계 입력 토큰 수
        execution_output_tokens: 실행 단계 출력 토큰 수
        judge_input_tokens: 판단 단계 입력 토큰 수
        judge_output_tokens: 판단 단계 출력 토큰 수

    Returns:
        업데이트된 log dict
    """
    round_entry: dict[str, Any] = {
        "round": round_num,
        "mutation_type": mutation_type,
        "mutation_description": mutation_description,
        "score_before": score_before,
        "score_after": score_after,
        "items_detail": items_detail,
        "decision": decision,
        "input_tokens": input_tokens,
        "output_tokens": output_tokens,
        "mutation_input_tokens": mutation_input_tokens,
        "mutation_output_tokens": mutation_output_tokens,
        "execution_input_tokens": execution_input_tokens,
        "execution_output_tokens": execution_output_tokens,
        "judge_input_tokens": judge_input_tokens,
        "judge_output_tokens": judge_output_tokens,
    }

    log["rounds"].append(round_entry)

    if decision == "kept":
        log["kept"] = int(log["kept"]) + 1
    elif decision == "reverted":
        log["reverted"] = int(log["reverted"]) + 1

    return log


def finalize_log(log: dict[str, Any], final_score: float) -> dict[str, Any]:
    """로그 마무리 - 최종 점수와 total_rounds 업데이트.

    Args:
        log: 현재 changelog dict
        final_score: 최종 점수

    Returns:
        업데이트된 log dict
    """
    log["final_score"] = final_score
    log["total_rounds"] = len(log["rounds"])
    return log


def _resolve_evals_path(skill_name: str, evals_dir: Optional[str]) -> Path:
    """evals 디렉토리 경로를 결정.

    evals_dir이 지정되면 그 디렉토리를 직접 사용.
    지정되지 않으면 기본 경로: /home/jay/workspace/skills/<skill_name>/evals/
    """
    if evals_dir is not None:
        return Path(evals_dir)
    return Path(_WORKSPACE_ROOT) / "skills" / skill_name / "evals"


def save_log(log: dict[str, Any], skill_name: str, evals_dir: Optional[str] = None) -> str:
    """로그를 JSON 파일로 저장.

    경로: <evals_dir>/autoresearch-log.json
    evals_dir 미지정 시: skills/<skill_name>/evals/autoresearch-log.json

    Args:
        log: 저장할 changelog dict
        skill_name: 스킬 이름
        evals_dir: 저장 디렉토리 (None이면 기본 경로 사용)

    Returns:
        저장된 파일의 절대 경로 문자열
    """
    target_dir = _resolve_evals_path(skill_name, evals_dir)
    target_dir.mkdir(parents=True, exist_ok=True)

    file_path = target_dir / "autoresearch-log.json"
    file_path.write_text(
        json.dumps(log, ensure_ascii=False, indent=2),
        encoding="utf-8",
    )
    return str(file_path.resolve())


def load_log(skill_name: str, evals_dir: Optional[str] = None) -> Optional[dict[str, Any]]:
    """기존 로그를 로드.

    Args:
        skill_name: 스킬 이름
        evals_dir: 로그 디렉토리 (None이면 기본 경로 사용)

    Returns:
        로드된 changelog dict, 없으면 None
    """
    target_dir = _resolve_evals_path(skill_name, evals_dir)
    file_path = target_dir / "autoresearch-log.json"

    if not file_path.exists():
        return None

    content = file_path.read_text(encoding="utf-8")
    result: dict[str, Any] = json.loads(content)
    return result


def get_recent_changelog(log: dict[str, Any], count: int = 5) -> str:
    """최근 N개 라운드 변경 내역을 텍스트로 반환 (mutator 프롬프트에 제공용).

    Args:
        log: changelog dict
        count: 반환할 최근 라운드 수

    Returns:
        사람이 읽기 쉬운 텍스트 형식의 변경 내역
    """
    rounds: list[Any] = log.get("rounds", [])

    if not rounds:
        return "변경 이력 없음"

    recent = rounds[-count:] if len(rounds) > count else rounds

    lines: list[str] = []
    lines.append(f"=== 최근 {len(recent)}개 변경 내역 ===")

    for entry in recent:
        round_num = entry.get("round", "?")
        mutation_type = entry.get("mutation_type", "unknown")
        mutation_description = entry.get("mutation_description", "")
        score_before = entry.get("score_before", 0.0)
        score_after = entry.get("score_after", 0.0)
        decision = entry.get("decision", "unknown")
        delta = float(score_after) - float(score_before)
        delta_str = f"+{delta:.3f}" if delta >= 0 else f"{delta:.3f}"

        lines.append(f"[Round {round_num}] {mutation_type}: {mutation_description}")
        lines.append(f"  점수: {score_before:.3f} -> {score_after:.3f} ({delta_str}) | 결정: {decision}")

    return "\n".join(lines)
