import os
import secrets
import socket
import sys
import threading
import time

import uvicorn
import webview
from webview.menu import Menu, MenuAction

APP_NAME = "Agent DevLog"


def _set_macos_app_name(name: str):
    """Set the application name in the macOS menu bar."""
    try:
        import AppKit

        bundle = AppKit.NSBundle.mainBundle()
        info = bundle.localizedInfoDictionary() or bundle.infoDictionary()
        info["CFBundleName"] = name
    except ImportError:
        pass


def _find_free_port(host: str, preferred: int) -> int:
    """Return preferred port if available, otherwise find a free one."""
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        try:
            s.bind((host, preferred))
            return preferred
        except OSError:
            s.bind((host, 0))
            return s.getsockname()[1]


def _start_server(host: str, port: int):
    uvicorn.run(
        "agent_devlog.app:app",
        host=host,
        port=port,
        log_level="error",
    )


def _wait_for_server(host: str, port: int, timeout: float = 5.0):
    """Block until the server is accepting connections."""
    deadline = time.monotonic() + timeout
    while time.monotonic() < deadline:
        try:
            with socket.create_connection((host, port), timeout=0.1):
                return
        except OSError:
            time.sleep(0.05)


def main():
    preferred_port = int(os.environ.get("PORT", "8000"))
    host = os.environ.get("HOST", "127.0.0.1")

    if not os.environ.get("PYVIEW_SECRET"):
        os.environ["PYVIEW_SECRET"] = secrets.token_urlsafe(16)

    port = _find_free_port(host, preferred_port)

    if sys.platform == "darwin":
        _set_macos_app_name(APP_NAME)

    url = f"http://{host}:{port}"

    threading.Thread(target=_start_server, args=(host, port), daemon=True).start()
    _wait_for_server(host, port)

    window = webview.create_window(APP_NAME, url)

    def refresh():
        window.evaluate_js("location.reload()")

    def bind_keys():
        window.evaluate_js(
            "document.addEventListener('keydown', e => {"
            "  if ((e.metaKey || e.ctrlKey) && e.key === 'r') {"
            "    e.preventDefault(); location.reload();"
            "  }"
            "})"
        )

    window.events.loaded += bind_keys

    menu = [Menu("View", [MenuAction("Refresh", refresh)])]

    webview.start(menu=menu)


if __name__ == "__main__":
    main()
