#!/usr/bin/env python3
"""
Reddit Idea Generator — Proof of Concept v5
Uses Reddit RSS feeds (Atom XML). No browser needed.
Trafilatura for clean text extraction. SQLite for storage.

Usage: python3 reddit_proof.py [count]
Example: python3 reddit_proof.py 20
"""

import sys
import json
import re
import xml.etree.ElementTree as ET
import sqlite3
import os
import time
import urllib.request
import urllib.error
from datetime import datetime, timezone
from html import unescape

import trafilatura

DB_PATH = os.path.join(os.path.dirname(__file__), "oracle.db")
SCHEMA_PATH = os.path.join(os.path.dirname(__file__), "schema.sql")

SUBREDDITS = [
    "MachineLearning", "artificial", "LocalLLaMA", "Startups",
]


def init_db():
    conn = sqlite3.connect(DB_PATH)
    with open(SCHEMA_PATH) as f:
        conn.executescript(f.read())
    conn.commit()
    return conn


def fetch_rss(subreddit, sort="hot"):
    """Fetch RSS feed for a subreddit. Returns parsed entries."""
    url = f"https://www.reddit.com/r/{subreddit}/{sort}/.rss?limit=50"
    req = urllib.request.Request(url, headers={"User-Agent": "oracle-reddit-proof/1.0"})

    for attempt in range(3):
        try:
            with urllib.request.urlopen(req, timeout=15) as resp:
                xml_data = resp.read().decode("utf-8")
            break
        except urllib.error.HTTPError as e:
            if e.code == 429:
                wait = 5 * (attempt + 1)
                print(f"    429 on r/{subreddit}, retry in {wait}s")
                time.sleep(wait)
                continue
            print(f"    RSS error r/{subreddit}: {e}")
            return []
        except Exception as e:
            print(f"    RSS error r/{subreddit}: {e}")
            return []
    else:
        print(f"    r/{subreddit}: still rate limited, skip")
        return []

    # Parse Atom XML — find all <entry> elements
    root = ET.fromstring(xml_data)
    entries = []

    # Handle namespace: Atom uses http://www.w3.org/2005/Atom
    # But ET.findall with ns prefix requires registering the namespace
    # Simpler approach: strip namespace from tags and search directly
    for entry in root.iter():
        # Get local name (strip namespace)
        tag = entry.tag.split("}")[-1] if "}" in entry.tag else entry.tag

        if tag == "entry":
            title = None
            link = None
            author = ""
            content = ""
            pub = ""
            eid = ""

            for child in entry:
                ctag = child.tag.split("}")[-1]
                if ctag == "title":
                    title = child.text
                elif ctag == "link":
                    link = child.get("href", "")
                elif ctag == "author":
                    name_el = child[0] if child else None
                    if name_el:
                        name_tag = name_el.tag.split("}")[-1]
                        if name_tag == "name":
                            author = name_el.text or ""
                elif ctag == "content":
                    content = child.text or ""
                elif ctag == "published":
                    pub = child.text or ""
                elif ctag == "id":
                    eid = child.text or ""

            if title and link:
                entries.append({
                    "title": unescape(title.strip()),
                    "url": link,
                    "author": unescape(author.strip()),
                    "content": content,
                    "published": pub,
                    "id": eid,
                    "subreddit": subreddit,
                })

    return entries


def clean_html_content(html):
    """Extract readable text from Reddit's HTML content."""
    if not html:
        return ""
    text = re.sub(r"<!--.*?-->", "", html, flags=re.DOTALL)
    text = re.sub(r"<div[^>]*>", "\n", text)
    text = re.sub(r"</div>", "\n", text)
    text = re.sub(r"<br\s*/?>", "\n", text, flags=re.I)
    text = re.sub(r"<[^>]+>", "", text)
    text = unescape(text)
    text = re.sub(r"\n\s*\n+", "\n\n", text)
    return text.strip()


def main():
    if len(sys.argv) > 1:
        count = int(sys.argv[1])
    else:
        count = 20

    print(f"=== Reddit Idea Generator — Proof of Concept v5 ===")
    print(f" count: {count}")
    print()

    conn = init_db()
    cursor = conn.cursor()

    # Step 1: Fetch RSS
    print(f"[1/3] Fetching RSS feeds...")
    all_entries = []
    seen_ids = set()

    for i, sub in enumerate(SUBREDDITS):
        entries = fetch_rss(sub)
        new = [e for e in entries if e["id"] not in seen_ids]
        seen_ids.update(e["id"] for e in new)
        all_entries.extend(new)
        if new:
            print(f"  r/{sub}: {len(new)} entries")
        # Rate limit between subreddits
        if i < len(SUBREDDITS) - 1:
            time.sleep(3)

    print(f"  Total: {len(all_entries)} entries")

    if not all_entries:
        print("\n  No entries fetched. Reddit may be rate-limiting this IP.")
        print("  Try again later or use fewer subreddits.")
        sys.exit(1)

    # Limit to count
    entries_to_store = all_entries[:count]
    print(f"  Storing {len(entries_to_store)} entries")

    # Step 2: Store
    stored = 0
    for entry in entries_to_store:
        post_id = entry["id"].replace("t3_", "")
        content_text = clean_html_content(entry["content"])

        # Signal score — RSS hot feed already sorted by relevance
        # Use position-based scoring (higher rank = higher score)
        idx = entries_to_store.index(entry)
        score = max(10.0 - idx * 0.5, 1.0)

        # Category tags
        category_tags = ["reddit"]
        sub = entry.get("subreddit", "").lower()
        if "machinelearning" in sub:
            category_tags.append("machine-learning")
        elif "artificial" in sub:
            category_tags.append("ai-general")
        elif "localllama" in sub:
            category_tags.append("local-llm")
        elif "startups" in sub:
            category_tags.append("startups")

        # Post type from title markers
        title = entry.get("title", "")
        if " [P]" in title or " [p]" in title:
            category_tags.append("project")
        elif " [R]" in title or " [r]" in title:
            category_tags.append("research")
        elif " [D]" in title or " [d]" in title:
            category_tags.append("discussion")
        elif " [N]" in title or " [n]" in title:
            category_tags.append("news")
        else:
            category_tags.append("general")

        # Clean title (remove [X] markers)
        clean_title = re.sub(r"\s*\[[A-Z]\]\s*$", "", title)

        raw_meta = {
            "subreddit": entry["subreddit"],
            "author": entry["author"],
            "published": entry["published"],
            "text_length": len(content_text),
        }

        source_id = post_id or entry["url"].split("/")[-1] or f"rss_{stored}"
        now = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")

        try:
            cursor.execute("""
                INSERT OR REPLACE INTO entries
                (source, source_id, url, title, extracted_text, summary,
                 category_tags, signal_score, raw_metadata, first_seen, last_updated)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            """, (
                "reddit", source_id, entry["url"], clean_title,
                content_text,
                None,  # summary — LLM later
                json.dumps(category_tags),
                score,
                json.dumps(raw_meta),
                now, now,
            ))
            stored += 1
        except Exception as e:
            print(f"  DB ERROR: {e}")

    conn.commit()
    print(f"  Stored {stored} entries")

    # Step 3: Summary
    print(f"\n[3/3] Summary")
    cursor.execute("SELECT COUNT(*) FROM entries")
    total = cursor.fetchone()[0]
    print(f"  Total entries in DB: {total}")
    cursor.execute("SELECT COUNT(*) FROM entries WHERE source='reddit'")
    reddit_count = cursor.fetchone()[0]
    print(f"  Reddit entries: {reddit_count}")
    cursor.execute("SELECT AVG(signal_score) FROM entries WHERE source='reddit'")
    avg_score = cursor.fetchone()[0] or 0
    print(f"  Avg signal score: {avg_score:.2f}")

    # Subreddit distribution
    cursor.execute("""
        SELECT raw_metadata, COUNT(*) FROM entries
        WHERE source='reddit'
        GROUP BY raw_metadata
        ORDER BY COUNT(*) DESC
    """)
    print(f"\n  Subreddit distribution:")
    for meta, cnt in cursor.fetchall():
        d = json.loads(meta)
        print(f"    r/{d.get('subreddit', '?')}: {cnt}")

    # Top 5
    print(f"\n  Top 5 by signal score:")
    cursor.execute("""
        SELECT id, title, signal_score, raw_metadata, category_tags,
               LENGTH(extracted_text) as text_len
        FROM entries WHERE source='reddit'
        ORDER BY signal_score DESC
        LIMIT 5
    """)
    for row in cursor.fetchall():
        eid, title, score, meta, tags, txt_len = row
        meta_dict = json.loads(meta) if meta else {}
        print(f"    [{eid}] score={score:.1f} text={txt_len}ch")
        print(f"        {title[:90]}")
        print(f"        r/{meta_dict.get('subreddit', '?')} "
              f"by {meta_dict.get('author', '?')}")

    # Extraction quality
    print(f"\n  Extraction quality (top entry):")
    cursor.execute("""
        SELECT title, extracted_text
        FROM entries WHERE source='reddit'
        ORDER BY signal_score DESC
        LIMIT 1
    """)
    row = cursor.fetchone()
    if row:
        title, excerpt = row
        print(f"    Title: {title[:80]}")
        print(f"    Length: {len(excerpt) if excerpt else 0} chars")
        if excerpt:
            print(f"    Preview:\n    {excerpt[:400]}...")
        else:
            print("    (empty)")

    # Check for garbled extractions
    cursor.execute("""
        SELECT COUNT(*) FROM entries
        WHERE source='reddit' AND LENGTH(extracted_text) < 100
    """)
    short_count = cursor.fetchone()[0]
    if short_count > 0:
        print(f"\n  ⚠ {short_count}/{stored} entries have very short extractions (<100 chars)")
        print("    These are likely link-only posts or external links")

    conn.close()
    print(f"\n  Database: {DB_PATH}")
    print("  Done.")


if __name__ == "__main__":
    main()
