#!/usr/bin/env python3
"""Read lessons-index.jsonl, tag each lesson with topic categories +
Aria/Kadi relevance score, write enriched index to lessons-classified.jsonl.
"""
from __future__ import annotations

import json
import re
from collections import Counter
from pathlib import Path

INDEX_PATH = Path("/root/aria/state/maven/lessons-index.jsonl")
OUT_PATH = Path("/root/aria/state/maven/lessons-classified.jsonl")

# Topic taxonomy mirrors Maven's own top-nav.
# Patterns are case-insensitive regex strings.
TAXONOMY = {
    "AI/Agents": [
        r"\bagent(ic|s)?\b", r"\bllm\b", r"\brag\b", r"\bmcp\b", r"\bclaude\b",
        r"\bopenai\b", r"\bgpt\b", r"\bgemini\b", r"\bcontext engineering\b",
        r"\bprompt", r"\bfine.?tun(e|ing)\b", r"\bevals?\b", r"\bevaluations?\b",
        r"\bsynthetic data\b", r"\bmodel\b", r"\binference\b", r"\bskill(s)?\b",
    ],
    "AI/Tooling": [
        r"\bclaude code\b", r"\bcursor\b", r"\bcopilot\b", r"\bvibe.?cod",
        r"\bno.?code\b", r"\blovable\b", r"\bv0\b", r"\bbolt\b", r"\bwindsurf\b",
        r"\breplit\b", r"\bnotebook\b", r"\bn8n\b", r"\bzapier\b",
    ],
    "Engineering/Backend": [
        r"\bbackend\b", r"\bapi(s)?\b", r"\bdatabase\b", r"\bsupabase\b",
        r"\bpostgres\b", r"\bsql\b", r"\bnode\.?js\b", r"\bpython\b",
        r"\bmicroservice\b", r"\bdocker\b", r"\bkubernetes\b",
        r"\bdistributed\b", r"\bdata pipeline\b", r"\bmlops?\b", r"\bllmops?\b",
    ],
    "Engineering/Frontend": [
        r"\breact\b", r"\bnext\.?js\b", r"\btypescript\b", r"\bfrontend\b",
        r"\btailwind\b", r"\bshadcn\b", r"\bui kit\b",
    ],
    "Engineering/Observability": [
        r"\bobservab(le|ility)\b", r"\btrac(e|ing)\b", r"\bmonitor", r"\bdebug",
        r"\bevals?\b", r"\bevaluation\b", r"\bdataset\b", r"\bbenchmark\b", r"\bquality\b",
    ],
    "Product": [
        r"\bproduct manager\b", r"\bpm\b", r"\bproduct.led\b", r"\bdiscovery\b",
        r"\bvalidation\b", r"\bjtbd\b", r"\bjobs.to.be.done\b", r"\bideation\b",
        r"\bmvp\b", r"\bnpv\b", r"\bnorth star\b", r"\bgrowth\b", r"\bretention\b",
        r"\bopportunity\b", r"\bideas?\b",
    ],
    "Product/Strategy": [
        r"\bstrateg", r"\broadmap\b", r"\bopportunity\b", r"\bprioritization\b",
        r"\bopportunit(y|ies)\b",
    ],
    "Design": [
        r"\bdesign system\b", r"\bux\b", r"\bui\b", r"\bfigma\b", r"\bdesigner\b",
        r"\bvisual\b", r"\binterface\b", r"\bdesign\b",
    ],
    "Marketing": [
        r"\bmarket(ing)?\b", r"\bgrowth\b", r"\bseo\b", r"\bbranding?\b",
        r"\bcontent\b", r"\bcampaign\b", r"\bemail\b", r"\bcopywrit",
        r"\bperformance marketing\b", r"\bppc\b", r"\bsocial\b",
    ],
    "Sales/RevOps": [
        r"\bsales\b", r"\brev.?ops\b", r"\bpipeline\b", r"\bquota\b", r"\bclos(e|ing)\b",
        r"\boutbound\b", r"\bbusiness development\b", r"\bcrm\b",
    ],
    "Leadership/Management": [
        r"\bleader(ship)?\b", r"\bmanager\b", r"\bmanagement\b", r"\bexecutive\b",
        r"\bteam\b", r"\bculture\b", r"\bhiring\b", r"\bcoach", r"\bmentoring\b",
        r"\bdecision\b", r"\bdelegate\b", r"\b1:1\b",
    ],
    "Founders/Startups": [
        r"\bfounder\b", r"\bstartup\b", r"\bventure\b", r"\bfundraising\b",
        r"\bseries [a-c]\b", r"\bpitch\b", r"\binvestor\b", r"\bbootstrap\b",
        r"\bgtm\b", r"\bgo.to.market\b",
    ],
    "Career/Productivity": [
        r"\bcareer\b", r"\bproductiv(e|ity)\b", r"\bhabit\b", r"\binterview\b",
        r"\bnegotia", r"\bsalary\b", r"\bbalance\b", r"\bflow\b", r"\bskill",
    ],
    "Data/Analytics": [
        r"\banalytic", r"\bdata sci", r"\bdashboard\b", r"\bmetric\b", r"\bkpi\b",
        r"\bsql\b", r"\btableau\b", r"\bdbt\b", r"\bwarehouse\b", r"\bbi\b",
    ],
    "Security/Governance": [
        r"\bsecurit", r"\bgovern", r"\bcomplian", r"\bgdpr\b", r"\bsoc.?2\b",
        r"\bprivacy\b", r"\bauth\b", r"\bidentity\b", r"\brisk\b",
    ],
}

ARIA_KEYWORDS: list[tuple[str, int]] = [
    ("agent", 5), ("mcp", 5), ("claude code", 5), ("skill", 4), ("plugin", 4),
    ("context engineering", 5), (r"\bevals?\b", 4), ("rag", 4), ("observab", 4),
    ("multi.?agent", 4), ("autonomous", 4), ("memory", 3), ("knowledge graph", 4),
    ("prompt engineer", 3), ("dataset", 3), ("orchestrat", 4), ("workflow", 2),
    ("vibe.?cod", 3), ("supabase", 4), ("next.?js", 3), ("typescript", 2),
    ("react", 2), ("vercel", 3), ("postgres", 3), ("rls", 3),
    ("plt", 5), ("pmo", 5), ("workstream", 3), ("workshop", 2), ("lieferant", 5),
    ("supplier", 5), ("bmw", 4), ("automotive", 4), ("manufacturing", 3),
    ("oee", 5), ("cycle time", 5), ("qaf", 5), ("quotation", 3),
]


def classify(row: dict) -> dict:
    text = " ".join(
        str(row.get(k) or "")
        for k in ("title", "description", "instructor_headline", "instructor_title", "course_name")
    ).lower()

    tags = []
    for tag, patterns in TAXONOMY.items():
        for p in patterns:
            if re.search(p, text):
                tags.append(tag)
                break

    aria_score = 0
    matched_kw = []
    for kw, weight in ARIA_KEYWORDS:
        if re.search(kw, text):
            aria_score += weight
            matched_kw.append(kw)

    return {
        **row,
        "tags": sorted(set(tags)),
        "aria_score": aria_score,
        "aria_matched_keywords": matched_kw[:8],
    }


def main():
    rows = []
    bad = 0
    for line in INDEX_PATH.read_text().splitlines():
        if not line.strip():
            continue
        try:
            rows.append(json.loads(line))
        except json.JSONDecodeError:
            bad += 1
    if bad:
        print(f"# warning: skipped {bad} malformed lines (likely mid-write from concurrent crawler)")
    print(f"# input: {len(rows)} lessons")
    enriched = [classify(r) for r in rows]
    with OUT_PATH.open("w") as f:
        for r in enriched:
            f.write(json.dumps(r, ensure_ascii=False) + "\n")
    print(f"# wrote {len(enriched)} to {OUT_PATH}")
    tag_counter: Counter = Counter()
    for r in enriched:
        for t in r["tags"]:
            tag_counter[t] += 1
    print("\n== Tag distribution ==")
    for tag, n in tag_counter.most_common():
        print(f"  {n:5}  {tag}")
    print("\n== Aria-Top 20 ==")
    top = sorted(enriched, key=lambda r: r["aria_score"], reverse=True)[:20]
    for r in top:
        t = r.get('title') or '(no title)'
        print(f"  {r['aria_score']:3}  {t[:80]} (by {r.get('instructor_name')})")


if __name__ == "__main__":
    main()
