"""Grok Build session collectors.

공식 세션 문서는 대화를 ``~/.grok/sessions/`` 에 둔다. cwd 는 퍼센트 인코딩된
디렉터리 이름이다. 누적 사용량은 ``updates.jsonl`` 의
``params.update.usage.modelUsage`` 마지막 스냅샷이다.
"""
from __future__ import annotations

import json
import os
from datetime import datetime, timezone
from pathlib import Path
from typing import Mapping
from urllib.parse import quote, unquote

from .jsonl_io import iter_jsonl
from .paths import ts_in_window


def grok_sessions_root(
    home: Path | None = None,
    env: Mapping[str, str] | None = None,
) -> Path:
    environ = env if env is not None else os.environ
    configured = str(environ.get("GROK_HOME") or "").strip()
    base = Path(configured).expanduser() if configured else (home or Path.home()) / ".grok"
    return base / "sessions"


def _iso_from_unix(value: object) -> str | None:
    if not isinstance(value, (int, float)) or isinstance(value, bool):
        return None
    return datetime.fromtimestamp(value, timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")


def _usage_payload(record: dict) -> dict | None:
    params = record.get("params")
    if not isinstance(params, dict):
        return None
    update = params.get("update")
    if not isinstance(update, dict):
        return None
    usage = update.get("usage")
    return usage if isinstance(usage, dict) else None


def _model_snapshot(usage: dict) -> tuple[dict, str | None]:
    models = usage.get("modelUsage")
    if isinstance(models, dict) and len(models) == 1:
        name, payload = next(iter(models.items()))
        if isinstance(payload, dict):
            return payload, name if isinstance(name, str) else None
    return usage, None


def grok_session_total(updates_path: Path) -> dict:
    """마지막 modelUsage 스냅샷. 세션 누적이라 더하지 않는다."""
    last: dict | None = None
    model: str | None = None
    started: str | None = None
    ended: str | None = None
    for record in iter_jsonl(updates_path):
        usage = _usage_payload(record)
        if usage is None:
            continue
        iso = _iso_from_unix(record.get("timestamp"))
        if iso and started is None:
            started = iso
        if iso:
            ended = iso
        snapshot, snapshot_model = _model_snapshot(usage)
        last = snapshot
        if snapshot_model:
            model = snapshot_model
    if last is None:
        return {"totalTokens": 0, "available": False}
    return {
        "totalTokens": last.get("totalTokens", 0) or 0,
        "inputTokens": last.get("inputTokens", 0) or 0,
        "outputTokens": last.get("outputTokens", 0) or 0,
        "cachedInputTokens": last.get("cachedReadTokens", 0) or 0,
        "reasoningOutputTokens": last.get("reasoningTokens", 0) or 0,
        "durationMs": last.get("apiDurationMs", 0) or 0,
        "model": model,
        "startedAt": started,
        "endedAt": ended,
        "available": True,
    }


def _session_started_in_window(
    updates_path: Path, started_at: str, ended_at: str,
) -> bool:
    """첫 usage 시각이 창 안에 있을 때만 이 창의 세션이다.

    창 중간의 갱신만 보면 같은 cwd 의 리드 대화가 워커 창에 섞인다.
    """
    for record in iter_jsonl(updates_path):
        iso = _iso_from_unix(record.get("timestamp"))
        if iso:
            return ts_in_window(iso, started_at, ended_at)
    return False


def find_grok_sessions(
    cwd: Path,
    started_at: str,
    ended_at: str,
    *,
    session_root: Path | None = None,
) -> list[Path]:
    """cwd 로 인코딩된 세션 중 창 안에서 시작된 updates.jsonl."""
    if not started_at or not ended_at:
        return []
    root = session_root or grok_sessions_root()
    if not root.is_dir():
        return []
    target = str(cwd)
    matches: list[Path] = []
    for child in root.iterdir():
        if not child.is_dir():
            continue
        decoded = unquote(child.name)
        if decoded != target:
            continue
        for session in child.iterdir():
            updates = session / "updates.jsonl"
            if updates.is_file() and _session_started_in_window(
                updates, started_at, ended_at
            ):
                matches.append(updates)
    return sorted(matches)


def grok_session_dir_name(cwd: Path) -> str:
    return quote(str(cwd), safe="")


def grok_session_is_non_interactive(updates_path: Path) -> bool:
    """워커 래퍼 세션은 prompt_context.is_non_interactive 가 true 이다."""
    context_path = updates_path.parent / "prompt_context.json"
    try:
        payload = json.loads(context_path.read_text(encoding="utf-8"))
    except (OSError, json.JSONDecodeError):
        return False
    return payload.get("is_non_interactive") is True
