#!/usr/bin/env python3
"""Timmy Time — Development server launcher.

Satisfies tox -e dev criteria:
  - Graceful port selection (finds next free port if default is taken)
  - Clickable links to dashboard and other web GUIs
  - Status line: backend inference source, version, git commit, smoke tests
  - Auto-reload on code changes (delegates to uvicorn --reload)

Usage: python scripts/dev_server.py [--port PORT]
"""

import argparse
import datetime
import os
import socket
import subprocess
import sys

DEFAULT_PORT = 8000
MAX_PORT_ATTEMPTS = 10
OLLAMA_DEFAULT = "http://localhost:11434"


def _port_free(port: int) -> bool:
    """Return True if the TCP port is available on localhost."""
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        try:
            s.bind(("0.0.0.0", port))
            return True
        except OSError:
            return False


def _find_port(start: int) -> int:
    """Return *start* if free, otherwise probe up to MAX_PORT_ATTEMPTS higher."""
    for offset in range(MAX_PORT_ATTEMPTS):
        candidate = start + offset
        if _port_free(candidate):
            return candidate
    raise RuntimeError(
        f"No free port found in range {start}–{start + MAX_PORT_ATTEMPTS - 1}"
    )


def _git_info() -> str:
    """Return short commit hash + timestamp, or 'unknown'."""
    try:
        sha = subprocess.check_output(
            ["git", "rev-parse", "--short", "HEAD"],
            stderr=subprocess.DEVNULL,
            text=True,
        ).strip()
        ts = subprocess.check_output(
            ["git", "log", "-1", "--format=%ci"],
            stderr=subprocess.DEVNULL,
            text=True,
        ).strip()
        return f"{sha} ({ts})"
    except Exception:
        return "unknown"


def _project_version() -> str:
    """Read version from pyproject.toml without importing toml libs."""
    pyproject = os.path.join(os.path.dirname(__file__), "..", "pyproject.toml")
    try:
        with open(pyproject) as f:
            for line in f:
                if line.strip().startswith("version"):
                    # version = "1.0.0"
                    return line.split("=", 1)[1].strip().strip('"').strip("'")
    except Exception:
        pass
    return "unknown"


def _ollama_url() -> str:
    return os.environ.get("OLLAMA_URL", OLLAMA_DEFAULT)


def _smoke_ollama(url: str) -> str:
    """Quick connectivity check against Ollama."""
    import urllib.request
    import urllib.error

    try:
        req = urllib.request.Request(url, method="GET")
        with urllib.request.urlopen(req, timeout=3):
            return "ok"
    except Exception:
        return "unreachable"


def _print_banner(port: int) -> None:
    version = _project_version()
    git = _git_info()
    ollama_url = _ollama_url()
    ollama_status = _smoke_ollama(ollama_url)

    hr = "─" * 62
    print(flush=True)
    print(f"  {hr}")
    print(f"  ┃  Timmy Time — Development Server")
    print(f"  {hr}")
    print()
    print(f"  Dashboard:   http://localhost:{port}")
    print(f"  API docs:    http://localhost:{port}/docs")
    print(f"  Health:      http://localhost:{port}/health")
    print()
    print(f"  ── Status ──────────────────────────────────────────────")
    print(f"  Backend:     {ollama_url}  [{ollama_status}]")
    print(f"  Version:     {version}")
    print(f"  Git commit:  {git}")
    print(f"  {hr}")
    print(flush=True)


def main() -> None:
    parser = argparse.ArgumentParser(description="Timmy dev server")
    parser.add_argument(
        "--port",
        type=int,
        default=DEFAULT_PORT,
        help=f"Preferred port (default: {DEFAULT_PORT})",
    )
    args = parser.parse_args()

    port = _find_port(args.port)
    if port != args.port:
        print(f"  ⚠  Port {args.port} in use — using {port} instead")

    _print_banner(port)

    # Set PYTHONPATH so `timmy` CLI inside the tox venv resolves to this source.
    src_dir = os.path.join(os.path.dirname(__file__), "..", "src")
    os.environ["PYTHONPATH"] = os.path.abspath(src_dir)

    # Launch uvicorn with auto-reload
    cmd = [
        sys.executable,
        "-m",
        "uvicorn",
        "dashboard.app:app",
        "--reload",
        "--host",
        "0.0.0.0",
        "--port",
        str(port),
        "--reload-dir",
        os.path.abspath(src_dir),
        "--reload-include",
        "*.html",
        "--reload-include",
        "*.css",
        "--reload-include",
        "*.js",
        "--reload-exclude",
        ".claude",
    ]

    try:
        subprocess.run(cmd, check=True)
    except KeyboardInterrupt:
        print("\n  Shutting down dev server.")


if __name__ == "__main__":
    main()
