#!/usr/bin/env python3
"""DEPRECATED: logic now embedded in build pipeline; this script is preserved
for historical reference only.

The re-attribution step is now `reattribute_lost_messages()` in
`src/claude_timeline/build/pipeline.py`, called as a regular phase of
`run_build()` so that `build-db --full` rebuilds stay idempotent for
re-attribution. Do not invoke this script as part of normal builds.

Original docstring follows.

Re-attribute messages.account = '/home/m/.claude-lost' to the real profile
that owns each message's session.

Uses the on-disk session->profile mapping: each <UUID>.jsonl in a real
profile's projects/ subtree resolves that session to that profile. The 13
orphan sessions (no <UUID>.jsonl in any real profile) keep .claude-lost.

Also rebuilds messages_fts and the Parquet snapshot.

Usage:
  uv run scripts/reattribute-lost-messages          # dry-run
  uv run scripts/reattribute-lost-messages --apply  # actually update
"""
from __future__ import annotations

import argparse
import sqlite3
from pathlib import Path

from claude_timeline.config import DB_PATH, SNAPSHOT_DIR
from claude_timeline.build.snapshot import export_snapshot

LOST = "/home/m/.claude-lost"
REAL_PROFILES = [
    Path.home() / ".claude-personal",
    Path.home() / ".claude-work",
    Path.home() / ".claude-the-third",
]


def build_session_map() -> dict[str, str]:
    """session_id -> profile path string. Walks every real profile's
    projects/<encoded>/<UUID>.jsonl and bins by UUID."""
    smap: dict[str, list[str]] = {}
    for prof in REAL_PROFILES:
        proj = prof / "projects"
        if not proj.is_dir():
            continue
        for jl in proj.glob("*/*.jsonl"):
            uid = jl.stem
            smap.setdefault(uid, []).append(str(prof))
    # Verify no UUID maps to multiple profiles (would be a bug we can't resolve here).
    for uid, profs in list(smap.items()):
        if len(set(profs)) > 1:
            print(f"WARN: session {uid} appears in multiple profiles: {profs}; using first")
    return {uid: profs[0] for uid, profs in smap.items()}


def main() -> int:
    ap = argparse.ArgumentParser(description=__doc__)
    ap.add_argument("--apply", action="store_true",
                    help="Actually update messages and rebuild snapshot.")
    args = ap.parse_args()

    smap = build_session_map()
    print(f"[reattr] sessions in real profiles: {len(smap)}")

    conn = sqlite3.connect(str(DB_PATH))

    # How many .claude-lost messages map to a real profile?
    rows = conn.execute(
        "SELECT session_id, count(*) FROM messages WHERE account = ? GROUP BY session_id",
        (LOST,),
    ).fetchall()
    total_lost = sum(c for _, c in rows)
    mapped = [(sid, c) for sid, c in rows if sid in smap]
    unmapped = [(sid, c) for sid, c in rows if sid not in smap]
    mapped_total = sum(c for _, c in mapped)
    unmapped_total = sum(c for _, c in unmapped)

    # Per-profile breakdown of what would be re-attributed
    by_target: dict[str, int] = {}
    for sid, c in mapped:
        by_target[smap[sid]] = by_target.get(smap[sid], 0) + c

    print(f"[reattr] .claude-lost messages: {total_lost:,}")
    print(f"[reattr]   mappable to real profile: {mapped_total:,} across {len(mapped)} sessions")
    print(f"[reattr]   stay as orphans:           {unmapped_total:,} across {len(unmapped)} sessions")
    print()
    print("Re-attribution distribution:")
    for prof, n in sorted(by_target.items()):
        print(f"  {prof:<40} {n:>6}")
    print()

    if not args.apply:
        print("Dry-run -- pass --apply to execute.")
        return 0

    cur = conn.cursor()
    updated = 0
    for sid, real_acct in smap.items():
        n = cur.execute(
            "UPDATE messages SET account = ? WHERE account = ? AND session_id = ?",
            (real_acct, LOST, sid),
        ).rowcount
        updated += n
    conn.commit()
    print(f"[reattr] updated {updated:,} message rows")

    # Rebuild messages_fts since we changed account (FTS is over `display` only,
    # so technically not required, but keep it consistent).
    conn.execute("INSERT INTO messages_fts(messages_fts) VALUES('rebuild')")
    conn.commit()

    # Re-export snapshot so DuckDB-WASM matches.
    export_snapshot(conn, SNAPSHOT_DIR)
    print("[reattr] snapshot rebuilt")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
