import asyncio
import os
import sys
import time
from pathlib import Path

from playwright.async_api import async_playwright  # type: ignore

HERE = Path(__file__).parent
PROJECT_ROOT = HERE.parent


# Ensure Playwright browsers are installed
def install_playwright_browsers():
    print("Installing Playwright browsers...")
    try:
        # Simulate the `playwright install` command
        os.system(f"{sys.executable} -m playwright install chromium")
        print("Playwright browsers installed successfully.")
    except Exception as e:
        print(f"Failed to install Playwright browsers: {e}", file=sys.stderr)
        sys.exit(1)


# Start an HTTP server on the dynamic port
def start_http_server(port: int, directory: Path):
    from fastled import Test  # type: ignore

    server_process = Test.spawn_http_server(
        directory=directory, port=port, open_browser=False
    )
    return server_process


async def main() -> None:
    install_playwright_browsers()
    # Find an available port
    port = (
        8080  # Todo, figure out why the http server ignores any port other than 8080.
    )
    print(f"Using port: {port}")

    # Start the HTTP server
    os.chdir(str(PROJECT_ROOT))
    directory = Path("examples/wasm/fastled_js")
    server_process = start_http_server(port=port, directory=directory)

    try:
        # Give the server some time to start
        time.sleep(2)

        # Use Playwright to test the server
        async with async_playwright() as p:
            browser = await p.chromium.launch()
            page = await browser.new_page()

            try:
                await page.goto(f"http://localhost:{port}", timeout=30000)

                # Listen for console messages
                def console_log_handler(msg):
                    if "INVALID_OPERATION" in msg.text:
                        print(
                            "INVALID_OPERATION detected in console log", file=sys.stderr
                        )
                        raise Exception("INVALID_OPERATION detected in console log")

                page.on("console", console_log_handler)

                # Evaluate and monitor window.frameCallCount
                await page.evaluate(
                    """
                    window.frameCallCount = 0;
                    globalThis.FastLED_onFrame = (jsonStr) => {
                        console.log('FastLED_onFrame called with:', jsonStr);
                        window.frameCallCount++;
                    };
                """
                )
                await page.wait_for_timeout(5000)

                call_count = await page.evaluate("window.frameCallCount")
                if call_count > 0:
                    print(
                        f"Success: FastLED.js was initialized and FastLED_onFrame was called {call_count} times"
                    )
                else:
                    print(
                        "Error: FastLED.js had something go wrong and FastLED_onFrame was not called within 5 seconds",
                        file=sys.stderr,
                    )
                    raise Exception("FastLED.js failed to initialize")

            except Exception as e:
                print(f"An error occurred: {e}", file=sys.stderr)
                raise Exception(f"An error occurred: {e}") from e

            finally:
                await browser.close()

    finally:
        # Terminate the server process
        server_process.terminate()


# Run the main function
if __name__ == "__main__":
    sys.exit(asyncio.run(main()))
