#!/usr/bin/env python3
"""
Watchlists build script.

For each *-watchlist.md in this folder:
  - Parse title, optional first-load lightbox, and playlist entries
  - Generate a self-contained HTML page

Then update watchlists-hub.html subtitle with current totals.

Output filenames: strip '-watchlist' suffix, lowercase the stem, no hyphens/spaces.
  ContentAddictionArchive-watchlist.md  →  contentaddictionarchive.html
  AnalogFrontier-watchlist.md           →  analogfrontier.html
  etc.

Run after adding or editing any *-watchlist.md file.
"""

import re
from pathlib import Path
from html import escape

HERE = Path(__file__).parent
HUB  = HERE / "watchlists-hub.html"

COLORS = ["teal", "green", "toucan"]   # rotation order

ALLOW = (
    "accelerometer; autoplay; clipboard-write; "
    "encrypted-media; gyroscope; picture-in-picture; web-share"
)

# ── MD parsing ────────────────────────────────────────────────────────────────

def slug_from_path(path: Path) -> str:
    stem = path.stem                         # e.g. "AnalogFrontier-watchlist"
    stem = re.sub(r'-watchlist$', '', stem, flags=re.IGNORECASE)
    return stem.lower().replace('-', '').replace('_', '').replace(' ', '')


def parse_md(path: Path) -> dict:
    text = path.read_text(encoding='utf-8')

    # Title: first # heading
    m = re.search(r'^#\s+(.+)$', text, re.MULTILINE)
    title = m.group(1).strip() if m else path.stem

    # Optional lightbox: >>on-first-load - lightbox - "text"
    m = re.search(r'>>on-first-load\s+-\s+lightbox\s+-\s+"([^"]+)"', text)
    lightbox = m.group(1).strip() if m else None

    # Playlist entries
    # - **Name \- YouTube**
    #   - URL: https://www.youtube.com/playlist?list=PLxxxxxx
    playlists = []
    for m in re.finditer(
        r'-\s+\*\*(.+?)\s*\\-\s*YouTube\*\*\s*\n\s+-\s+URL:\s+(https://[^\s]+)',
        text
    ):
        name = m.group(1).strip()
        url  = m.group(2).strip()
        lid  = re.search(r'[?&]list=([A-Za-z0-9_-]+)', url)
        if lid:
            playlists.append({'name': name, 'list_id': lid.group(1)})

    return {'title': title, 'lightbox': lightbox, 'playlists': playlists}


# ── HTML generation ───────────────────────────────────────────────────────────

def build_lightbox_html(text: str, slug: str) -> tuple[str, str]:
    """Return (lightbox_div_html, lightbox_js_html). Empty strings if no lightbox."""
    if not text:
        return '', ''

    safe = escape(text)
    div = f"""
    <div id="lightbox" role="dialog" aria-modal="true" aria-label="Introduction">
        <div class="caption-box">
            <button class="caption-close" id="caption-close" aria-label="Close">×</button>
            <p class="caption-text">{safe}</p>
            <p class="dismiss-hint">CLICK ANYWHERE TO DISMISS</p>
        </div>
    </div>"""

    js = f"""
            const lightbox = document.getElementById('lightbox');
            lightbox.style.display = 'flex';

            function closeLightbox() {{ lightbox.style.display = 'none'; }}

            lightbox.addEventListener('click', (e) => {{
                if (e.target === lightbox) closeLightbox();
            }});
            document.getElementById('caption-close').addEventListener('click', closeLightbox);
            document.addEventListener('keydown', (e) => {{
                if (e.key === 'Escape') closeLightbox();
            }});
"""
    return div, js


def build_panels_html(playlists: list) -> str:
    panels = []
    for i, pl in enumerate(playlists):
        color     = COLORS[i % len(COLORS)]
        num       = f"PANEL {i+1:02d}"
        embed_url = f"https://www.youtube.com/embed/videoseries?list={pl['list_id']}"
        title_esc = escape(pl['name'].upper())

        playlist_url = f"https://www.youtube.com/playlist?list={pl['list_id']}"

        panels.append(f"""
        <section class="playlist-panel panel-{color}">
            <div class="panel-header">
                <h2>{title_esc}</h2>
                <span class="panel-number">{num}</span>
            </div>
            <div class="video-container">
                <iframe
                    data-src="{embed_url}"
                    allow="{ALLOW}"
                    allowfullscreen>
                </iframe>
            </div>
            <a href="{playlist_url}" target="_blank" rel="noopener" class="playlist-link">
                → OPEN FULL PLAYLIST ON YOUTUBE
            </a>
        </section>""")

    return '\n'.join(panels)


def build_stagger_css(count: int) -> str:
    lines = []
    for i in range(1, count + 1):
        delay = (i - 1) * 60
        lines.append(
            f"        .playlist-panel:nth-child({i}) {{ animation-delay: {delay}ms; }}"
        )
    return '\n'.join(lines)


def generate_html(data: dict, slug: str) -> str:
    title        = data['title']
    playlists    = data['playlists']
    count        = len(playlists)
    title_upper  = title.upper()
    count_label  = f"{count} PLAYLIST{'S' if count != 1 else ''}"

    lightbox_div, lightbox_js = build_lightbox_html(data['lightbox'], slug)
    panels_html  = build_panels_html(playlists)
    stagger_css  = build_stagger_css(count)

    # Lightbox CSS block (only if there's a lightbox)
    lightbox_css = """
        /* ── Lightbox ── */
        #lightbox {
            position: fixed;
            inset: 0;
            background: rgba(4, 6, 11, 0.92);
            display: none;
            justify-content: center;
            align-items: center;
            z-index: 2000;
            padding: 2rem;
            cursor: pointer;
        }

        .caption-box {
            background: #080d10;
            border: 2px solid var(--wl-teal);
            border-top: 10px solid var(--wl-toucan);
            border-left: 6px solid var(--wl-green);
            max-width: 640px;
            width: 100%;
            max-height: 90vh;
            overflow-y: auto;
            padding: 2rem 2rem 1.5rem;
            position: relative;
            cursor: default;
        }

        .caption-close {
            position: absolute;
            top: 0.6rem;
            right: 0.75rem;
            background: none;
            border: none;
            color: var(--wl-teal);
            font-family: 'Rambla', sans-serif;
            font-size: 1.6rem;
            font-weight: 700;
            line-height: 1;
            cursor: pointer;
            padding: 0.1rem 0.3rem;
            transition: color 100ms ease;
        }

        .caption-close:hover { color: var(--wl-toucan); }

        .caption-text {
            font-style: italic;
            font-size: 1.05rem;
            color: var(--text-warm);
            margin-bottom: 1.25rem;
            line-height: 1.65;
            padding-right: 1.5rem;
        }

        .dismiss-hint {
            font-weight: 700;
            text-transform: uppercase;
            font-size: 0.62rem;
            letter-spacing: 0.18em;
            color: var(--muted);
            text-align: center;
            margin-top: 1.25rem;
        }
""" if data['lightbox'] else ''

    return f"""<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{escape(title_upper)} | WATCHLISTS</title>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Rambla:ital,wght@0,400;0,700;1,400;1,700&display=swap" rel="stylesheet">
    <style>
        :root {{
            --bg-void:        #04060b;
            --text-warm:      #e8d5b8;
            --wl-teal:        #2ac4b3;
            --wl-green:       #32dc8c;
            --wl-toucan:      #ffcf40;
            --wl-teal-glow:   rgba(42, 196, 179, 0.22);
            --wl-green-glow:  rgba(50, 220, 140, 0.22);
            --wl-toucan-glow: rgba(255, 207, 64, 0.22);
            --muted:          rgba(232, 213, 184, 0.45);
        }}

        * {{ box-sizing: border-box; margin: 0; padding: 0; border-radius: 0; }}

        body {{
            background-color: var(--bg-void);
            color: var(--text-warm);
            font-family: 'Rambla', sans-serif;
            line-height: 1.5;
            padding-top: 88px;
        }}

        /* ── Sticky header ── */
        .sticky-header {{
            position: fixed;
            top: 0; left: 0; right: 0;
            height: 72px;
            background: var(--bg-void);
            border-bottom: 2px solid var(--wl-teal);
            display: flex;
            align-items: center;
            justify-content: space-between;
            padding: 0 2rem;
            z-index: 1000;
        }}

        .header-title {{
            font-weight: 700;
            text-transform: uppercase;
            color: var(--wl-toucan);
            font-size: 1.1rem;
            letter-spacing: -0.01em;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            max-width: 55%;
        }}

        .header-nav {{
            display: flex;
            align-items: center;
            gap: 2rem;
        }}

        .nav-link {{
            font-weight: 700;
            text-transform: uppercase;
            text-decoration: none;
            color: var(--wl-teal);
            font-size: 0.85rem;
            letter-spacing: 0.04em;
            transition: color 100ms ease;
        }}

        .nav-link:hover {{ color: var(--wl-green); }}

        .header-count {{
            font-weight: 700;
            text-transform: uppercase;
            color: var(--wl-green);
            font-size: 0.78rem;
            letter-spacing: 0.1em;
        }}

        .menu-toggle {{
            display: none;
            background: none;
            border: 2px solid var(--wl-teal);
            color: var(--wl-teal);
            padding: 0.4rem 0.6rem;
            font-size: 1.1rem;
            cursor: pointer;
            font-family: inherit;
            transition: color 100ms ease, border-color 100ms ease;
        }}

        .menu-toggle:hover {{ color: var(--wl-green); border-color: var(--wl-green); }}

        @media (max-width: 600px) {{
            .header-nav {{
                display: none;
                flex-direction: column;
                align-items: flex-start;
                position: absolute;
                top: 72px; left: 0; right: 0;
                background: var(--bg-void);
                padding: 1.25rem 2rem;
                border-bottom: 2px solid var(--wl-teal);
                gap: 0.75rem;
            }}
            .header-nav.open {{ display: flex; }}
            .menu-toggle {{ display: block; }}
            .header-title {{ max-width: 65%; }}
        }}
{lightbox_css}
        /* ── Panels ── */
        .container {{
            max-width: 900px;
            margin: 0 auto;
            padding: 2rem 2rem 4rem;
        }}

        @media (max-width: 600px) {{
            .container {{ padding: 1.5rem 1.25rem 3rem; }}
        }}

        @keyframes panelIn {{
            from {{ opacity: 0; transform: translateY(20px); }}
            to   {{ opacity: 1; transform: translateY(0); }}
        }}

        .playlist-panel {{
            margin-bottom: 3.5rem;
            border: 2px solid var(--border-color);
            background: var(--bg-void);
            position: relative;
            box-shadow: 0 2px 6px rgba(0, 0, 0, 0.6);
            animation: panelIn 350ms ease both;
        }}

{stagger_css}

        .panel-header {{
            background: var(--border-color);
            padding: 0.75rem 1.25rem;
            color: var(--bg-void);
            display: flex;
            justify-content: space-between;
            align-items: center;
        }}

        .panel-header h2 {{
            font-size: 1.15rem;
            font-weight: 700;
            text-transform: uppercase;
            margin: 0;
            line-height: 1.2;
        }}

        .panel-number {{
            font-size: 0.75rem;
            font-weight: 700;
            text-transform: uppercase;
            color: rgba(4, 6, 11, 0.75);
            letter-spacing: 0.06em;
            white-space: nowrap;
            margin-left: 1rem;
            flex-shrink: 0;
        }}

        .video-container {{
            position: relative;
            padding-bottom: 56.25%;
            height: 0;
            overflow: hidden;
        }}

        .video-container iframe {{
            position: absolute;
            top: 0; left: 0;
            width: 100%; height: 100%;
            border: 0;
        }}

        .panel-teal   {{ --border-color: var(--wl-teal); }}
        .panel-green  {{ --border-color: var(--wl-green); }}
        .panel-toucan {{ --border-color: var(--wl-toucan); }}

        .playlist-link {{
            display: block;
            padding: 0.85rem 1.25rem;
            font-weight: 700;
            text-transform: uppercase;
            font-size: 0.9rem;
            letter-spacing: 0.08em;
            color: var(--border-color);
            text-decoration: none;
            border-top: 1px solid var(--border-color);
            transition: background 100ms ease, color 100ms ease;
        }}

        .playlist-link:hover {{
            background: var(--border-color);
            color: var(--bg-void);
        }}
    </style>
</head>
<body>

    <header class="sticky-header">
        <div class="header-title">{escape(title_upper)}</div>
        <button class="menu-toggle" id="menu-toggle">☰</button>
        <nav class="header-nav" id="header-nav">
            <a href="watchlists-hub.html" class="nav-link">← WATCHLISTS</a>
            <span class="header-count">{count_label}</span>
        </nav>
    </header>
{lightbox_div}
    <main class="container">
{panels_html}
    </main>

    <script>
        document.addEventListener('DOMContentLoaded', () => {{
{lightbox_js}
            // Mobile nav toggle
            const menuToggle = document.getElementById('menu-toggle');
            const headerNav  = document.getElementById('header-nav');

            menuToggle.addEventListener('click', (e) => {{
                e.stopPropagation();
                headerNav.classList.toggle('open');
            }});

            document.addEventListener('click', (e) => {{
                if (!headerNav.contains(e.target) && e.target !== menuToggle) {{
                    headerNav.classList.remove('open');
                }}
            }});

            // Lazy-load iframes via IntersectionObserver
            const observer = new IntersectionObserver((entries, obs) => {{
                entries.forEach(entry => {{
                    if (entry.isIntersecting) {{
                        const iframe = entry.target;
                        const src = iframe.getAttribute('data-src');
                        if (src) {{
                            iframe.setAttribute('src', src);
                            iframe.removeAttribute('data-src');
                        }}
                        obs.unobserve(iframe);
                    }}
                }});
            }}, {{ rootMargin: '200px 0px' }});

            document.querySelectorAll('iframe[data-src]').forEach(
                iframe => observer.observe(iframe)
            );
        }});
    </script>

</body>
</html>
"""


# ── Hub subtitle update ───────────────────────────────────────────────────────

def update_hub_subtitle(collection_count: int, playlist_total: int):
    hub_text = HUB.read_text(encoding='utf-8')
    subtitle = (
        f'<div class="subtitle">'
        f'{collection_count} COLLECTION{"S" if collection_count != 1 else ""}'
        f' · CURATED VIDEO ARCHIVES'
        f' · {playlist_total} PLAYLIST{"S" if playlist_total != 1 else ""}'
        f'</div>'
    )
    hub_text = re.sub(
        r'<!-- SUBTITLE-START -->.*?<!-- SUBTITLE-END -->',
        f'<!-- SUBTITLE-START -->{subtitle}<!-- SUBTITLE-END -->',
        hub_text,
        flags=re.DOTALL
    )
    HUB.write_text(hub_text, encoding='utf-8')


# ── Main ──────────────────────────────────────────────────────────────────────

def main():
    md_files = sorted(HERE.glob('*-watchlist.md'))
    if not md_files:
        print("No *-watchlist.md files found.")
        return

    total_playlists = 0

    for md_path in md_files:
        slug = slug_from_path(md_path)
        out  = HERE / f"{slug}.html"

        data = parse_md(md_path)
        count = len(data['playlists'])

        if count == 0:
            print(f"  SKIP  {md_path.name} — no playlists found")
            continue

        html = generate_html(data, slug)
        out.write_text(html, encoding='utf-8')
        total_playlists += count
        print(f"  BUILD {out.name} — {data['title']} ({count} playlists)")

    update_hub_subtitle(len(md_files), total_playlists)
    print(f"\nUpdated hub subtitle — {len(md_files)} collections, {total_playlists} playlists total")


if __name__ == '__main__':
    main()
