from __future__ import annotations

import json
import socket
import webbrowser
from functools import partial
from http.server import HTTPServer, SimpleHTTPRequestHandler
from pathlib import Path
from tempfile import TemporaryDirectory

from fastelt.app import FastELT

_VIEWER_HTML = Path(__file__).parent / "viewer.html"


def generate_schema(app: FastELT, path: Path) -> None:
    """Write fastelt.json schema file."""
    path.write_text(json.dumps(app.schema(), indent=2))


def generate_viewer(app: FastELT, path: Path) -> None:
    """Generate a self-contained HTML viewer with the schema embedded."""
    schema_json = json.dumps(app.schema())
    html = _VIEWER_HTML.read_text()
    script_tag = f'<script id="__FASTELT_SCHEMA__" type="application/json">{schema_json}</script>'
    html = html.replace("</head>", f"{script_tag}\n</head>")
    path.write_text(html)


class _ReusableHTTPServer(HTTPServer):
    allow_reuse_address = True
    allow_reuse_port = True


def serve_viewer(
    app: FastELT,
    host: str = "localhost",
    port: int = 8000,
    open_browser: bool = False,
) -> None:
    """Generate docs and serve via built-in HTTP server."""
    with TemporaryDirectory(prefix="fastelt-docs-") as tmpdir:
        tmp = Path(tmpdir)
        generate_schema(app, tmp / "fastelt.json")

        html = _VIEWER_HTML.read_text()
        (tmp / "index.html").write_text(html)

        handler = partial(SimpleHTTPRequestHandler, directory=tmpdir)
        server = _ReusableHTTPServer((host, port), handler)

        url = f"http://{host}:{port}"
        print(f"Serving FastELT docs at {url}")
        print("Press Ctrl+C to stop.")

        if open_browser:
            webbrowser.open(url)

        try:
            server.serve_forever()
        except KeyboardInterrupt:
            print("\nStopped.")
            server.server_close()
