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

SOURCE_PATH="${BASH_SOURCE[0]}"
while [[ -L "$SOURCE_PATH" ]]; do
  SOURCE_DIR="$(cd "$(dirname "$SOURCE_PATH")" && pwd)"
  SOURCE_PATH="$(readlink "$SOURCE_PATH")"
  [[ "$SOURCE_PATH" != /* ]] && SOURCE_PATH="$SOURCE_DIR/$SOURCE_PATH"
done
SCRIPT_DIR="$(cd "$(dirname "$SOURCE_PATH")" && pwd)"
PROJECT_DIR="${PROJECT_DIR:-$(cd "$SCRIPT_DIR/.." && pwd)}"
PIPELINE_SCRIPT="$PROJECT_DIR/transcript_pipeline.py"
PIPELINE_LOG="$PROJECT_DIR/pipeline.log"
STATE_DB="$PROJECT_DIR/pipeline_state.sqlite3"
PLATFORM="$(uname -s)"
LABEL="com.maddin.whisper-transcript-pipeline"
PYTHON_BIN="${PYTHON_BIN:-$(command -v python3 || true)}"

if [[ -z "$PYTHON_BIN" ]]; then
  echo "python3 not found in PATH" >&2
  exit 1
fi

macos_is_loaded() {
  local domain
  domain="gui/$(id -u)"
  launchctl print "$domain/$LABEL" >/dev/null 2>&1
}

linux_service_name() {
  echo "$LABEL.service"
}

linux_unit_path() {
  echo "$HOME/.config/systemd/user/$(linux_service_name)"
}

show_pending_uploads() {
  if [[ -f "$STATE_DB" ]] && command -v sqlite3 >/dev/null 2>&1; then
    local pending
    pending="$(sqlite3 "$STATE_DB" "select basename || '|' || coalesce(remote_audio_status,'') || '|' || coalesce(remote_audio_last_error,'') from source_state where coalesce(remote_audio_status,'') != '' and remote_audio_status != 'uploaded';" || true)"
    if [[ -n "$pending" ]]; then
      echo "pending uploads:"
      echo "$pending"
    fi
  fi
}

macos_start() {
  exec "$PROJECT_DIR/install_launch_agent.sh"
}

macos_stop() {
  if [[ -x "$PROJECT_DIR/uninstall_launch_agent.sh" ]]; then
    "$PROJECT_DIR/uninstall_launch_agent.sh" --keep-files
  fi
  pkill -f "$PIPELINE_SCRIPT watch" >/dev/null 2>&1 || true
  echo "stopped: $LABEL"
}

macos_status() {
  local pids
  if macos_is_loaded; then
    echo "launchd: loaded"
    launchctl list | grep "$LABEL" || true
  else
    echo "launchd: not loaded"
  fi

  pids="$(pgrep -af "$PIPELINE_SCRIPT watch" || true)"
  if [[ -n "$pids" ]]; then
    echo "process:"
    echo "$pids"
  else
    echo "process: not running"
  fi

  if [[ -f "$PIPELINE_LOG" ]]; then
    echo "pipeline log:"
    tail -n 5 "$PIPELINE_LOG"
  fi
  show_pending_uploads
}

linux_start() {
  exec "$PROJECT_DIR/deploy/linux/install_systemd_service.sh"
}

linux_stop() {
  local service
  service="$(linux_service_name)"
  systemctl --user stop "$service" >/dev/null 2>&1 || true
  pkill -f "$PIPELINE_SCRIPT watch" >/dev/null 2>&1 || true
  echo "stopped: $service"
}

linux_status() {
  local service pids
  service="$(linux_service_name)"
  if systemctl --user status "$service" >/dev/null 2>&1; then
    echo "systemd --user: loaded"
  else
    echo "systemd --user: not loaded"
  fi

  pids="$(pgrep -af "$PIPELINE_SCRIPT watch" || true)"
  if [[ -n "$pids" ]]; then
    echo "process:"
    echo "$pids"
  else
    echo "process: not running"
  fi

  if [[ -f "$PIPELINE_LOG" ]]; then
    echo "pipeline log:"
    tail -n 5 "$PIPELINE_LOG"
  fi
  show_pending_uploads
}

cmd_start() {
  case "$PLATFORM" in
    Darwin) macos_start ;;
    Linux) linux_start ;;
    *)
      echo "unsupported platform: $PLATFORM" >&2
      exit 1
      ;;
  esac
}

cmd_stop() {
  case "$PLATFORM" in
    Darwin) macos_stop ;;
    Linux) linux_stop ;;
    *)
      echo "unsupported platform: $PLATFORM" >&2
      exit 1
      ;;
  esac
}

cmd_restart() {
  cmd_stop
  cmd_start
}

cmd_install() {
  cmd_start
}

cmd_uninstall() {
  case "$PLATFORM" in
    Darwin) exec "$PROJECT_DIR/uninstall_launch_agent.sh" ;;
    Linux) exec "$PROJECT_DIR/deploy/linux/uninstall_systemd_service.sh" ;;
    *)
      echo "unsupported platform: $PLATFORM" >&2
      exit 1
      ;;
  esac
}

cmd_status() {
  case "$PLATFORM" in
    Darwin) macos_status ;;
    Linux) linux_status ;;
    *)
      echo "unsupported platform: $PLATFORM" >&2
      exit 1
      ;;
  esac
}

cmd_logs() {
  local which_log="${1:-pipeline}"
  case "$PLATFORM" in
    Darwin)
      case "$which_log" in
        pipeline) tail -f "$PIPELINE_LOG" ;;
        stdout) tail -f "$PROJECT_DIR/launchd.stdout.log" ;;
        stderr) tail -f "$PROJECT_DIR/launchd.stderr.log" ;;
        all) tail -f "$PIPELINE_LOG" "$PROJECT_DIR/launchd.stdout.log" "$PROJECT_DIR/launchd.stderr.log" ;;
        *)
          echo "unknown log target: $which_log" >&2
          exit 1
          ;;
      esac
      ;;
    Linux)
      case "$which_log" in
        pipeline) tail -f "$PIPELINE_LOG" ;;
        service|journal) journalctl --user -u "$(linux_service_name)" -f ;;
        all) tail -f "$PIPELINE_LOG" ;;
        *)
          echo "unknown log target: $which_log" >&2
          exit 1
          ;;
      esac
      ;;
    *)
      echo "unsupported platform: $PLATFORM" >&2
      exit 1
      ;;
  esac
}

cmd_scan() {
  exec "$PYTHON_BIN" "$PIPELINE_SCRIPT" scan "$@"
}

cmd_cleanup() {
  exec "$PYTHON_BIN" "$PIPELINE_SCRIPT" cleanup
}

cmd_memos_sync() {
  exec "$PYTHON_BIN" "$PIPELINE_SCRIPT" memos-sync
}

cmd_memos_auth() {
  exec "$PYTHON_BIN" "$PIPELINE_SCRIPT" memos-auth
}

cmd_retry_uploads() {
  exec "$PYTHON_BIN" "$PIPELINE_SCRIPT" retry-uploads
}

cmd_migrate_archive() {
  exec "$PYTHON_BIN" "$PIPELINE_SCRIPT" migrate-archive
}

cmd_reprocess() {
  if [[ $# -lt 1 ]]; then
    echo "usage: transcript reprocess <basename>" >&2
    exit 1
  fi
  exec "$PYTHON_BIN" "$PIPELINE_SCRIPT" reprocess "$1"
}

cmd_bundle() {
  exec "$PROJECT_DIR/scripts/create_migration_bundle.sh"
}

cmd_help() {
  cat <<'EOF'
Usage: transcript <command> [args]

Commands:
  install               Install and start the background watcher
  start                 Start or install the background watcher
  stop                  Stop the background watcher
  restart               Restart the background watcher
  uninstall             Uninstall the background watcher service
  status                Show service/process status and recent pipeline log lines
  logs [pipeline|stdout|stderr|service|journal|all]
                        Follow log output
  scan                  Process currently available transcript/audio pairs once
  cleanup               Delete archived originals older than the retention period
  memos-sync            Export published notes for Quartz and rebuild memos.maddin.app
  memos-auth            Generate the Basic Auth htpasswd file from .env
  retry-uploads         Retry remote audio uploads from the local archive
  migrate-archive       Retroactively migrate archived sources to the new schema
  reprocess <basename>  Reprocess one basename from the watch folder
  bundle                Build a portable migration tarball in dist/
  help                  Show this help
EOF
}

command="${1:-help}"
shift || true

case "$command" in
  install) cmd_install ;;
  start) cmd_start ;;
  stop) cmd_stop ;;
  restart) cmd_restart ;;
  uninstall) cmd_uninstall ;;
  status) cmd_status ;;
  logs) cmd_logs "$@" ;;
  scan) cmd_scan "$@" ;;
  cleanup) cmd_cleanup ;;
  memos-sync) cmd_memos_sync ;;
  memos-auth) cmd_memos_auth ;;
  retry-uploads) cmd_retry_uploads ;;
  migrate-archive) cmd_migrate_archive ;;
  reprocess) cmd_reprocess "$@" ;;
  bundle) cmd_bundle ;;
  help|-h|--help) cmd_help ;;
  *)
    echo "unknown command: $command" >&2
    echo >&2
    cmd_help >&2
    exit 1
    ;;
esac
