#!/usr/bin/env python3
"""
decision_logger.py - JSONL 결정 히스토리 기록 유틸리티

각 작업의 판단 근거를 JSONL로 자동 기록한다.
dispatch.py 위임 시, .done 처리 시, /retro 스킬에서 참조.

출처: gstack artifact chain 패턴 (MIT 라이선스, https://github.com/garrytan/gstack)

Usage:
    # 결정 기록
    python3 decision_logger.py log --task-id task-xxx --stage plan --decision "A안 선택" --reason "성능 우선"

    # 특정 task의 결정 조회
    python3 decision_logger.py query --task-id task-xxx

    # 전체 결정 통계
    python3 decision_logger.py stats [--days 7]
"""

import argparse
import json
import os
import sys
from datetime import datetime, timedelta
from pathlib import Path
from typing import Optional

WORKSPACE = Path(os.environ.get("WORKSPACE_ROOT", "/home/jay/workspace"))
DECISIONS_DIR = WORKSPACE / "memory" / "events" / "decisions"


def log_decision(
    task_id: str,
    stage: str,
    decision: str,
    reason: str = "",
    findings: Optional[int] = None,
    **extra,
) -> dict:
    """
    결정을 JSONL 파일에 기록.

    Args:
        task_id: 작업 ID
        stage: 단계 (plan, review, dispatch, done, cross_review 등)
        decision: 결정 내용
        reason: 결정 사유
        findings: 발견 사항 수 (선택)
        **extra: 추가 필드

    Returns:
        기록된 entry dict
    """
    DECISIONS_DIR.mkdir(parents=True, exist_ok=True)

    entry: dict[str, object] = {
        "task_id": task_id,
        "stage": stage,
        "decision": decision,
        "timestamp": datetime.now().isoformat(),
    }
    if reason:
        entry["reason"] = reason
    if findings is not None:
        entry["findings"] = findings
    entry.update(extra)

    # task별 JSONL 파일에 추가
    decisions_file = DECISIONS_DIR / f"{task_id}.jsonl"
    with open(decisions_file, "a", encoding="utf-8") as f:
        f.write(json.dumps(entry, ensure_ascii=False) + "\n")

    return entry


def query_decisions(task_id: str) -> list[dict]:
    """특정 task의 모든 결정 기록 조회."""
    decisions_file = DECISIONS_DIR / f"{task_id}.jsonl"
    if not decisions_file.exists():
        return []

    entries = []
    with open(decisions_file, "r", encoding="utf-8") as f:
        for line in f:
            line = line.strip()
            if line:
                try:
                    entries.append(json.loads(line))
                except json.JSONDecodeError:
                    pass
    return entries


def get_stats(days: int = 7) -> dict:
    """
    최근 N일간 결정 통계.

    Returns:
        {
            "total_decisions": int,
            "total_tasks": int,
            "by_stage": {"plan": N, "review": N, ...},
            "period": "YYYY-MM-DD ~ YYYY-MM-DD",
        }
    """
    if not DECISIONS_DIR.exists():
        return {
            "total_decisions": 0,
            "total_tasks": 0,
            "by_stage": {},
            "period": "N/A",
        }

    cutoff = datetime.now() - timedelta(days=days)
    cutoff_str = cutoff.isoformat()

    total = 0
    tasks = set()
    by_stage: dict[str, int] = {}

    for jsonl_file in DECISIONS_DIR.glob("*.jsonl"):
        with open(jsonl_file, "r", encoding="utf-8") as f:
            for line in f:
                line = line.strip()
                if not line:
                    continue
                try:
                    entry = json.loads(line)
                except json.JSONDecodeError:
                    continue

                ts = entry.get("timestamp", "")
                if ts < cutoff_str:
                    continue

                total += 1
                tasks.add(entry.get("task_id", ""))
                stage = entry.get("stage", "unknown")
                by_stage[stage] = by_stage.get(stage, 0) + 1

    end_date = datetime.now().strftime("%Y-%m-%d")
    start_date = cutoff.strftime("%Y-%m-%d")

    return {
        "total_decisions": total,
        "total_tasks": len(tasks),
        "by_stage": by_stage,
        "period": f"{start_date} ~ {end_date}",
    }


def main() -> None:
    parser = argparse.ArgumentParser(description="JSONL 결정 히스토리 유틸리티")
    subparsers = parser.add_subparsers(dest="command", required=True)

    # log 서브커맨드
    log_parser = subparsers.add_parser("log", help="결정 기록")
    log_parser.add_argument("--task-id", required=True, help="작업 ID")
    log_parser.add_argument("--stage", required=True, help="단계 (plan/review/dispatch/done 등)")
    log_parser.add_argument("--decision", required=True, help="결정 내용")
    log_parser.add_argument("--reason", default="", help="결정 사유")
    log_parser.add_argument("--findings", type=int, default=None, help="발견 사항 수")

    # query 서브커맨드
    query_parser = subparsers.add_parser("query", help="결정 조회")
    query_parser.add_argument("--task-id", required=True, help="조회할 작업 ID")

    # stats 서브커맨드
    stats_parser = subparsers.add_parser("stats", help="결정 통계")
    stats_parser.add_argument("--days", type=int, default=7, help="통계 기간 (일)")

    args = parser.parse_args()

    if args.command == "log":
        entry = log_decision(
            task_id=args.task_id,
            stage=args.stage,
            decision=args.decision,
            reason=args.reason,
            findings=args.findings,
        )
        print(json.dumps(entry, ensure_ascii=False, indent=2))

    elif args.command == "query":
        entries = query_decisions(args.task_id)
        if not entries:
            print(json.dumps({"status": "empty", "message": f"결정 기록 없음: {args.task_id}"}, ensure_ascii=False))
        else:
            for entry in entries:
                print(json.dumps(entry, ensure_ascii=False))

    elif args.command == "stats":
        stats = get_stats(days=args.days)
        print(json.dumps(stats, ensure_ascii=False, indent=2))


if __name__ == "__main__":
    main()
