"""
data_integrity.py - task-timers.json 교차검증 verifier
task-timers.json의 task 상태와 .done 파일을 교차 대조
stale 체크: running 상태가 2시간 이상이면 WARNING
"""
import json
import os
from datetime import datetime, timezone

TASK_TIMERS_PATH = "/home/jay/workspace/memory/task-timers.json"
EVENTS_DIR = "/home/jay/workspace/memory/events"
STALE_THRESHOLD_HOURS = 2
COMPLETED_STATUSES = {"completed", "done"}
RUNNING_STATUS = "running"


def _load_task_timers() -> tuple[dict, str]:
    """task-timers.json 로드. (data, error_msg) 반환."""
    if not os.path.exists(TASK_TIMERS_PATH):
        return {}, f"task-timers.json not found: {TASK_TIMERS_PATH}"

    try:
        with open(TASK_TIMERS_PATH, "r", encoding="utf-8") as f:
            data = json.load(f)
        return data, ""
    except json.JSONDecodeError as e:
        return {}, f"JSON parse error in task-timers.json: {e}"
    except PermissionError:
        return {}, f"Permission denied: {TASK_TIMERS_PATH}"
    except OSError as e:
        return {}, f"OS error reading task-timers.json: {e}"


def _has_done_file(task_id: str) -> bool:
    """events/ 디렉토리에 task_id의 .done 파일이 있는지 확인."""
    if not os.path.isdir(EVENTS_DIR):
        return False
    try:
        entries = os.listdir(EVENTS_DIR)
        return any(e.startswith(task_id) and ".done" in e for e in entries)
    except OSError:
        return False


def _check_stale(task_info: dict, task_id: str) -> tuple[bool, str]:
    """
    running 상태인 태스크가 2시간 이상 경과했는지 확인.
    (is_warning, detail_message) 반환.
    """
    status = task_info.get("status", "")
    if status != RUNNING_STATUS:
        return False, ""

    start_time_str = task_info.get("start_time", "")
    if not start_time_str:
        return True, f"WARNING [{task_id}]: running but no start_time recorded"

    try:
        start_time = datetime.fromisoformat(start_time_str)
        # timezone-naive라면 local time으로 간주
        if start_time.tzinfo is None:
            now = datetime.now()
        else:
            now = datetime.now(timezone.utc)

        elapsed_hours = (now - start_time).total_seconds() / 3600

        if elapsed_hours >= STALE_THRESHOLD_HOURS:
            return True, (
                f"WARNING [{task_id}]: running for {elapsed_hours:.1f}h "
                f"(threshold: {STALE_THRESHOLD_HOURS}h) — possibly stale"
            )
        return False, ""

    except ValueError as e:
        return True, f"WARNING [{task_id}]: cannot parse start_time '{start_time_str}': {e}"


def verify(task_id: str) -> dict:
    """
    task-timers.json에서 task_id의 상태를 확인하고
    .done 파일과 교차 검증합니다.

    Args:
        task_id: 검증할 task ID

    Returns:
        {"status": "PASS"|"FAIL"|"WARN"|"SKIP", "details": [...]}
    """
    if not task_id:
        return {"status": "SKIP", "details": ["No task_id specified"]}

    details = []
    has_failure = False
    has_warning = False

    # task-timers.json 로드
    data, load_err = _load_task_timers()
    if load_err:
        return {"status": "FAIL", "details": [load_err]}

    tasks = data.get("tasks", {})
    if not isinstance(tasks, dict):
        return {
            "status": "FAIL",
            "details": [f"task-timers.json: 'tasks' field is not a dict (got {type(tasks).__name__})"],
        }

    # task_id 존재 여부 확인
    if task_id not in tasks:
        return {
            "status": "FAIL",
            "details": [f"task '{task_id}' not found in task-timers.json"],
        }

    task_info = tasks[task_id]
    status = task_info.get("status", "unknown")
    details.append(f"task-timers.json: [{task_id}] status='{status}'")

    # .done 파일 존재 여부
    done_exists = _has_done_file(task_id)
    details.append(
        f"events/.done file: {'FOUND' if done_exists else 'NOT FOUND'} for {task_id}"
    )

    # 교차 검증 1: completed/done인데 .done 파일 없음
    if status in COMPLETED_STATUSES and not done_exists:
        details.append(
            f"FAIL [{task_id}]: status='{status}' but no .done file in events/"
        )
        has_failure = True

    # 교차 검증 2: .done 파일 있는데 status가 running
    elif done_exists and status == RUNNING_STATUS:
        details.append(
            f"WARNING [{task_id}]: .done file exists but status='{status}'"
        )
        has_warning = True

    # 교차 검증 3: 정상 케이스
    elif status in COMPLETED_STATUSES and done_exists:
        details.append(f"OK [{task_id}]: status='{status}' and .done file both consistent")

    elif status not in COMPLETED_STATUSES and not done_exists:
        details.append(f"OK [{task_id}]: status='{status}' — task not yet completed")

    # stale 체크
    is_stale, stale_msg = _check_stale(task_info, task_id)
    if is_stale:
        details.append(stale_msg)
        has_warning = True

    # 추가 정보 포함
    if "start_time" in task_info and "end_time" in task_info:
        details.append(
            f"timeline: {task_info['start_time']} → {task_info.get('end_time', 'N/A')} "
            f"({task_info.get('duration_human', '')})"
        )

    if has_failure:
        final_status = "FAIL"
    elif has_warning:
        final_status = "WARN"
    else:
        final_status = "PASS"

    return {"status": final_status, "details": details}


if __name__ == "__main__":
    import sys
    import json as _json

    tid = sys.argv[1] if len(sys.argv) > 1 else "task-4.4"
    result = verify(tid)
    print(_json.dumps(result, ensure_ascii=False, indent=2))
