#!/usr/bin/env python3
"""
dev_session_doc.py – Dokumentiert die zuletzt abgeschlossene Timetrack-Session in DEVLOG.md.
Wird automatisch vom Claude Code Stop-Hook aufgerufen.
"""

import json
import os
import subprocess
from datetime import datetime, timezone

BASE_DIR    = os.path.dirname(os.path.abspath(__file__))
DATA_FILE   = os.path.expanduser("~/.claude/timetrack.json")
DEVLOG      = os.path.join(BASE_DIR, "DEVLOG.md")
BACKEND_DIR = os.path.join(BASE_DIR, "backend")


# ── Helpers ───────────────────────────────────────────────────────────────────

def parse_iso(s: str) -> datetime:
    if s.endswith("Z"):
        s = s[:-1] + "+00:00"
    return datetime.fromisoformat(s)


def format_duration(seconds: float) -> str:
    seconds = int(seconds)
    h = seconds // 3600
    m = (seconds % 3600) // 60
    if h > 0:
        return f"{h}h {m:02d}m"
    return f"{m}m"


def local_display(dt: datetime) -> str:
    return dt.astimezone().strftime("%H:%M")


def local_date(dt: datetime) -> str:
    return dt.astimezone().strftime("%Y-%m-%d")


def run(cmd: list[str]) -> str:
    """Run a command and return stdout; return '' on any error."""
    try:
        result = subprocess.run(
            cmd,
            capture_output=True,
            text=True,
            timeout=15,
        )
        return result.stdout.strip()
    except Exception:
        return ""


# ── Core logic ────────────────────────────────────────────────────────────────

def get_last_completed_session(data: dict) -> dict | None:
    """Return the most recently *completed* session (end != None)."""
    completed = [s for s in data.get("sessions", []) if s.get("end") is not None]
    if not completed:
        return None
    return max(completed, key=lambda s: s["end"])


def get_commits(start_iso: str, end_iso: str) -> list[str]:
    """Return list of 'HASH message' strings for commits within the session window."""
    start_dt = parse_iso(start_iso)
    end_dt   = parse_iso(end_iso)

    # git log uses local times via --after/--before; pass UTC explicitly as ISO
    after  = start_dt.strftime("%Y-%m-%dT%H:%M:%SZ")
    before = end_dt.strftime("%Y-%m-%dT%H:%M:%SZ")

    raw = run([
        "git", "-C", BACKEND_DIR,
        "log", "--oneline",
        f"--after={after}",
        f"--before={before}",
    ])
    if not raw:
        return []
    return [line for line in raw.splitlines() if line.strip()]


def get_diff_stat() -> list[str]:
    """Return lines from git diff --stat HEAD~1 HEAD."""
    raw = run([
        "git", "-C", BACKEND_DIR,
        "diff", "--stat", "HEAD~1", "HEAD",
    ])
    if not raw:
        return []
    lines = raw.splitlines()
    # Drop the summary line (last line with "N files changed …")
    return [l for l in lines if l.strip() and " | " in l]


def build_entry(session: dict) -> str:
    start_dt = parse_iso(session["start"])
    end_dt   = parse_iso(session["end"])
    elapsed  = (end_dt - start_dt).total_seconds()
    duration = format_duration(elapsed)

    date_str  = local_date(start_dt)
    start_str = local_display(start_dt)
    end_str   = local_display(end_dt)
    desc      = session.get("description") or "Claude Code Session"

    commits   = get_commits(session["start"], session["end"])
    diff_stat = get_diff_stat()

    lines: list[str] = []
    lines.append(f"## {date_str} {start_str} – {end_str} ({duration})")
    lines.append(f"**Beschreibung:** {desc}")
    lines.append("")

    # Commits section
    lines.append("### Commits")
    if commits:
        for c in commits:
            lines.append(f"- {c}")
    else:
        lines.append("Keine Commits in dieser Session.")
    lines.append("")

    # Changed files section
    lines.append("### Geänderte Dateien")
    if diff_stat:
        for l in diff_stat:
            # Normalize: "  path/file | 5 ++-" → "- path/file (+5/-2)"
            # Keep it simple and just relay the stat line
            lines.append(f"- {l.strip()}")
    else:
        lines.append("Keine Änderungen ermittelbar.")
    lines.append("")
    lines.append("---")
    lines.append("")

    return "\n".join(lines)


def append_to_devlog(entry: str) -> None:
    # Ensure file exists with a header
    if not os.path.exists(DEVLOG):
        with open(DEVLOG, "w", encoding="utf-8") as f:
            f.write("# TimeMaster – Dev Log\n\n")

    with open(DEVLOG, "a", encoding="utf-8") as f:
        f.write(entry)


# ── Entry point ───────────────────────────────────────────────────────────────

def main() -> None:
    if not os.path.exists(DATA_FILE):
        return  # Nothing to document

    with open(DATA_FILE, "r", encoding="utf-8") as f:
        data = json.load(f)

    session = get_last_completed_session(data)
    if not session:
        return

    entry = build_entry(session)
    append_to_devlog(entry)


if __name__ == "__main__":
    try:
        main()
    except Exception:
        # Never crash Claude Code
        pass
