#!/usr/bin/env python3
"""Test ALL web UI routes and report any returning 500 errors.

Runs against the Flask test client with dev=True so admin routes are accessible.
Queries SQLite DB for real IDs needed by dynamic routes.
"""
import os
import sys
import sqlite3
import traceback

# Must run from src/ directory
src_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'src')
sys.path.insert(0, src_dir)

DB_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'data', 'drafts.db')


def get_test_ids():
    """Query the database for real IDs to use in dynamic routes."""
    conn = sqlite3.connect(DB_PATH)
    conn.row_factory = sqlite3.Row

    ids = {}

    # Get a draft name
    row = conn.execute("SELECT name FROM drafts LIMIT 1").fetchone()
    ids["draft_name"] = row["name"] if row else "draft-nonexistent"

    # Get a person_id from authors
    row = conn.execute("SELECT person_id FROM authors WHERE person_id IS NOT NULL LIMIT 1").fetchone()
    ids["person_id"] = row["person_id"] if row else 1

    # Get a gap_id
    row = conn.execute("SELECT id FROM gaps LIMIT 1").fetchone()
    ids["gap_id"] = row["id"] if row else 1

    # Get an idea_id
    row = conn.execute("SELECT id FROM ideas LIMIT 1").fetchone()
    ids["idea_id"] = row["id"] if row else 1

    # Get a proposal_id (may not exist)
    try:
        row = conn.execute("SELECT id FROM proposals LIMIT 1").fetchone()
        ids["proposal_id"] = row["id"] if row else None
    except Exception:
        ids["proposal_id"] = None

    # Get a blog_draft_id (may not exist)
    try:
        row = conn.execute("SELECT id FROM blog_drafts LIMIT 1").fetchone()
        ids["blog_draft_id"] = row["id"] if row else None
    except Exception:
        ids["blog_draft_id"] = None

    # Get two draft names for compare
    rows = conn.execute("SELECT name FROM drafts LIMIT 2").fetchall()
    ids["two_drafts"] = ",".join(r["name"] for r in rows) if len(rows) >= 2 else ""

    conn.close()
    return ids


def main():
    ids = get_test_ids()
    print(f"Test IDs: draft={ids['draft_name']}, person={ids['person_id']}, "
          f"gap={ids['gap_id']}, idea={ids['idea_id']}, "
          f"proposal={ids['proposal_id']}, blog={ids['blog_draft_id']}")
    print()

    from webui.app import create_app
    app = create_app(dev=True)
    client = app.test_client()

    # Define all routes to test: (method, url, description)
    routes = [
        # === Pages (public) ===
        ("GET", "/", "overview"),
        ("GET", "/drafts", "drafts list"),
        ("GET", f"/drafts/{ids['draft_name']}", "draft detail"),
        ("GET", "/ideas", "ideas"),
        ("GET", "/ratings", "ratings"),
        ("GET", "/timeline", "timeline"),
        ("GET", "/idea-clusters", "idea clusters"),
        ("GET", "/architecture", "architecture"),
        ("GET", f"/authors/{ids['person_id']}", "author detail"),
        ("GET", "/authors", "authors"),
        ("GET", "/citations", "citations"),
        ("GET", "/about", "about"),
        ("GET", "/impressum", "impressum"),
        ("GET", "/datenschutz", "datenschutz"),
        ("GET", "/search", "search (empty)"),
        ("GET", "/search?q=agent", "search (query)"),
        ("GET", "/ask", "ask (empty)"),

        # === API (public) ===
        ("GET", "/api/drafts", "api drafts"),
        ("GET", "/api/stats", "api stats"),
        ("GET", "/api/authors/network", "api author network"),
        ("GET", "/api/citations", "api citations"),
        ("GET", "/api/search?q=agent", "api search"),
        ("GET", "/api/ideas", "api ideas"),
        ("GET", "/api/ratings", "api ratings"),
        ("GET", "/api/timeline", "api timeline"),
        ("GET", "/api/idea-clusters", "api idea clusters"),
        ("GET", "/api/categories", "api categories"),
        ("GET", f"/api/drafts/{ids['draft_name']}", "api draft detail"),
        ("GET", "/api/architecture", "api architecture"),

        # === Admin pages ===
        ("GET", "/gaps", "gaps"),
        ("GET", "/gaps/demo", "gaps demo"),
        ("GET", f"/gaps/{ids['gap_id']}", "gap detail"),
        ("GET", "/api/gaps", "api gaps"),
        ("GET", f"/api/gaps/{ids['gap_id']}", "api gap detail"),
        ("GET", "/monitor", "monitor"),
        ("GET", "/api/monitor", "api monitor"),
        ("GET", "/admin/analytics", "analytics"),
        ("GET", "/landscape", "landscape"),
        ("GET", "/api/landscape", "api landscape"),
        ("GET", "/similarity", "similarity"),
        ("GET", "/api/similarity", "api similarity"),
        ("GET", "/compare", "compare (empty)"),
        ("GET", f"/compare?drafts={ids['two_drafts']}", "compare (with drafts)"),
        ("GET", "/sources", "sources"),
        ("GET", "/false-positives", "false positives"),
        ("GET", "/api/sources", "api sources"),
        ("GET", "/api/false-positives", "api false positives"),
        ("GET", "/api/citations/influence", "api citation influence"),
        ("GET", "/api/citations/bcp", "api bcp analysis"),
        ("GET", "/idea-analysis", "idea analysis"),
        ("GET", "/api/idea-analysis", "api idea analysis"),
        ("GET", f"/ideas/{ids['idea_id']}", "idea detail"),
        ("GET", "/trends", "trends"),
        ("GET", "/complexity", "complexity"),
        ("GET", "/api/trends", "api trends"),
        ("GET", "/api/complexity", "api complexity"),
        ("GET", "/proposals", "proposals"),
        ("GET", "/proposals/new", "proposal new (GET)"),
        ("GET", "/api/proposals", "api proposals"),
        ("GET", "/proposals/intake", "proposal intake (GET)"),
        ("GET", "/blog", "blog drafts"),
        ("GET", "/blog/generate", "blog generate (GET)"),
        ("GET", "/export/obsidian", "obsidian export"),
    ]

    # Add conditional routes that need existing records
    if ids["proposal_id"]:
        routes.extend([
            ("GET", f"/proposals/{ids['proposal_id']}", "proposal detail"),
            ("GET", f"/proposals/{ids['proposal_id']}/edit", "proposal edit (GET)"),
            ("GET", f"/api/proposals/{ids['proposal_id']}", "api proposal detail"),
        ])

    if ids["blog_draft_id"]:
        routes.extend([
            ("GET", f"/blog/{ids['blog_draft_id']}", "blog detail"),
            ("GET", f"/blog/{ids['blog_draft_id']}/edit", "blog edit (GET)"),
            ("GET", f"/blog/{ids['blog_draft_id']}/export", "blog export"),
        ])

    # Run tests
    results = {"ok": [], "error_500": [], "error_other": [], "exception": []}

    for method, url, desc in routes:
        try:
            if method == "GET":
                resp = client.get(url)
            elif method == "POST":
                resp = client.post(url, json={})
            else:
                continue

            status = resp.status_code
            if status == 500:
                # Try to extract error from response
                error_text = resp.data.decode("utf-8", errors="replace")[:500]
                results["error_500"].append((desc, url, status, error_text))
                print(f"  FAIL 500  {desc:30s}  {url}")
            elif status >= 400:
                results["error_other"].append((desc, url, status))
                print(f"  WARN {status}  {desc:30s}  {url}")
            else:
                results["ok"].append((desc, url, status))
                print(f"  OK   {status}  {desc:30s}  {url}")
        except Exception as e:
            tb = traceback.format_exc()
            results["exception"].append((desc, url, str(e), tb))
            print(f"  EXCP      {desc:30s}  {url}  -> {e}")

    # Summary
    print("\n" + "=" * 70)
    print(f"SUMMARY: {len(results['ok'])} OK, {len(results['error_500'])} x 500, "
          f"{len(results['error_other'])} x 4xx, {len(results['exception'])} exceptions")
    print("=" * 70)

    if results["error_500"]:
        print("\n--- 500 ERRORS (BROKEN ROUTES) ---")
        for desc, url, status, error_text in results["error_500"]:
            print(f"\n  Route: {desc}")
            print(f"  URL:   {url}")
            print(f"  Error preview:")
            # Show just enough of the error
            for line in error_text.split("\n")[:10]:
                print(f"    {line}")

    if results["exception"]:
        print("\n--- EXCEPTIONS (APP CRASHED) ---")
        for desc, url, err, tb in results["exception"]:
            print(f"\n  Route: {desc}")
            print(f"  URL:   {url}")
            print(f"  Exception: {err}")
            # Show last few lines of traceback
            tb_lines = tb.strip().split("\n")
            for line in tb_lines[-5:]:
                print(f"    {line}")

    if results["error_other"]:
        print("\n--- 4xx RESPONSES (may be expected) ---")
        for desc, url, status in results["error_other"]:
            print(f"  {status}  {desc:30s}  {url}")


if __name__ == "__main__":
    main()
