"""
Local development server — serves the rendered topic page and opens the browser.
Also serves the interactive playground.
"""

import json
import os
import threading
import webbrowser

from flask import Flask, render_template, request, jsonify

from .registry import get_topic, list_topics

_DIR = os.path.dirname(os.path.abspath(__file__))


def _make_app(template_folder=None, static_folder=None):
    """Create a Flask app with common config."""
    return Flask(
        __name__,
        template_folder=template_folder or os.path.join(_DIR, "templates"),
        static_folder=static_folder or os.path.join(_DIR, "static"),
    )


def _suppress_flask_noise():
    """Suppress Flask development warnings and request logs."""
    import logging
    import flask.cli
    logging.getLogger("werkzeug").setLevel(logging.ERROR)
    flask.cli.show_server_banner = lambda *args: None


def start(topic: str, port: int = 5556):
    """
    Render the requested topic and serve it on localhost.

    Parameters
    ----------
    topic : str
        Name of the ML/DL topic (e.g. "linear regression").
    port : int
        Port number for the local server. Default 5556.
    """
    # Resolve topic
    module = get_topic(topic)
    content = module.get_content()

    # Build Flask app
    app = _make_app()

    @app.route("/")
    def index():
        return render_template(
            "topic.html",
            topic=content,
            all_topics=list_topics(),
        )

    @app.route("/shutdown", methods=["POST"])
    def shutdown():
        func = request.environ.get("werkzeug.server.shutdown")
        if func:
            func()
        return "Server shutting down..."

    # Open browser after a short delay
    url = f"http://localhost:{port}"
    threading.Timer(1.2, lambda: webbrowser.open(url)).start()

    _suppress_flask_noise()

    print(f"\n  ✦ VexRay is running at {url}")
    print(f"  ✦ Topic: {content['title']}")
    print(f"  ✦ Press Ctrl+C to stop\n")

    app.run(host="127.0.0.1", port=port, debug=False)


def start_playground(algorithm: str, port: int = 5556):
    """
    Launch the interactive playground for a specific ML algorithm.

    Parameters
    ----------
    algorithm : str
        Name of the ML algorithm (e.g. "linear regression", "knn").
    port : int
        Port number for the local server. Default 5556.
    """
    from .playgrounds import get_playground

    pg_module = get_playground(algorithm)
    meta = pg_module.META
    params = pg_module.PARAMS

    # Compute initial graph with default params
    defaults = {p["name"]: p["default"] for p in params}
    initial_graph = pg_module.compute(defaults)

    app = _make_app()

    @app.route("/")
    def index():
        return render_template(
            "playground.html",
            meta=meta,
            params=params,
            defaults_json=json.dumps(defaults),
            initial_graph_json=json.dumps(initial_graph),
        )

    @app.route("/api/compute", methods=["POST"])
    def compute():
        user_params = request.get_json(force=True)
        try:
            result = pg_module.compute(user_params)
            return jsonify(result)
        except Exception as e:
            return jsonify({"error": str(e)}), 500

    # Open browser
    url = f"http://localhost:{port}"
    threading.Timer(1.2, lambda: webbrowser.open(url)).start()

    _suppress_flask_noise()

    print(f"\n  ✦ VexRay Playground is running at {url}")
    print(f"  ✦ Algorithm: {meta['title']}")
    print(f"  ✦ Press Ctrl+C to stop\n")

    app.run(host="127.0.0.1", port=port, debug=False)
