#!/usr/bin/env python3
"""
List recent Claude Code sessions with descriptive information.

Usage:
    python list-sessions.py [--project-dir <path>] [--limit <n>]
"""

import argparse
import json
import os
import sys
from datetime import datetime
from pathlib import Path


def get_project_sessions_dir(project_dir: Path) -> Path:
    """Convert project directory to Claude sessions directory name."""
    # Claude converts paths like /Users/foo/bar to -Users-foo-bar
    normalized = str(project_dir.resolve()).replace("/", "-")
    return Path.home() / ".claude" / "projects" / normalized


def parse_jsonl_metadata(jsonl_path: Path) -> dict:
    """Extract metadata from a JSONL session file."""
    try:
        with open(jsonl_path, "r") as f:
            lines = f.readlines()

        # Parse first line for session metadata
        first_line = json.loads(lines[0])

        # Find first user message with actual content
        first_user_msg = "No messages"
        for line in lines[:10]:  # Check first 10 lines
            data = json.loads(line)
            if data.get("type") == "user":
                content = data.get("message", {}).get("content", "")
                # Handle both string and array content formats
                if isinstance(content, str):
                    msg_text = content
                elif isinstance(content, list):
                    # Extract text from array format
                    text_parts = [
                        item.get("text", "")
                        for item in content
                        if isinstance(item, dict) and item.get("type") == "text"
                    ]
                    msg_text = " ".join(text_parts)
                else:
                    msg_text = str(content)

                # Clean up IDE noise
                if "<ide_selection>" in msg_text:
                    msg_text = msg_text.split("</ide_selection>")[-1].strip()
                if "<ide_opened_file>" in msg_text:
                    msg_text = msg_text.split("</ide_opened_file>")[-1].strip()

                # Skip empty or warmup messages
                if msg_text and msg_text.strip() and msg_text not in ["Warmup", ""]:
                    first_user_msg = msg_text.strip()
                    break

        # Truncate long messages
        if len(first_user_msg) > 80:
            first_user_msg = first_user_msg[:77] + "..."

        # Count total messages
        message_count = sum(
            1 for line in lines if json.loads(line).get("type") in ["user", "assistant"]
        )

        # Get timestamp and format it
        timestamp = first_line.get("timestamp", "")
        if timestamp:
            dt = datetime.fromisoformat(timestamp.replace("Z", "+00:00"))
            formatted_time = dt.strftime("%b %d %H:%M")
        else:
            formatted_time = "Unknown"

        # Get git branch
        git_branch = first_line.get("gitBranch", "unknown")

        # Get file modification time as fallback
        mtime = datetime.fromtimestamp(jsonl_path.stat().st_mtime)

        return {
            "path": jsonl_path,
            "first_message": first_user_msg,
            "timestamp": formatted_time,
            "mtime": mtime,
            "message_count": message_count,
            "git_branch": git_branch,
        }
    except Exception as e:
        return {
            "path": jsonl_path,
            "first_message": f"Error reading file: {e}",
            "timestamp": "Unknown",
            "mtime": datetime.fromtimestamp(jsonl_path.stat().st_mtime),
            "message_count": 0,
            "git_branch": "unknown",
        }


def main():
    parser = argparse.ArgumentParser(
        description="List recent Claude Code sessions with descriptive information."
    )
    parser.add_argument(
        "--project-dir",
        type=Path,
        default=Path.cwd(),
        help="Project directory (default: current working directory)",
    )
    parser.add_argument(
        "--limit",
        type=int,
        default=5,
        help="Number of recent sessions to show (default: 5)",
    )
    parser.add_argument(
        "--format",
        choices=["human", "json"],
        default="human",
        help="Output format (default: human)",
    )

    args = parser.parse_args()

    # Find sessions directory
    sessions_dir = get_project_sessions_dir(args.project_dir)

    if not sessions_dir.exists():
        print(f"No sessions found for project: {args.project_dir}", file=sys.stderr)
        print(f"Expected sessions directory: {sessions_dir}", file=sys.stderr)
        sys.exit(1)

    # Find all JSONL files
    jsonl_files = list(sessions_dir.glob("*.jsonl"))

    if not jsonl_files:
        print(f"No session files found in: {sessions_dir}", file=sys.stderr)
        sys.exit(1)

    # Parse metadata for all files
    sessions = [parse_jsonl_metadata(f) for f in jsonl_files]

    # Sort by modification time (most recent first)
    sessions.sort(key=lambda s: s["mtime"], reverse=True)

    # Limit results
    sessions = sessions[: args.limit]

    # Output
    if args.format == "json":
        output = [
            {
                "index": i + 1,
                "path": str(s["path"]),
                "first_message": s["first_message"],
                "timestamp": s["timestamp"],
                "message_count": s["message_count"],
                "git_branch": s["git_branch"],
            }
            for i, s in enumerate(sessions)
        ]
        print(json.dumps(output, indent=2))
    else:
        print("\nRecent sessions:")
        print("=" * 80)
        for i, s in enumerate(sessions, 1):
            print(
                f"{i}. [{s['timestamp']}] \"{s['first_message']}\" "
                f"({s['message_count']} messages, branch: {s['git_branch']})"
            )
            print(f"   Path: {s['path']}")
            print()


if __name__ == "__main__":
    main()
