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

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PORT="${PORT:-8000}"
HOST="${HOST:-127.0.0.1}"
PID_FILE="$ROOT_DIR/.static-server.pid"
LOG_FILE="$ROOT_DIR/.static-server.log"

usage() {
  printf 'Usage: %s {start|stop|restart|status}\n' "$0"
  printf 'Environment: PORT=8000 HOST=127.0.0.1\n'
}

is_running() {
  [[ -f "$PID_FILE" ]] || return 1

  local pid
  pid="$(cat "$PID_FILE")"
  [[ "$pid" =~ ^[0-9]+$ ]] || return 1

  kill -0 "$pid" 2>/dev/null
}

start_server() {
  if is_running; then
    printf 'Server is already running on http://%s:%s/ with PID %s\n' "$HOST" "$PORT" "$(cat "$PID_FILE")"
    return 0
  fi

  rm -f "$PID_FILE"

  if ! command -v python3 >/dev/null 2>&1; then
    printf 'Error: python3 is required but was not found.\n' >&2
    return 1
  fi

  if command -v setsid >/dev/null 2>&1; then
    nohup setsid python3 -m http.server "$PORT" --bind "$HOST" --directory "$ROOT_DIR" >"$LOG_FILE" 2>&1 &
  else
    nohup python3 -m http.server "$PORT" --bind "$HOST" --directory "$ROOT_DIR" >"$LOG_FILE" 2>&1 &
  fi
  local pid="$!"
  printf '%s\n' "$pid" >"$PID_FILE"

  sleep 1

  if ! kill -0 "$pid" 2>/dev/null; then
    rm -f "$PID_FILE"
    printf 'Server failed to start. See %s\n' "$LOG_FILE" >&2
    return 1
  fi

  printf 'Server started on http://%s:%s/ with PID %s\n' "$HOST" "$PORT" "$pid"
  printf 'Log: %s\n' "$LOG_FILE"
}

stop_server() {
  if ! is_running; then
    rm -f "$PID_FILE"
    printf 'Server is not running.\n'
    return 0
  fi

  local pid
  pid="$(cat "$PID_FILE")"
  kill "$pid"

  local waited=0
  while kill -0 "$pid" 2>/dev/null; do
    if [[ "$waited" -ge 5 ]]; then
      kill -9 "$pid" 2>/dev/null || true
      break
    fi
    sleep 1
    waited=$((waited + 1))
  done

  rm -f "$PID_FILE"
  printf 'Server stopped.\n'
}

status_server() {
  if is_running; then
    printf 'Server is running on http://%s:%s/ with PID %s\n' "$HOST" "$PORT" "$(cat "$PID_FILE")"
  else
    rm -f "$PID_FILE"
    printf 'Server is not running.\n'
  fi
}

case "${1:-}" in
  start)
    start_server
    ;;
  stop)
    stop_server
    ;;
  restart)
    stop_server
    start_server
    ;;
  status)
    status_server
    ;;
  *)
    usage
    exit 2
    ;;
esac
