#!/usr/bin/env bash
set -euo pipefail

script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
project_root="${PROJECT_AGENT_PROJECT_ROOT:-$(cd -- "$script_dir/.." && pwd -P)}"
project_root="$(cd -- "$project_root" && pwd -P)"
workspace_root="${PROJECT_AGENT_WORKSPACE_ROOT:-$(dirname -- "$project_root")}"
project_agent_helper="${PROJECT_AGENT_HELPER:-${HOME:?HOME is required for the default launcher helper}/.config/omarchy/plugins/kunal.project-agent-launcher/project_agent.py}"
cd -- "$project_root"

for command in python3 curl xdg-open; do
    command -v "$command" >/dev/null || {
        printf 'Required command is unavailable: %s\n' "$command" >&2
        exit 1
    }
done
if [[ ! -f "$project_agent_helper" ]]; then
    printf 'Launcher helper is not a regular file: %s\n' "$project_agent_helper" >&2
    exit 1
fi
if [[ ! -f "$project_root/presentation/centrifuge-architecture.html" ]]; then
    printf 'Architecture presentation is missing from %s\n' "$project_root" >&2
    exit 1
fi

# Prefer the documented port, but leave any existing listener alone.
port="$(python3 - <<'PY'
import errno
import socket

with socket.socket() as listener:
    try:
        listener.bind(('127.0.0.1', 8000))
    except OSError as error:
        if error.errno != errno.EADDRINUSE:
            raise
        listener.bind(('127.0.0.1', 0))
    print(listener.getsockname()[1])
PY
)"
local_url="http://127.0.0.1:$port/presentation/centrifuge-architecture.html"
server_pid=''

cleanup() {
    local status=$?
    trap - EXIT TERM INT HUP
    if [[ -n "$server_pid" ]]; then
        kill -TERM "$server_pid" 2>/dev/null || true
        wait "$server_pid" 2>/dev/null || true
    fi
    exit "$status"
}
trap cleanup EXIT
trap 'exit 143' TERM
trap 'exit 130' INT
trap 'exit 129' HUP

# Background only for readiness and browser coordination; never daemonize.
python3 -u -m http.server "$port" --bind 127.0.0.1 --directory "$project_root" &
server_pid=$!

ready=false
deadline=$((SECONDS + 30))
while (( SECONDS < deadline )); do
    if ! kill -0 "$server_pid" 2>/dev/null; then
        printf 'The presentation server exited before becoming ready.\n' >&2
        exit 1
    fi
    code="$(curl --noproxy '*' -s -o /dev/null -w '%{http_code}' \
        --connect-timeout 1 --max-time 2 "$local_url" || true)"
    # Authentication challenges and other HTTP responses also prove readiness.
    if [[ "$code" =~ ^[0-9]{3}$ && "$code" != 000 ]]; then
        ready=true
        break
    fi
    sleep 0.2
done
if [[ "$ready" != true ]] || ! kill -0 "$server_pid" 2>/dev/null; then
    printf 'The presentation server did not become ready within 30 seconds.\n' >&2
    exit 1
fi

# The helper selects local/tunnel mode and atomically writes run.url.
selected_url="$(python3 "$project_agent_helper" project-tunnel \
    "$workspace_root" "$project_root" "$local_url")"
python3 - "$selected_url" <<'PY'
import ipaddress
import sys
from urllib.parse import urlsplit

url = sys.argv[1]
try:
    parsed = urlsplit(url)
    host = parsed.hostname
    port = parsed.port
    valid = bool(host) and not any(character.isspace() or ord(character) < 32 for character in url)
    valid = valid and parsed.username is None and parsed.password is None
    if parsed.scheme == 'http':
        try:
            loopback = host == 'localhost' or ipaddress.ip_address(host).is_loopback
        except ValueError:
            loopback = False
        valid = valid and loopback
    else:
        # Public HTTPS URLs are supplied by the trusted project-tunnel helper.
        valid = valid and parsed.scheme == 'https'
except ValueError:
    valid = False
if not valid:
    sys.exit('Launcher helper did not return a loopback HTTP or public HTTPS URL.')
PY

if ! kill -0 "$server_pid" 2>/dev/null; then
    printf 'The presentation server exited during launcher setup.\n' >&2
    exit 1
fi
printf 'Project ready: %s\n' "$selected_url"
xdg-open "$selected_url"
wait "$server_pid"
