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

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"

if [[ ! -d ".venv" ]]; then
  python3 -m venv .venv
fi

source .venv/bin/activate
pip install -r requirements.txt >/dev/null

FRONTEND_DIR="${SCRIPT_DIR}/frontend"
: "${FRONTEND_BUILD_ON_START:=1}"

resolve_frontend_runner() {
  if command -v bun >/dev/null 2>&1; then
    echo "bun"
    return 0
  fi
  if [[ -x "${HOME}/.bun/bin/bun" ]]; then
    echo "${HOME}/.bun/bin/bun"
    return 0
  fi
  if command -v npm >/dev/null 2>&1; then
    echo "npm"
    return 0
  fi
  return 1
}

build_frontend_bundle() {
  if [[ ! -f "${FRONTEND_DIR}/package.json" ]]; then
    echo "Frontend package.json not found at ${FRONTEND_DIR}" >&2
    return 1
  fi

  local runner
  if ! runner="$(resolve_frontend_runner)"; then
    echo "Unable to build frontend: install Bun or npm first." >&2
    return 1
  fi

  if [[ ! -d "${FRONTEND_DIR}/node_modules" ]]; then
    echo "Frontend dependencies are missing at ${FRONTEND_DIR}/node_modules." >&2
    if [[ "${runner}" == "bun" || "${runner}" == "${HOME}/.bun/bin/bun" ]]; then
      (
        cd "${FRONTEND_DIR}"
        "${runner}" install --frozen-lockfile
      )
    else
      echo "Install frontend dependencies before starting the server." >&2
      return 1
    fi
  fi

  echo "Building frontend bundle from ${FRONTEND_DIR}"
  if [[ "${runner}" == "npm" ]]; then
    (
      cd "${FRONTEND_DIR}"
      npm run build
    )
  else
    (
      cd "${FRONTEND_DIR}"
      "${runner}" run build
    )
  fi
}

if [[ "${FRONTEND_BUILD_ON_START}" == "1" ]]; then
  build_frontend_bundle
fi

# Optional local voice settings. Example file: .env.voice
if [[ -f ".env.voice" ]]; then
  set -a
  # shellcheck disable=SC1091
  source ".env.voice"
  set +a
fi

# Nanobot command defaults (prefer Nanobot's own virtualenv interpreter).
: "${NANOBOT_WORKDIR:=${HOME}/nanobot}"
if [[ -z "${NANOBOT_COMMAND:-}" ]]; then
  if [[ -x "${NANOBOT_WORKDIR}/.venv/bin/python" ]]; then
    NANOBOT_COMMAND="${NANOBOT_WORKDIR}/.venv/bin/python -m nanobot agent --no-markdown"
  elif [[ -x "${NANOBOT_WORKDIR}/venv/bin/python" ]]; then
    NANOBOT_COMMAND="${NANOBOT_WORKDIR}/venv/bin/python -m nanobot agent --no-markdown"
  fi
fi
export NANOBOT_WORKDIR NANOBOT_COMMAND
: "${NANOBOT_SUPPRESS_NOISY_UI:=1}"
: "${NANOBOT_OUTPUT_DEDUP_WINDOW_S:=1.5}"
export NANOBOT_SUPPRESS_NOISY_UI NANOBOT_OUTPUT_DEDUP_WINDOW_S

# Host voice pipeline env vars (safe defaults).
: "${HOST_STT_PROVIDER:=faster-whisper}"
: "${HOST_STT_COMMAND:=}"
: "${HOST_STT_MODEL:=distil-large-v3}"
: "${HOST_STT_DEVICE:=auto}"
: "${HOST_STT_COMPUTE_TYPE:=int8}"
: "${HOST_STT_LANGUAGE:=en}"
: "${HOST_STT_BEAM_SIZE:=2}"
: "${HOST_STT_BEST_OF:=2}"
: "${HOST_STT_VAD_FILTER:=0}"
: "${HOST_STT_TEMPERATURE:=0.0}"
: "${HOST_STT_LOG_PROB_THRESHOLD:=-1.0}"
: "${HOST_STT_NO_SPEECH_THRESHOLD:=0.6}"
: "${HOST_STT_COMPRESSION_RATIO_THRESHOLD:=2.4}"
: "${HOST_STT_INITIAL_PROMPT:=Transcribe brief spoken English precisely. Prefer common words over sound effects.}"
: "${HOST_STT_REPETITION_PENALTY:=1.0}"
: "${HOST_STT_HALLUCINATION_SILENCE_THRESHOLD:=}"
: "${HOST_TTS_PROVIDER:=supertonic}"
: "${HOST_TTS_COMMAND:=}"
: "${SUPERTONIC_MODEL:=supertonic-2}"
: "${SUPERTONIC_VOICE_STYLE:=F1}"
: "${SUPERTONIC_LANG:=en}"
: "${SUPERTONIC_TOTAL_STEPS:=8}"
: "${SUPERTONIC_SPEED:=1.5}"
: "${SUPERTONIC_INTRA_OP_THREADS:=1}"
: "${SUPERTONIC_INTER_OP_THREADS:=1}"
: "${SUPERTONIC_AUTO_DOWNLOAD:=1}"
: "${HOST_STT_MIN_PTT_MS:=220}"
: "${HOST_STT_SEGMENT_QUEUE_SIZE:=2}"
: "${HOST_STT_BACKLOG_NOTICE_INTERVAL_S:=6.0}"
: "${HOST_STT_SUPPRESS_DURING_TTS:=1}"
: "${HOST_STT_SUPPRESS_MS_AFTER_TTS:=300}"
: "${HOST_RTC_OUTBOUND_LEAD_IN_MS:=120}"
: "${HOST_RTC_OUTBOUND_IDLE_S:=0.6}"

export HOST_STT_PROVIDER HOST_STT_COMMAND HOST_STT_MODEL HOST_STT_DEVICE
export HOST_STT_COMPUTE_TYPE HOST_STT_LANGUAGE HOST_STT_BEAM_SIZE HOST_STT_BEST_OF HOST_STT_VAD_FILTER
export HOST_STT_TEMPERATURE HOST_STT_LOG_PROB_THRESHOLD HOST_STT_NO_SPEECH_THRESHOLD
export HOST_STT_COMPRESSION_RATIO_THRESHOLD
export HOST_STT_INITIAL_PROMPT HOST_STT_REPETITION_PENALTY HOST_STT_HALLUCINATION_SILENCE_THRESHOLD
export HOST_TTS_PROVIDER HOST_TTS_COMMAND
export SUPERTONIC_MODEL SUPERTONIC_VOICE_STYLE SUPERTONIC_LANG
export SUPERTONIC_TOTAL_STEPS SUPERTONIC_SPEED
export SUPERTONIC_INTRA_OP_THREADS SUPERTONIC_INTER_OP_THREADS SUPERTONIC_AUTO_DOWNLOAD
export HOST_STT_MIN_PTT_MS HOST_STT_SEGMENT_QUEUE_SIZE
export HOST_STT_BACKLOG_NOTICE_INTERVAL_S
export HOST_STT_SUPPRESS_DURING_TTS HOST_STT_SUPPRESS_MS_AFTER_TTS
export HOST_RTC_OUTBOUND_LEAD_IN_MS HOST_RTC_OUTBOUND_IDLE_S

: "${UVICORN_HOST:=0.0.0.0}"
: "${UVICORN_PORT:=8000}"
: "${ENABLE_HTTPS:=1}"
: "${SSL_DAYS:=365}"
: "${SSL_CERT_FILE:=.certs/local-cert.pem}"
: "${SSL_KEY_FILE:=.certs/local-key.pem}"

if [[ "$ENABLE_HTTPS" == "1" ]]; then
  mkdir -p "$(dirname "$SSL_CERT_FILE")"
  mkdir -p "$(dirname "$SSL_KEY_FILE")"

  if [[ ! -f "$SSL_CERT_FILE" || ! -f "$SSL_KEY_FILE" ]]; then
    LOCAL_IP="$(hostname -I 2>/dev/null | awk '{print $1}')"
    SAN_ENTRIES="DNS:localhost,IP:127.0.0.1"
    if [[ -n "${LOCAL_IP:-}" ]]; then
      SAN_ENTRIES="${SAN_ENTRIES},IP:${LOCAL_IP}"
    fi

    echo "Generating local TLS certificate at '$SSL_CERT_FILE' (SAN: ${SAN_ENTRIES})"
    openssl req -x509 -newkey rsa:2048 -sha256 -nodes -days "$SSL_DAYS" \
      -keyout "$SSL_KEY_FILE" \
      -out "$SSL_CERT_FILE" \
      -subj "/CN=localhost" \
      -addext "subjectAltName=${SAN_ENTRIES}" \
      -addext "keyUsage=digitalSignature,keyEncipherment" \
      -addext "extendedKeyUsage=serverAuth"
  fi

  echo "Starting HTTPS server on https://localhost:${UVICORN_PORT}"
  exec uvicorn app:app --host "$UVICORN_HOST" --port "$UVICORN_PORT" \
    --ssl-certfile "$SSL_CERT_FILE" \
    --ssl-keyfile "$SSL_KEY_FILE"
fi

echo "Starting HTTP server on http://localhost:${UVICORN_PORT}"
exec uvicorn app:app --host "$UVICORN_HOST" --port "$UVICORN_PORT"
