"""Take screenshots of the demo Django app for documentation.

Starts the example Django dev server, logs in as superuser,
and captures screenshots of key pages using Playwright.

Usage:
    python scripts/take_screenshots.py
"""

import subprocess
import sys
import time
from pathlib import Path

from playwright.sync_api import Page, sync_playwright

PROJECT_ROOT = Path(__file__).resolve().parent.parent
EXAMPLES_DIR = PROJECT_ROOT / "examples" / "sample"
OUTPUT_DIR = PROJECT_ROOT / "docs" / "_content"
PORT = 8123
BASE_URL = f"http://127.0.0.1:{PORT}"
SUPERUSER = "admin"
PASSWORD = "admin"


def setup_database() -> None:
    """Run migrations and create superuser for the demo project."""
    env_vars = {
        "DJANGO_SETTINGS_MODULE": "settings",
        "PYTHONPATH": f"{EXAMPLES_DIR}:{PROJECT_ROOT}",
    }
    import os
    env = {**os.environ, **env_vars}

    subprocess.run(
        [sys.executable, "manage.py", "migrate", "--run-syncdb"],
        cwd=EXAMPLES_DIR, env=env, capture_output=True, check=True,
    )
    # Create superuser via shell command
    create_user_script = (
        "from django.contrib.auth import get_user_model; "
        "User = get_user_model(); "
        f"User.objects.filter(username='{SUPERUSER}').exists() or "
        f"User.objects.create_superuser('{SUPERUSER}', '', '{PASSWORD}')"
    )
    subprocess.run(
        [sys.executable, "manage.py", "shell", "-c", create_user_script],
        cwd=EXAMPLES_DIR, env=env, capture_output=True, check=True,
    )


def start_server() -> subprocess.Popen:
    """Start Django dev server as a subprocess."""
    import os
    env = {
        **os.environ,
        "DJANGO_SETTINGS_MODULE": "settings",
        "PYTHONPATH": f"{EXAMPLES_DIR}:{PROJECT_ROOT}",
    }
    proc = subprocess.Popen(
        [sys.executable, "manage.py", "runserver", str(PORT), "--noreload"],
        cwd=EXAMPLES_DIR, env=env,
        stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
    )
    # Wait for server to be ready
    for _ in range(30):
        try:
            import urllib.request
            urllib.request.urlopen(f"{BASE_URL}/admin/login/", timeout=1)
            break
        except Exception:
            time.sleep(0.5)
    else:
        proc.kill()
        raise RuntimeError("Django dev server failed to start")
    return proc


def screenshot_content(page: Page, filename: str) -> None:
    """Take a cropped screenshot using clip to cut off empty whitespace below content."""
    width = page.viewport_size["width"]
    # Shrink viewport to 1px so vh-based min-heights collapse
    page.set_viewport_size({"width": width, "height": 1})
    content_height = page.evaluate("() => document.documentElement.scrollHeight")
    page.set_viewport_size({"width": width, "height": content_height})
    page.screenshot(path=str(OUTPUT_DIR / filename))
    # Restore viewport for next screenshot
    page.set_viewport_size({"width": width, "height": 900})
    print(f"  {filename}")


def take_screenshots() -> None:
    """Capture all documentation screenshots."""
    OUTPUT_DIR.mkdir(parents=True, exist_ok=True)

    with sync_playwright() as p:
        browser = p.chromium.launch()
        page = browser.new_page(viewport={"width": 1280, "height": 900})

        # Login
        page.goto(f"{BASE_URL}/admin/login/")
        page.fill("#id_username", SUPERUSER)
        page.fill("#id_password", PASSWORD)
        page.click('input[type="submit"]')
        page.wait_for_url(f"{BASE_URL}/admin/")

        # 1. Command list (regular viewport screenshot, not cropped)
        page.goto(f"{BASE_URL}/admin/commands/")
        page.wait_for_load_state("networkidle")
        page.screenshot(path=str(OUTPUT_DIR / "command-list.png"))
        print("  command-list.png")

        # 2. Text args form
        page.goto(f"{BASE_URL}/admin/commands/text_args/")
        page.wait_for_load_state("networkidle")
        screenshot_content(page, "command-form-text.png")

        # 3. Choice args form
        page.goto(f"{BASE_URL}/admin/commands/choice_args/")
        page.wait_for_load_state("networkidle")
        screenshot_content(page, "command-form-choices.png")

        # 4. Boolean args form
        page.goto(f"{BASE_URL}/admin/commands/boolean_args/")
        page.wait_for_load_state("networkidle")
        screenshot_content(page, "command-form-boolean.png")

        # 5. Path args form
        page.goto(f"{BASE_URL}/admin/commands/path_args/")
        page.wait_for_load_state("networkidle")
        screenshot_content(page, "command-form-path.png")

        # 6. Command result — fill and submit text_args form
        page.goto(f"{BASE_URL}/admin/commands/text_args/")
        page.wait_for_load_state("networkidle")
        page.fill('input[name="name"]', "World")
        page.fill('input[name="greeting"]', "Hello")
        page.fill('input[name="title"]', "Dr")
        page.fill('input[name="tags"]', "python django admin")
        page.fill('input[name="extras"]', "first second third")
        page.click('input[type="submit"]')
        page.wait_for_load_state("networkidle")
        screenshot_content(page, "command-result.png")

        # 7. Path form — text input mode (click "or enter path as text")
        page.goto(f"{BASE_URL}/admin/commands/path_args/")
        page.wait_for_load_state("networkidle")
        # Switch "Output file" to text mode (second toggle link)
        page.locator('a[data-toggle-to="text"]').nth(1).click()
        screenshot_content(page, "command-form-path-text.png")

        # 8. File upload result — upload a sample file to path_args
        page.goto(f"{BASE_URL}/admin/commands/path_args/")
        page.wait_for_load_state("networkidle")
        # Create a temp file to upload
        sample_file = OUTPUT_DIR / "_sample_upload.txt"
        sample_file.write_text("Hello from uploaded file!\nThis is a demo.")
        file_input = page.locator('input[type="file"]').first
        file_input.set_input_files(str(sample_file))
        # Switch "Output file" to text mode and fill it
        page.locator('a[data-toggle-to="text"]').nth(1).click()
        page.locator('.path-text-input').nth(1).fill("/tmp/result.txt")
        page.click('input[type="submit"]')
        page.wait_for_load_state("networkidle")
        # Re-fill fields on the result page so both form and output are visible
        file_input2 = page.locator('input[type="file"]').first
        file_input2.set_input_files(str(sample_file))
        page.locator('a[data-toggle-to="text"]').nth(1).click()
        page.locator('.path-text-input').nth(1).fill("/tmp/result.txt")
        screenshot_content(page, "command-result-file.png")
        sample_file.unlink(missing_ok=True)

        # 9. Admin app list — go to admin index and screenshot the app list
        page.goto(f"{BASE_URL}/admin/")
        page.wait_for_load_state("networkidle")
        app_list = page.locator("#content-main")
        if app_list.count() > 0:
            app_list.first.screenshot(path=str(OUTPUT_DIR / "admin-app-list.png"))
        else:
            screenshot_content(page, "admin-app-list.png")
        print("  admin-app-list.png")

        browser.close()


def main() -> None:
    print("Setting up database...")
    setup_database()

    print("Starting Django dev server...")
    server = start_server()

    try:
        print("Taking screenshots...")
        take_screenshots()
        print(f"\nDone! Screenshots saved to {OUTPUT_DIR}/")
    finally:
        server.terminate()
        server.wait(timeout=5)


if __name__ == "__main__":
    main()
