#!/usr/bin/python3
# topics.py: a cross-conversation Topics index, the macOS equivalent of the iOS People & Topics view.
# Topics are produced by the organizer (per-clip sidecar ai.topics); this inverts them into
# topic -> [conversations], ranked by how many conversations mention each topic (ties alphabetical),
# exactly like the iOS aggregator. Hidden conversations (meta.py) are excluded. No network, no model.
#
#   topics.py --rec-dir DIR
#
# Output JSON: {ok, total, topics:[{name, count, conversations:[{title,time_range,who_with,when,summary}]}]}
# Pure stdlib.
import sys, os, json

sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
try:
    import meta as meta_store
except Exception:
    meta_store = None

HOME = os.path.expanduser("~")
DEFAULT_REC = os.path.join(HOME, "Recordings/Epiphani")


def load_diary(rec_dir):
    try:
        with open(os.path.join(rec_dir, "diary.json"), encoding="utf-8") as f:
            return json.load(f)
    except (OSError, ValueError):
        return None


def _sidecar_topics(rec_dir, fname):
    if not fname:
        return []
    try:
        with open(os.path.join(rec_dir, ".organized", fname + ".json"), encoding="utf-8") as f:
            return (json.load(f).get("ai", {}) or {}).get("topics") or []
    except (OSError, ValueError):
        return []


def _conv_key(conv):
    clips = conv.get("clips") or []
    return clips[0].get("file", "") if clips else ""


def build(rec_dir):
    diary = load_diary(rec_dir)
    if diary is None:
        return {"ok": False, "error": "No diary yet. Record something and organize it first.",
                "topics": [], "total": 0}
    hidden = set(meta_store.hidden_keys(meta_store.load_meta(rec_dir))) if meta_store else set()
    # topic (normalized) -> {display, conversations:[...]}; one conversation counts once per topic.
    index = {}
    for day in diary.get("days", []):
        for conv in day.get("conversations", []):
            if _conv_key(conv) in hidden:
                continue
            seen_here = set()
            for clip in conv.get("clips") or []:
                for raw in _sidecar_topics(rec_dir, clip.get("file", "")):
                    name = (raw or "").strip()
                    if not name:
                        continue
                    norm = name.lower()
                    if norm in seen_here:   # this conversation already counted for this topic
                        continue
                    seen_here.add(norm)
                    slot = index.setdefault(norm, {"display": name, "conversations": []})
                    slot["conversations"].append({
                        "title": conv.get("title", ""), "time_range": conv.get("time_range", ""),
                        "who_with": (conv.get("who_with") or "").strip(),
                        "summary": conv.get("summary", ""),
                        "when": "%s · %s" % (day.get("heading") or day.get("date", ""),
                                                  conv.get("time_range", "")),
                    })
    topics = [{"name": v["display"], "count": len(v["conversations"]),
               "conversations": v["conversations"]} for v in index.values()]
    # Most-discussed first; ties broken alphabetically (case-insensitive), mirroring the iOS ranker.
    topics.sort(key=lambda t: (-t["count"], t["name"].lower()))
    return {"ok": True, "total": len(topics), "topics": topics}


def main(argv):
    rec_dir = os.path.expanduser(argv[argv.index("--rec-dir") + 1]) if "--rec-dir" in argv else DEFAULT_REC
    sys.stdout.write(json.dumps(build(rec_dir), ensure_ascii=False))


if __name__ == "__main__":
    main(sys.argv[1:])
