"""WorkOS browser-redirect login flow.

The CLI handles the browser redirect and captures the auth code.
The control plane exchanges the code for tokens (it has the API key).
"""

import html
import http.server
import urllib.parse
import webbrowser
from typing import Any

import httpx

from . import config
from .api import _raise_for_status

REDIRECT_URI = "http://localhost:9876/callback"


def login(env: str | None = None) -> dict[str, Any]:
    """Open browser for WorkOS login, send code to control plane, save credentials."""
    env = env or config.get_current_env()
    env_config = config.get_env_config(env)

    endpoint: str | None = env_config.get("endpoint")
    if not endpoint:
        raise ValueError(f"No endpoint configured for environment '{env}'")

    # Step 1: Get auth URL from control plane
    resp = httpx.get(f"{endpoint}/auth/url", params={"redirect_uri": REDIRECT_URI}, timeout=10)
    _raise_for_status(resp)
    auth_data: dict[str, Any] = resp.json()
    auth_url: str = auth_data["url"]

    # Step 2: Open browser + capture callback code
    result: dict[str, str] = {}

    class CallbackHandler(http.server.BaseHTTPRequestHandler):
        def do_GET(self) -> None:
            query = urllib.parse.urlparse(self.path).query
            params = urllib.parse.parse_qs(query)

            if "code" in params:
                result["code"] = params["code"][0]
                self.send_response(200)
                self.send_header("Content-Type", "text/html")
                self.end_headers()
                self.wfile.write(
                    b"<html><body style='font-family:system-ui;text-align:center;padding:60px'>"
                    b"<h1>Logged in!</h1><p>You can close this tab.</p></body></html>"
                )
            else:
                error = params.get("error", ["unknown"])[0]
                result["error"] = error
                self.send_response(400)
                self.send_header("Content-Type", "text/html")
                self.end_headers()
                self.wfile.write(f"<html><body>Error: {html.escape(error)}</body></html>".encode())

        def log_message(self, format: str, *args: object) -> None:
            pass

    try:
        server = http.server.HTTPServer(("localhost", 9876), CallbackHandler)
    except OSError as e:
        raise RuntimeError(f"Could not start login server on port 9876: {e}. Is another process using it?")

    webbrowser.open(auth_url)
    server.handle_request()
    server.server_close()

    if "error" in result:
        raise RuntimeError(f"Login failed: {result['error']}")

    # Step 3: Send code to control plane for exchange
    resp = httpx.post(
        f"{endpoint}/auth/callback",
        json={"code": result["code"], "redirect_uri": REDIRECT_URI},
        timeout=30,
    )
    _raise_for_status(resp)
    data: dict[str, Any] = resp.json()

    # Step 4: Save credentials
    config.save_credentials(
        env,
        {
            "user_id": data["user_id"],
            "email": data["email"],
            "first_name": data.get("first_name"),
            "last_name": data.get("last_name"),
            "access_token": data["access_token"],
            "refresh_token": data.get("refresh_token"),
        },
    )

    return data
