"""Console-script entrypoint for `ratatoskr-web`.

Per docs/contracts/issues/16.contract.md FN main and INV-001:
- MUST NOT import starlette / uvicorn at module top
- Imports happen INSIDE main() after argparse, with ImportError caught
  and converted to a clean `pip install ratatoskr[web]` exit
- Users without the [web] extras installed get a readable hint instead
  of a naked ImportError traceback
"""

from __future__ import annotations

import argparse
import os
import sys
import webbrowser
from importlib.metadata import version as _pkg_version


def _build_arg_parser() -> argparse.ArgumentParser:
    p = argparse.ArgumentParser(
        prog="ratatoskr-web",
        description="Browser-based debug companion to ratatoskr.",
    )
    p.add_argument(
        "--host", default="0.0.0.0",
        help="Bind address. Default: 0.0.0.0 (LAN-accessible). "
             "Use 127.0.0.1 to restrict to localhost.",
    )
    p.add_argument(
        "--port", type=int, default=8765,
        help="Listen port. Default 8765. Use 0 for random free.",
    )
    p.add_argument(
        "--open", action="store_true",
        help="Auto-open the URL in the system browser.",
    )
    return p


def main(argv: list[str] | None = None) -> int:
    """Console-script entry. Per FN main.

    Returns:
      0 on clean shutdown
      11 on missing WORLDTREE_API_KEY ([auth_error])
      12 on missing [web] extras ([missing_extras])
    """
    args = _build_arg_parser().parse_args(argv)

    # Validate env BEFORE importing starlette so missing env shows the
    # right error regardless of extras-install state.
    api_key = os.environ.get("WORLDTREE_API_KEY")
    if not api_key:
        sys.stderr.write(
            "[auth_error] WORLDTREE_API_KEY env var required. "
            "Source env.sh in your project root.\n"
        )
        return 11
    server_url = os.environ.get("WORLDTREE_API_URL", "http://localhost:8000")
    end_user_id = os.environ.get("RATATOSKR_END_USER_ID")
    # Issue #17 (web bind split): server-held Bifrost binding config. The browser
    # selects the plane; the consumer key + visible host live server-side only.
    bifrost_consumer_key = os.environ.get("RATATOSKR_BIFROST_CONSUMER_KEY")
    bifrost_visible_host = os.environ.get("RATATOSKR_PROVIDER_VISIBLE_HOST")
    # Issue #18 (Deliverable 2): the affect provider's read base URL (server→provider
    # hop on the same dev box) so the persona pane can render PAD/valence from OUR store.
    affect_read_url = os.environ.get(
        "RATATOSKR_AFFECT_READ_URL", "http://127.0.0.1:8390"
    )
    # Admin observability panes (BifrostState + AdminEvents): the readonly-admin
    # key stays SERVER-SIDE — the server proxies admin-scoped reads; the browser
    # never receives the key, only the session-filtered result.
    admin_key = os.environ.get("RATATOSKR_ADMIN_API_KEY")

    # INV-001: lazy import. Users without [web] extras get a clean hint
    # instead of a raw ImportError. Scoped narrowly to the OPTIONAL
    # extras (starlette / uvicorn) so a real import bug inside a
    # production module (ratatoskr.web.server, ratatoskr.cli, httpx —
    # all baseline deps) propagates as a true traceback rather than
    # being masked as "install ratatoskr[web]".
    try:
        import starlette  # noqa: F401  (extras-presence probe)
        import uvicorn
    except ImportError as exc:
        sys.stderr.write(
            f"[missing_extras] {exc}\n"
            f"ratatoskr-web requires the [web] optional dependencies.\n"
            f"Install with: pip install ratatoskr[web]\n"
        )
        return 12

    # Baseline deps + own modules — a failure here is a real bug, not a
    # missing-extras condition; let it propagate.
    import httpx
    from ratatoskr.cli import USER_AGENT
    from ratatoskr.web.server import create_app

    def client_factory() -> "httpx.AsyncClient":
        return httpx.AsyncClient(
            base_url=server_url,
            headers={
                "Authorization": f"Bearer {api_key}",
                "User-Agent": USER_AGENT,
            },
            timeout=httpx.Timeout(connect=10.0, read=None, write=10.0, pool=10.0),
        )

    app = create_app(
        client_factory,
        end_user_id=end_user_id,
        bifrost_consumer_key=bifrost_consumer_key,
        bifrost_visible_host=bifrost_visible_host,
        affect_read_url=affect_read_url,
        admin_key=admin_key,
    )

    # Boot banner to stderr (so stdout stays clean for piping).
    version = _pkg_version("ratatoskr")
    host = args.host
    port = args.port
    display_host = "localhost" if host == "0.0.0.0" else host
    sys.stderr.write(
        f"ratatoskr-web v{version}\n"
        f"Listening on http://{host}:{port}/\n"
        f"Connect from this device: http://{display_host}:{port}/\n"
    )
    if host == "0.0.0.0":
        sys.stderr.write(
            f"Connect from LAN:        http://<host-ip>:{port}/\n"
        )
    sys.stderr.write("Ctrl-C to stop.\n")
    sys.stderr.flush()

    if args.open:
        webbrowser.open(f"http://{display_host}:{port}/")

    uvicorn.run(app, host=host, port=port, log_config=None)
    return 0
