#!/usr/bin/env python3
"""
Vault Status -- At-a-glance overview of your AI Dev Vault.

Shows everything installed, recent activity, learning system stats,
search index status, and overall health. The terminal equivalent of
a project dashboard.

Usage:
    vault-status                    # full status overview
    vault-status --brief            # one-line summary
    vault-status --json             # machine-readable output
    vault-status --version          # show version
"""

import sys
import os
import re
import json
import subprocess
from pathlib import Path
from datetime import datetime
from collections import defaultdict

__version__ = "1.0.0"

# --- Configuration ---
PROJECT_DIR = Path(os.environ.get("PROJECT_DIR", ".")).resolve()
VAULT_ROOT = Path(os.environ.get("VAULT_ROOT", PROJECT_DIR)).resolve()

# ANSI colors
class C:
    GREEN = "\033[92m"
    YELLOW = "\033[93m"
    RED = "\033[91m"
    BLUE = "\033[94m"
    CYAN = "\033[96m"
    BOLD = "\033[1m"
    DIM = "\033[2m"
    RESET = "\033[0m"

    @staticmethod
    def disable():
        for attr in ['GREEN', 'YELLOW', 'RED', 'BLUE', 'CYAN', 'BOLD', 'DIM', 'RESET']:
            setattr(C, attr, '')


def count_files(directory, pattern="*"):
    """Count files matching a pattern in a directory."""
    d = PROJECT_DIR / directory
    if not d.exists():
        return 0
    return len(list(d.glob(pattern)))


def count_learning_entries(filename):
    """Count ### entries in a learning file."""
    fpath = PROJECT_DIR / "agent-learnings" / filename
    if not fpath.exists():
        return 0
    content = fpath.read_text(encoding="utf-8", errors="ignore")
    return len(re.findall(r'^### ', content, re.MULTILINE))


def get_git_info():
    """Get recent git activity."""
    info = {}
    try:
        info["branch"] = subprocess.run(
            ["git", "branch", "--show-current"],
            capture_output=True, text=True, cwd=str(PROJECT_DIR), timeout=5
        ).stdout.strip()

        info["last_commit"] = subprocess.run(
            ["git", "log", "-1", "--format=%h %s (%cr)"],
            capture_output=True, text=True, cwd=str(PROJECT_DIR), timeout=5
        ).stdout.strip()

        info["uncommitted"] = subprocess.run(
            ["git", "status", "--porcelain"],
            capture_output=True, text=True, cwd=str(PROJECT_DIR), timeout=5
        ).stdout.strip().count("\n") + (1 if subprocess.run(
            ["git", "status", "--porcelain"],
            capture_output=True, text=True, cwd=str(PROJECT_DIR), timeout=5
        ).stdout.strip() else 0)

        # Commits today
        today = datetime.now().strftime("%Y-%m-%d")
        result = subprocess.run(
            ["git", "log", f"--since={today}", "--oneline"],
            capture_output=True, text=True, cwd=str(PROJECT_DIR), timeout=5
        )
        info["commits_today"] = len(result.stdout.strip().split("\n")) if result.stdout.strip() else 0

    except Exception:
        pass
    return info


def get_search_stats():
    """Get vault search index stats."""
    index_path = VAULT_ROOT / ".vault-search" / "index.pkl"
    if not index_path.exists():
        return {"indexed": False}

    try:
        import pickle
        with open(index_path, "rb") as f:
            data = pickle.load(f)
        sections = data.get("sections", [])
        files = set(s["file"] for s in sections)
        has_bm25 = "bm25" in data
        return {
            "indexed": True,
            "sections": len(sections),
            "files": len(files),
            "hybrid": has_bm25,
        }
    except Exception:
        return {"indexed": True, "error": True}


def get_session_info():
    """Get current session state."""
    session_dir = PROJECT_DIR / ".session"
    if not session_dir.exists():
        return {"active": False}

    state_file = session_dir / "state.md"
    checkpoint_file = session_dir / "checkpoint.md"

    info = {"active": True}

    if state_file.exists():
        content = state_file.read_text(encoding="utf-8", errors="ignore")
        if "ended" in content.lower():
            info["status"] = "ended"
        else:
            info["status"] = "active"

    if checkpoint_file.exists():
        content = checkpoint_file.read_text(encoding="utf-8", errors="ignore")
        # Count modified files
        info["files_modified"] = content.count("- ")

    # Check tool use counter
    counter_file = session_dir / "tool-use-counter"
    if counter_file.exists():
        try:
            info["tool_uses"] = int(counter_file.read_text().strip())
        except Exception:
            pass

    return info


def get_latest_handoff():
    """Get info about the latest handoff."""
    handoffs_dir = PROJECT_DIR / "handoffs"
    if not handoffs_dir.exists():
        return None

    handoffs = sorted(handoffs_dir.glob("HANDOFF_SESSION_*.md"))
    if not handoffs:
        return None

    latest = handoffs[-1]
    # Extract session number from filename
    match = re.search(r'SESSION_(\d+)', latest.name)
    session_num = match.group(1) if match else "?"

    return {
        "file": latest.name,
        "session": session_num,
        "date": latest.stat().st_mtime,
    }


def print_status(brief=False):
    """Print the full status overview."""
    # --- Gather all data ---
    agents = count_files(".claude/agents", "*.md")
    skills = len([d for d in (PROJECT_DIR / ".claude" / "skills").iterdir() if d.is_dir()]) if (PROJECT_DIR / ".claude" / "skills").exists() else 0
    hooks = count_files(".claude/hooks", "*.sh")

    scripts = sum(1 for s in ["vault-search.py", "codebase-map.py", "tldr-codefile.py",
                               "health-check.py", "diff-summary.py", "token-estimator.py",
                               "vault-status.py"]
                  if (PROJECT_DIR / s).exists() or (VAULT_ROOT / s).exists())

    patterns = count_learning_entries("PATTERNS.md")
    mistakes = count_learning_entries("MISTAKES.md")
    decisions = count_learning_entries("DECISIONS.md")
    improvements = count_learning_entries("IMPROVEMENTS.md")

    handoffs = count_files("handoffs", "HANDOFF_SESSION_*.md")
    latest_handoff = get_latest_handoff()

    search = get_search_stats()
    git = get_git_info()
    session = get_session_info()

    has_claude_md = (PROJECT_DIR / "CLAUDE.md").exists()
    claude_md_lines = 0
    if has_claude_md:
        claude_md_lines = (PROJECT_DIR / "CLAUDE.md").read_text().count("\n") + 1

    # --- Brief mode ---
    if brief:
        parts = [f"{agents} agents", f"{skills} skills", f"{hooks} hooks", f"{scripts} scripts"]
        learning_total = patterns + mistakes + decisions + improvements
        parts.append(f"{learning_total} learnings")
        parts.append(f"{handoffs} handoffs")
        if search.get("indexed"):
            parts.append(f"{search.get('sections', '?')} sections indexed")
        print(f"AI Dev Vault: {', '.join(parts)}")
        return

    # --- Full status ---
    project_name = PROJECT_DIR.name
    print(f"\n{C.BOLD}{C.CYAN}  AI Dev Vault: {project_name}{C.RESET}")
    print(f"{C.DIM}  {'=' * 55}{C.RESET}\n")

    # Components
    print(f"  {C.BOLD}Components{C.RESET}")
    print(f"    Agents:     {C.GREEN}{agents:>3d}{C.RESET} {C.DIM}(.claude/agents/){C.RESET}")
    print(f"    Skills:     {C.GREEN}{skills:>3d}{C.RESET} {C.DIM}(.claude/skills/){C.RESET}")
    print(f"    Hooks:      {C.GREEN}{hooks:>3d}{C.RESET} {C.DIM}(.claude/hooks/){C.RESET}")
    print(f"    Scripts:    {C.GREEN}{scripts:>3d}{C.RESET} {C.DIM}(vault-search, codebase-map, ...){C.RESET}")
    print(f"    CLAUDE.md:  {'  ' + C.GREEN + 'yes' + C.RESET if has_claude_md else '  ' + C.RED + 'no' + C.RESET} {C.DIM}({claude_md_lines} lines){C.RESET}")
    print()

    # Learning System
    total_learnings = patterns + mistakes + decisions + improvements
    print(f"  {C.BOLD}Learning System{C.RESET} {C.DIM}({total_learnings} total entries){C.RESET}")
    print(f"    Patterns:      {C.BLUE}{patterns:>3d}{C.RESET}")
    print(f"    Mistakes:      {C.BLUE}{mistakes:>3d}{C.RESET}")
    print(f"    Decisions:     {C.BLUE}{decisions:>3d}{C.RESET}")
    print(f"    Improvements:  {C.BLUE}{improvements:>3d}{C.RESET}")
    print()

    # Search Index
    print(f"  {C.BOLD}Search Index{C.RESET}")
    if search.get("indexed") and not search.get("error"):
        mode = "hybrid (BM25 + vector)" if search.get("hybrid") else "semantic only"
        print(f"    Status:    {C.GREEN}indexed{C.RESET}")
        print(f"    Sections:  {search.get('sections', '?'):,}")
        print(f"    Files:     {search.get('files', '?')}")
        print(f"    Mode:      {mode}")
    elif search.get("indexed"):
        print(f"    Status:    {C.YELLOW}index exists but unreadable{C.RESET}")
    else:
        print(f"    Status:    {C.RED}not indexed{C.RESET} {C.DIM}(run: python3 vault-search.py --reindex){C.RESET}")
    print()

    # Session History
    print(f"  {C.BOLD}Session History{C.RESET}")
    print(f"    Handoffs:  {handoffs}")
    if latest_handoff:
        date_str = datetime.fromtimestamp(latest_handoff["date"]).strftime("%Y-%m-%d")
        print(f"    Latest:    Session {latest_handoff['session']} ({date_str})")
    print()

    # Current Session
    if session.get("active"):
        print(f"  {C.BOLD}Current Session{C.RESET}")
        status = session.get("status", "unknown")
        status_color = C.GREEN if status == "active" else C.YELLOW
        print(f"    Status:    {status_color}{status}{C.RESET}")
        if session.get("files_modified"):
            print(f"    Modified:  {session['files_modified']} files")
        if session.get("tool_uses"):
            uses = session["tool_uses"]
            color = C.RED if uses > 100 else C.YELLOW if uses > 50 else ""
            print(f"    Tool uses: {color}{uses}{C.RESET}")
        print()

    # Git
    if git:
        print(f"  {C.BOLD}Git{C.RESET}")
        if git.get("branch"):
            print(f"    Branch:     {git['branch']}")
        if git.get("last_commit"):
            print(f"    Last:       {C.DIM}{git['last_commit']}{C.RESET}")
        if git.get("commits_today"):
            print(f"    Today:      {git['commits_today']} commits")
        if git.get("uncommitted"):
            print(f"    Uncommitted: {C.YELLOW}{git['uncommitted']} files{C.RESET}")
        print()

    # Available Commands
    print(f"  {C.BOLD}Available Commands{C.RESET}")
    commands = [
        ("/startup", "daily briefing"),
        ("/pipeline [task]", "full agent pipeline"),
        ("/closeout", "session end protocol"),
        ("/experiment", "structured sandbox"),
        ("/quality-gate", "typecheck + lint + test"),
        ("/context", "current session state"),
        ("/briefing", "status summary"),
        ("/backup", "vault backup"),
    ]
    for cmd, desc in commands:
        print(f"    {C.CYAN}{cmd:<22s}{C.RESET} {C.DIM}{desc}{C.RESET}")
    print()

    # Scripts
    print(f"  {C.BOLD}Scripts{C.RESET}")
    script_info = [
        ("vault-search.py", "semantic + keyword search"),
        ("codebase-map.py", "architecture visualization"),
        ("tldr-codefile.py", "compressed code summaries"),
        ("health-check.py", "vault diagnostics"),
        ("diff-summary.py", "git change summaries"),
        ("token-estimator.py", "token cost estimation"),
        ("vault-status.py", "this status view"),
    ]
    for script, desc in script_info:
        exists = (PROJECT_DIR / script).exists() or (VAULT_ROOT / script).exists()
        status = f"{C.GREEN}installed{C.RESET}" if exists else f"{C.DIM}not found{C.RESET}"
        print(f"    {script:<22s} {status}  {C.DIM}{desc}{C.RESET}")
    print()

    print(f"{C.DIM}  {'=' * 55}{C.RESET}")
    print(f"  {C.DIM}Run 'python3 health-check.py' for detailed diagnostics{C.RESET}")
    print()


def print_json_status():
    """Output status as JSON."""
    data = {
        "version": __version__,
        "project": PROJECT_DIR.name,
        "components": {
            "agents": count_files(".claude/agents", "*.md"),
            "skills": len([d for d in (PROJECT_DIR / ".claude" / "skills").iterdir() if d.is_dir()]) if (PROJECT_DIR / ".claude" / "skills").exists() else 0,
            "hooks": count_files(".claude/hooks", "*.sh"),
        },
        "learning": {
            "patterns": count_learning_entries("PATTERNS.md"),
            "mistakes": count_learning_entries("MISTAKES.md"),
            "decisions": count_learning_entries("DECISIONS.md"),
            "improvements": count_learning_entries("IMPROVEMENTS.md"),
        },
        "search": get_search_stats(),
        "git": get_git_info(),
        "session": get_session_info(),
        "handoffs": count_files("handoffs", "HANDOFF_SESSION_*.md"),
    }
    print(json.dumps(data, indent=2, default=str))


def main():
    args = sys.argv[1:]

    if "--version" in args:
        print(f"vault-status {__version__}")
        sys.exit(0)

    if "--help" in args:
        print(__doc__)
        sys.exit(0)

    if not sys.stdout.isatty():
        C.disable()

    if "--json" in args:
        print_json_status()
    elif "--brief" in args:
        print_status(brief=True)
    else:
        print_status()


if __name__ == "__main__":
    main()
