#!/usr/bin/env python3
"""
Standalone Python fallback for knowledge-db.
Used when the Rust binary is not installed.

Usage:
  knowledge-py append pitfalls '## tool\nfastapi\n...'
  knowledge-py read pitfalls
  knowledge-py search pitfalls 'tool:fastapi timeout'
  knowledge-py stats
"""

import os
import re
import sys
from pathlib import Path


STORE = Path.home() / ".hermes" / "knowledge"


def parse_h2(content: str) -> dict:
    fields = {}
    cur = None
    val = []
    for line in content.split("\n"):
        s = line.strip()
        if s.startswith("## "):
            if cur:
                v = "\n".join(val).strip()
                if v:
                    fields[cur] = v
                val = []
            cur = s[3:].strip().lower()
        elif cur is not None:
            val.append(line)
    if cur:
        v = "\n".join(val).strip()
        if v:
            fields[cur] = v
    return fields


def slugify(text: str, n: int = 80) -> str:
    return re.sub(r"[^a-z0-9]+", "-", text.lower().strip()).strip("-")[:n]


def resolve_path(cat: str, fields: dict) -> str:
    parts = [cat]
    for f in ["tool", "severity", "domain", "type"]:
        if len(parts) >= 3:
            break
        if f in fields:
            s = slugify(fields[f])
            if s:
                parts.append(s)
    return "/".join(parts)


def gen_slug(fields: dict) -> str:
    for f in ["title", "source", "fix", "summary"]:
        if f in fields:
            s = slugify(fields[f])
            if s:
                return s
    for v in fields.values():
        if len(v) > 5:
            return slugify(v)
    return "untitled"


def cmd_append(cat: str, content: str):
    fields = parse_h2(content)
    if not fields:
        print("error: no ## field headers found", file=sys.stderr)
        sys.exit(1)
    d = resolve_path(cat, fields)
    slug = gen_slug(fields)
    path = STORE / d / f"{slug}.md"
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text(content)
    print(f"{d}/{slug}.md")


def cmd_read(cat: str):
    d = STORE / cat
    if not d.exists():
        return
    files = sorted(d.rglob("*.md"))
    out = []
    for i, f in enumerate(files):
        c = f.read_text().strip()
        if i > 0:
            out.append("---")
        out.append(c)
    if out:
        print("\n".join(out))


def cmd_search(cat: str, query: str):
    d = STORE / cat
    if not d.exists():
        print(f"No matches for \"{query}\" in {cat}")
        return

    parts = query.split()
    ff = {}
    tokens = []
    for p in parts:
        if ":" in p:
            k, v = p.split(":", 1)
            ff[k.lower()] = v.lower()
        else:
            tokens.append(p.lower())

    matches = []
    for f in sorted(d.rglob("*.md")):
        content = f.read_text()
        fields = parse_h2(content)
        if ff and not all(fields.get(k, "").lower() == v for k, v in ff.items()):
            continue
        if tokens:
            lo = content.lower()
            hits = sum(
                1
                for t in tokens
                if t in lo or any(t in v.lower() for v in fields.values())
            )
            if hits:
                matches.append((-hits, content.strip()))
        else:
            matches.append((0, content.strip()))

    matches.sort()
    if not matches:
        print(f"No matches for \"{query}\" in {cat}")
        return
    print("\n---\n".join(m[1] for m in matches))


def cmd_stats(cat: str = None):
    if cat:
        d = STORE / cat
        if not d.exists():
            print(f"category: {cat}\n  entries: 0")
            return
        files = list(d.rglob("*.md"))
        print(f"category: {cat}\n  entries: {len(files)}")
    else:
        cats = {}
        for p in STORE.iterdir():
            if p.is_dir() and not p.name.startswith("."):
                count = len(list(p.rglob("*.md")))
                if count:
                    cats[p.name] = count
        total = sum(cats.values())
        print(f"store: {STORE}")
        print(f"  total entries: {total}")
        print("  categories:")
        for name, count in sorted(cats.items(), key=lambda x: -x[1]):
            print(f"    {name}: {count}")


if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("usage: knowledge-py <append|read|search|stats> ...")
        sys.exit(1)

    cmd = sys.argv[1]
    if cmd == "append" and len(sys.argv) >= 4:
        cmd_append(sys.argv[2], " ".join(sys.argv[3:]))
    elif cmd == "read" and len(sys.argv) >= 3:
        cmd_read(sys.argv[2])
    elif cmd == "search" and len(sys.argv) >= 4:
        cmd_search(sys.argv[2], " ".join(sys.argv[3:]))
    elif cmd == "stats":
        cmd_stats(sys.argv[2] if len(sys.argv) > 2 else None)
    else:
        print(f"unknown command: {cmd}", file=sys.stderr)
        sys.exit(1)
