"""Parser for Claude Code conversation data.

Claude Code stores:
1. ~/.claude/history.jsonl — one line per user prompt, with project path
2. ~/.claude/projects/<project-name>/<session-id>.jsonl — full session transcripts
   where type="user" lines are user prompts
3. ~/.claude/projects/<project-name>/sessions-index.json — session metadata
   with firstPrompt, messageCount, created, modified, gitBranch
"""
import json
from collections import defaultdict
from pathlib import Path


def count_from_history(history_path: Path) -> dict[str, int]:
    """Count prompts per project from history.jsonl.

    Each line is: {"display": "...", "project": "/path/to/project", "timestamp": ...}
    Returns: {project_path: prompt_count}
    """
    counts = defaultdict(int)
    if not history_path.exists():
        return counts
    with open(history_path) as f:
        for line in f:
            line = line.strip()
            if not line:
                continue
            try:
                entry = json.loads(line)
                project = entry.get("project", "")
                if project:
                    counts[project] += 1
            except json.JSONDecodeError:
                continue
    return dict(counts)


def count_from_sessions(project_sessions_dir: Path) -> dict:
    """Count user prompts from session JSONL files in a project directory.

    Each session file has lines with type="user" for user messages.
    Returns: {"total_prompts": N, "sessions": M}
    """
    total = 0
    sessions = 0
    if not project_sessions_dir.exists():
        return {"total_prompts": 0, "sessions": 0}

    for session_file in project_sessions_dir.glob("*.jsonl"):
        session_prompts = 0
        with open(session_file) as f:
            for line in f:
                line = line.strip()
                if not line:
                    continue
                try:
                    entry = json.loads(line)
                    if entry.get("type") == "user":
                        session_prompts += 1
                except json.JSONDecodeError:
                    continue
        if session_prompts > 0:
            sessions += 1
            total += session_prompts

    return {"total_prompts": total, "sessions": sessions}


def _project_path_to_dir_name(project_path: str) -> str:
    """Convert a project path to the directory name Claude Code uses.

    Claude Code replaces both / and _ with - in directory names.
    /Users/test/my-app -> -Users-test-my-app
    /Users/test/my_app -> -Users-test-my-app
    """
    return project_path.replace("/", "-").replace("_", "-")


def count_for_project(project_path: str, claude_dir: Path) -> dict:
    """Count all prompts for a given project path.

    Uses history.jsonl as primary source, falls back to session files.
    Returns: {"prompts": N, "sessions": M, "source": "history"|"sessions"}
    """
    # Try history.jsonl first (most reliable, has project field)
    history_path = claude_dir / "history.jsonl"
    history_counts = count_from_history(history_path)
    prompt_count = history_counts.get(project_path, 0)

    # Get session count from session files
    dir_name = _project_path_to_dir_name(project_path)
    sessions_dir = claude_dir / "projects" / dir_name
    session_result = count_from_sessions(sessions_dir)

    if prompt_count > 0:
        return {
            "prompts": prompt_count,
            "sessions": session_result["sessions"],
            "source": "history",
        }

    # Fallback to session files if history doesn't have this project
    return {
        "prompts": session_result["total_prompts"],
        "sessions": session_result["sessions"],
        "source": "sessions",
    }


def list_chats(project_path: str, claude_dir: Path) -> list[dict]:
    """List all chat sessions for a project, sorted by most recent first.

    Reads from sessions-index.json which has:
    - firstPrompt, messageCount, created, modified, gitBranch, sessionId

    Returns list of: {"first_prompt": str, "message_count": int, "created": str,
                      "modified": str, "branch": str, "session_id": str, "tool": "claude"}
    """
    dir_name = _project_path_to_dir_name(project_path)
    index_path = claude_dir / "projects" / dir_name / "sessions-index.json"

    if not index_path.exists():
        return []

    try:
        with open(index_path) as f:
            data = json.load(f)
    except (json.JSONDecodeError, IOError):
        return []

    # Handle both old format (list) and new format (dict with entries)
    if isinstance(data, dict):
        entries = data.get("entries", [])
    elif isinstance(data, list):
        entries = data
    else:
        return []

    chats = []
    for entry in entries:
        chats.append({
            "first_prompt": entry.get("firstPrompt", ""),
            "message_count": entry.get("messageCount", 0),
            "created": entry.get("created", ""),
            "modified": entry.get("modified", ""),
            "branch": entry.get("gitBranch", ""),
            "session_id": entry.get("sessionId", ""),
            "tool": "claude",
        })

    # Sort by modified date descending
    chats.sort(key=lambda c: c.get("modified", ""), reverse=True)
    return chats
