"""
transcript-learner.py

세션 대화 트랜스크립트에서 패턴(지적/칭찬/선호)을 추출하여
memory/whisper/learnings.json에 누적 저장한다.

Usage:
    python3 transcript-learner.py [--input FILE] [--workspace /path]
    echo "대화 내용" | python3 transcript-learner.py
"""

import argparse
import json
import os
import sys
from datetime import datetime, timezone
from pathlib import Path
from typing import Any

# ---------------------------------------------------------------------------
# 상수: 패턴 키워드 정의
# ---------------------------------------------------------------------------

CRITICISM_KEYWORDS: list[str] = [
    "아까 말했잖아",
    "이미 했잖아",
    "아니라고",
    "이거 왜",
    "했잖아",
    "아니 그게",
    "다시",
    "또?",
]

PRAISE_KEYWORDS: list[str] = [
    "오 괜찮은데",
    "이거 맞어",
    "그래 이거야",
    "잘했어",
    "좋네",
    "괜찮다",
    "좋아",
]

PREFERENCE_KEYWORDS: list[str] = [
    "항상",
    "하지 마",
    "으로 해",
    "로 해",
    "난",
]

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


# ---------------------------------------------------------------------------
# 패턴 추출
# ---------------------------------------------------------------------------


def extract_patterns_from_line(line: str) -> list[dict[str, Any]]:
    """한 줄에서 모든 매칭 패턴을 추출한다."""
    results: list[dict[str, Any]] = []
    stripped = line.strip()
    if not stripped:
        return results

    # 중복 키워드 방지를 위해 이미 처리된 키워드 추적
    seen_keywords: set[str] = set()

    # criticism 키워드 검사
    for kw in CRITICISM_KEYWORDS:
        if kw in stripped and kw not in seen_keywords:
            seen_keywords.add(kw)
            results.append(
                {
                    "type": "criticism",
                    "keyword": kw,
                    "context": stripped,
                }
            )

    # praise 키워드 검사
    for kw in PRAISE_KEYWORDS:
        if kw in stripped and kw not in seen_keywords:
            seen_keywords.add(kw)
            results.append(
                {
                    "type": "praise",
                    "keyword": kw,
                    "context": stripped,
                }
            )

    # preference 키워드 검사
    for kw in PREFERENCE_KEYWORDS:
        if kw in stripped and kw not in seen_keywords:
            seen_keywords.add(kw)
            results.append(
                {
                    "type": "preference",
                    "keyword": kw,
                    "context": stripped,
                }
            )

    return results


# ---------------------------------------------------------------------------
# learnings.json 로드/저장
# ---------------------------------------------------------------------------


def _learnings_path(base_dir: Path) -> Path:
    return base_dir / "whisper" / "learnings.json"


def load_learnings(base_dir: Path | None = None) -> dict[str, Any]:
    """learnings.json 로드. 없거나 손상된 경우 빈 구조 반환."""
    if base_dir is None:
        base_dir = DEFAULT_WORKSPACE

    path = _learnings_path(base_dir)
    if not path.exists():
        return {"version": 1, "last_updated": "", "patterns": []}

    try:
        data = json.loads(path.read_text(encoding="utf-8"))
        if not isinstance(data, dict):
            raise ValueError("root is not a dict")
        if "patterns" not in data:
            data["patterns"] = []
        return data
    except (json.JSONDecodeError, ValueError, OSError):
        return {"version": 1, "last_updated": "", "patterns": []}


def save_learnings(data: dict[str, Any], base_dir: Path) -> None:
    """learnings.json 저장."""
    path = _learnings_path(base_dir)
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8")


# ---------------------------------------------------------------------------
# 핵심 처리 로직
# ---------------------------------------------------------------------------


def process_transcript(
    text: str,
    base_dir: Path | None = None,
) -> dict[str, Any]:
    """트랜스크립트 텍스트를 처리하여 패턴을 추출·저장한다.

    Returns:
        {"new_patterns": int, "updated_patterns": int, "total_patterns": int}
    """
    if base_dir is None:
        base_dir = DEFAULT_WORKSPACE

    learnings = load_learnings(base_dir=base_dir)
    patterns: list[dict[str, Any]] = learnings.get("patterns", [])

    today = datetime.now(timezone.utc).strftime("%Y-%m-%d")
    now_iso = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S")

    new_count = 0
    updated_count = 0

    for line in text.splitlines():
        extracted = extract_patterns_from_line(line)
        for item in extracted:
            # 동일한 keyword + context 검색
            existing = next(
                (p for p in patterns if p.get("keyword") == item["keyword"] and p.get("context") == item["context"]),
                None,
            )
            if existing is not None:
                existing["count"] = existing.get("count", 1) + 1
                existing["last_seen"] = today
                updated_count += 1
            else:
                patterns.append(
                    {
                        "type": item["type"],
                        "keyword": item["keyword"],
                        "context": item["context"],
                        "count": 1,
                        "first_seen": today,
                        "last_seen": today,
                    }
                )
                new_count += 1

    learnings["version"] = 1
    learnings["last_updated"] = now_iso
    learnings["patterns"] = patterns

    save_learnings(learnings, base_dir=base_dir)

    return {
        "new_patterns": new_count,
        "updated_patterns": updated_count,
        "total_patterns": len(patterns),
    }


# ---------------------------------------------------------------------------
# stdin / 파일 읽기
# ---------------------------------------------------------------------------


def read_input(input_file: str | None) -> str:
    """입력 텍스트를 파일 또는 stdin에서 읽는다."""
    if input_file is not None:
        return Path(input_file).read_text(encoding="utf-8")
    return sys.stdin.read()


# ---------------------------------------------------------------------------
# CLI 진입점
# ---------------------------------------------------------------------------


def main() -> None:
    parser = argparse.ArgumentParser(description="세션 트랜스크립트에서 패턴을 추출하여 learnings.json에 저장")
    parser.add_argument(
        "--input",
        metavar="FILE",
        default=None,
        help="입력 파일 경로 (없으면 stdin)",
    )
    parser.add_argument(
        "--workspace",
        metavar="PATH",
        default=str(DEFAULT_WORKSPACE),
        help=f"워크스페이스 경로 (기본값: {DEFAULT_WORKSPACE})",
    )
    args = parser.parse_args()

    text = read_input(input_file=args.input)
    base_dir = Path(args.workspace)
    result = process_transcript(text, base_dir=base_dir)
    print(json.dumps(result, ensure_ascii=False))


if __name__ == "__main__":
    main()
