#!/usr/bin/env python3
"""Clean up the rules database: remove duplicates, OCR artifacts, and noise."""

import json
import re
import sys
from collections import Counter

INPUT = "database/rules/rules-database.json"
OUTPUT = "database/rules/rules-database-cleaned.json"

def is_noise(content):
    """Return True if content is likely OCR noise."""
    text = content.strip()
    if len(text) < 10:
        return True
    # Only symbols/whitespace
    if re.sub(r'[\s™®©—–‘’“”•‣…​‌‍﻿]', '', text).strip() == "":
        return True
    # Only page numbers
    if re.match(r'^\s*\d+\s*$', text):
        return True
    # Only index entries
    if text.lower() == "index":
        return True
    return False

def is_credits(content):
    """Return True if content is credits/copyright."""
    text = content.lower()
    return any(kw in text for kw in [
        "credits", "designed by", "lead developer", "art direction",
        "production manager", "game designer", "game producer",
        "publisher", "licensing", "graphic design",
        "cover art", "copyright", "game workshop",
        "ffg", "fantasy flight games",
    ])

def is_page_header(content):
    """Return True if content looks like a page header/number."""
    text = content.strip()
    # Page number lines like "88 —" or "165 115"
    if re.match(r'^\d+\s*(—|—\s*\d+)?$', text):
        return True
    # "GAME?" or "GAME? (p.X"
    if re.match(r'^GAME\?\s*\(p\.', text):
        return True
    return False

def fix_title(title):
    """Fix common OCR title issues."""
    # Remove leading/trailing whitespace and control chars
    title = title.strip()
    # Remove control characters
    title = re.sub(r'[\x00-\x1f\x7f]', '', title).strip()
    # Fix "GAME?" -> "GAME"
    title = re.sub(r'^GAME\?', 'GAME', title)
    # Fix "fellowShip" -> "Fellowship"
    title = re.sub(r'^(fel)\s*\(', r'\1 (', title, flags=re.IGNORECASE)
    # Fix "balliStiC" -> "Ballistic"
    title = re.sub(r'^(balliStiC)\s*Skill', r'Ballistic Skill', title, flags=re.IGNORECASE)
    # Fix "perCeption" -> "Perception"
    title = re.sub(r'^(perCeption)', r'Perception', title, flags=re.IGNORECASE)
    # Fix "ExaMple" -> "Example"
    title = re.sub(r'^(exaMple)', r'Example', title, flags=re.IGNORECASE)
    # Fix "s" on its own line
    if title.strip() == "s":
        return None
    # Fix "88 —" or "165 115" style page numbers
    if re.match(r'^\d+\s*(—|—\s*\d+)?$', title):
        return None
    # Fix "therefore, and you will know no fear." (p.34, Core Rulebook)
    if re.match(r'^.*\(p\.\d+,\s*(Core Rulebook|Game Master\'s Kit)\)\s*$', title):
        return None
    # Fix "— (p.XX, Source)"
    if re.match(r'^—\s*\(p\.\d+,\s*(Core Rulebook|Game Master\'s Kit)\)\s*$', title):
        return None
    return title

def dedup_rules(rules):
    """Remove duplicate rules, keeping the one with the most content."""
    seen = {}
    kept = []
    removed = []

    for rule in rules:
        title = fix_title(rule.get('title', ''))
        if title is None:
            removed.append(('title_fix_none', rule))
            continue

        key = title.strip().lower()
        content = rule.get('content', '')

        if key in seen:
            existing = seen[key]
            if len(content) > len(existing.get('content', '')):
                removed.append(('duplicate', existing))
                seen[key] = rule
            else:
                removed.append(('duplicate', rule))
        else:
            seen[key] = rule

    # Update titles in the kept rules
    for rule in seen.values():
        rule['title'] = fix_title(rule.get('title', ''))

    return list(seen.values()), removed

def main():
    with open(INPUT) as f:
        data = json.load(f)

    rules = data['rules']
    print(f"Loaded {len(rules)} rules")

    # Phase 1: Remove noise
    noise_rules = [r for r in rules if is_noise(r.get('content', ''))]
    credits_rules = [r for r in rules if is_credits(r.get('content', ''))]
    header_rules = [r for r in rules if is_page_header(r.get('content', ''))]

    print(f"\nNoise (short/symbols): {len(noise_rules)}")
    print(f"Credits/copyright: {len(credits_rules)}")
    print(f"Page headers: {len(header_rules)}")

    # Phase 2: Dedup
    deduped, dups = dedup_rules(rules)
    print(f"\nDuplicates removed: {len(dups)}")

    # Phase 3: Combine noise removal
    cleaned = []
    for r in deduped:
        content = r.get('content', '')
        if is_noise(content) or is_credits(content) or is_page_header(content):
            continue
        cleaned.append(r)

    print(f"\nFinal count: {len(cleaned)} (was {len(rules)})")
    print(f"Removed: {len(rules) - len(cleaned)}")

    # Show what was removed
    print("\n--- Removed rules ---")
    for reason, r in dups:
        print(f"  [{reason}] {r.get('title', '?')[:60]}")
    for r in noise_rules + credits_rules + header_rules:
        if r not in cleaned:
            print(f"  [noise] {r.get('title', '?')[:60]}")

    # Write output
    out = {'rules': cleaned}
    with open(OUTPUT, 'w') as f:
        json.dump(out, f, indent=2, ensure_ascii=False)

    print(f"\nWrote cleaned rules to {OUTPUT}")

    # Show category breakdown
    from collections import Counter
    cats = Counter(r.get('category', 'unknown') for r in cleaned)
    print("\nCategories:")
    for c, n in cats.most_common():
        print(f"  {c}: {n}")

if __name__ == '__main__':
    main()
