#!/usr/bin/env bash

set -euo pipefail

LABEL="com.nextora.imessage-worker"
HOME_DIR="${HOME}"
BASE_DIR="${HOME_DIR}/.nextora-imessage"
LOG_DIR="${BASE_DIR}/logs"
LOG_FILE="${LOG_DIR}/worker.log"
WORKER_PATH="${BASE_DIR}/worker.sh"
ENV_PATH="${BASE_DIR}/.env"
PLIST_PATH="${HOME_DIR}/Library/LaunchAgents/${LABEL}.plist"

DEFAULT_GATEWAY_URL="https://www.usenextora.com"
DEFAULT_CRM_WEBHOOK_URL="https://www.usenextora.com/api/messages/inbound/blue"
DEFAULT_CRM_OUTBOUND_WEBHOOK_URL="https://www.usenextora.com/api/messages/outbound/blue-status"
DEFAULT_WORKER_URL="https://www.usenextora.com/imessage/worker.sh"

DEVICE_ID=""
DEVICE_SECRET=""

ensure_dirs() {
  mkdir -p "$BASE_DIR" "$LOG_DIR"
}

download_file() {
  local url="$1"
  local dest="$2"
  ensure_dirs
  curl -fsSL -H "User-Agent: nextora-imessage-cli/2.0" "$url" -o "$dest"
}

write_env() {
  local device_id="$1"
  local device_secret="$2"
  local gateway_url="$3"
  local crm_webhook_url="$4"
  local crm_outbound_webhook_url="$5"
  local check_interval="$6"
  local enable_inbound="$7"

  cat > "$ENV_PATH" <<EOF
DEVICE_ID=$device_id
DEVICE_SECRET=$device_secret
GATEWAY_URL=$gateway_url
CRM_WEBHOOK_URL=$crm_webhook_url
CRM_OUTBOUND_WEBHOOK_URL=$crm_outbound_webhook_url
CHECK_INTERVAL=$check_interval
ENABLE_INBOUND=$enable_inbound
EOF
  chmod 600 "$ENV_PATH" 2>/dev/null || true
}

cleanup_legacy_launcher() {
  local legacy_run_command="${BASE_DIR}/run.command"
  local legacy_supervisor="${BASE_DIR}/launch-supervisor.sh"
  pkill -f "$legacy_run_command" >/dev/null 2>&1 || true
  pkill -f "$legacy_supervisor" >/dev/null 2>&1 || true
  rm -f "$legacy_run_command" "$legacy_supervisor"
}

create_launch_agent() {
  mkdir -p "$(dirname "$PLIST_PATH")"
  cat > "$PLIST_PATH" <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key><string>${LABEL}</string>
  <key>ProgramArguments</key>
  <array>
    <string>/bin/bash</string>
    <string>${WORKER_PATH}</string>
  </array>
  <key>RunAtLoad</key><true/>
  <key>KeepAlive</key><true/>
  <key>StandardOutPath</key><string>${LOG_FILE}</string>
  <key>StandardErrorPath</key><string>${LOG_FILE}</string>
</dict>
</plist>
EOF
}

launchctl_load() {
  launchctl bootout "gui/$(id -u)" "$PLIST_PATH" 2>/dev/null || launchctl unload "$PLIST_PATH" 2>/dev/null || true
  launchctl bootstrap "gui/$(id -u)" "$PLIST_PATH" 2>/dev/null || launchctl load "$PLIST_PATH"
  launchctl kickstart -k "gui/$(id -u)/${LABEL}" 2>/dev/null || true
}

launchctl_unload() {
  launchctl bootout "gui/$(id -u)" "$PLIST_PATH" 2>/dev/null || launchctl unload "$PLIST_PATH" 2>/dev/null || true
}

launchctl_is_loaded() {
  launchctl list | grep -q "$LABEL"
}

enroll_with_pair_code() {
  local gateway_url="$1"
  local pair_code="$2"
  local tmp_file http_code
  tmp_file="$(mktemp)"
  http_code="$(curl -sS --connect-timeout 5 --max-time 30 -o "$tmp_file" -w '%{http_code}' \
    -X POST "${gateway_url%/}/api/device-workers/enroll" \
    -H "Content-Type: application/json" \
    -H "User-Agent: nextora-imessage-cli/2.0" \
    --data "{\"pairingCode\":\"${pair_code}\"}" || printf '000')"
  if [ "$http_code" != "200" ]; then
    rm -f "$tmp_file"
    echo "Enroll failed (HTTP $http_code)." >&2
    return 1
  fi

  DEVICE_ID="$(cat "$tmp_file" | /usr/bin/ruby -rjson -e 'data = JSON.parse(STDIN.read) rescue {}; puts(data["deviceId"].to_s)')"
  DEVICE_SECRET="$(cat "$tmp_file" | /usr/bin/ruby -rjson -e 'data = JSON.parse(STDIN.read) rescue {}; puts(data["deviceSecret"].to_s)')"
  rm -f "$tmp_file"
  [ -n "$DEVICE_ID" ] && [ -n "$DEVICE_SECRET" ]
}

cmd_install() {
  ensure_dirs

  local pair_code=""
  local worker_url="$DEFAULT_WORKER_URL"
  local crm_webhook_url="$DEFAULT_CRM_WEBHOOK_URL"
  local crm_outbound_webhook_url="$DEFAULT_CRM_OUTBOUND_WEBHOOK_URL"
  local gateway_url="$DEFAULT_GATEWAY_URL"
  local check_interval="10"
  local enable_inbound="true"

  while [ $# -gt 0 ]; do
    case "$1" in
      --pair-code) pair_code="${2:-}"; shift 2 ;;
      --device-id) DEVICE_ID="${2:-}"; shift 2 ;;
      --device-secret) DEVICE_SECRET="${2:-}"; shift 2 ;;
      --gateway-url) gateway_url="${2:-}"; shift 2 ;;
      --crm-webhook-url) crm_webhook_url="${2:-}"; shift 2 ;;
      --crm-outbound-webhook-url) crm_outbound_webhook_url="${2:-}"; shift 2 ;;
      --worker-url) worker_url="${2:-}"; shift 2 ;;
      --check-interval) check_interval="${2:-10}"; shift 2 ;;
      --disable-inbound) enable_inbound="false"; shift ;;
      *) echo "Unknown option: $1" >&2; exit 1 ;;
    esac
  done

  echo "Downloading shell worker..."
  download_file "$worker_url" "$WORKER_PATH"
  chmod +x "$WORKER_PATH"

  if [ -n "$pair_code" ]; then
    echo "Enrolling device with pairing code..."
    enroll_with_pair_code "$gateway_url" "$pair_code" || exit 1
  fi

  if [ -z "$DEVICE_ID" ] || [ -z "$DEVICE_SECRET" ]; then
    echo
    echo "Device credentials required (Nextora -> Settings -> Messaging -> Register Mac)"
    read -r -p "Device ID: " DEVICE_ID
    read -r -s -p "Device Secret: " DEVICE_SECRET
    echo
  fi

  if [ -z "$DEVICE_ID" ] || [ -z "$DEVICE_SECRET" ]; then
    echo "Device ID and Device Secret are required." >&2
    exit 1
  fi

  write_env "$DEVICE_ID" "$DEVICE_SECRET" "$gateway_url" "$crm_webhook_url" "$crm_outbound_webhook_url" "$check_interval" "$enable_inbound"
  cleanup_legacy_launcher
  create_launch_agent
  launchctl_load

  echo
  echo "Installed successfully."
  echo "Worker mode: headless launchd service (no Terminal window needed)."
  echo "Auto-start: launches when you log into this Mac and relaunches if it exits."
  echo "One-time permissions:"
  echo "  1) System Settings -> Privacy & Security -> Full Disk Access -> enable Terminal"
  echo "  2) First send may prompt: allow Terminal to control Messages"
  echo
  echo "Use: nextora-imessage status"
  echo "Use: nextora-imessage logs"
}

cmd_status() {
  echo "Nextora iMessage status"
  echo "----------------------------"
  echo "Base dir:      $BASE_DIR"
  [ -f "$WORKER_PATH" ] && echo "Worker file:   OK" || echo "Worker file:   missing"
  [ -f "$ENV_PATH" ] && echo "Config file:   OK" || echo "Config file:   missing"
  echo "Launch mode:   headless launchd service"
  launchctl_is_loaded && echo "LaunchAgent:   loaded" || echo "LaunchAgent:   not loaded"
  echo "Log file:      $LOG_FILE"

  if [ -f "$ENV_PATH" ]; then
    local device_id gateway
    device_id="$(grep '^DEVICE_ID=' "$ENV_PATH" | head -n1 | cut -d= -f2- || true)"
    gateway="$(grep '^GATEWAY_URL=' "$ENV_PATH" | head -n1 | cut -d= -f2- || true)"
    [ -n "$device_id" ] && echo "Device ID:     $device_id"
    [ -n "$gateway" ] && echo "Gateway URL:   $gateway"
  fi
}

applescript_send() {
  local to_number="$1"
  local body="$2"
  /usr/bin/osascript - "$to_number" "$body" <<'APPLESCRIPT'
on run argv
    set targetRecipient to item 1 of argv
    set messageBody to item 2 of argv
    tell application "Messages"
        set targetService to 1st account whose service type = iMessage
        set targetBuddy to participant targetRecipient of targetService
        send messageBody to targetBuddy
    end tell
end run
APPLESCRIPT
}

test_db_access() {
  local chat_db="${HOME_DIR}/Library/Messages/chat.db"
  if [ ! -f "$chat_db" ]; then
    echo "FAIL chat.db not found at $chat_db"
    return 1
  fi

  if sqlite3 -readonly "$chat_db" "SELECT COUNT(*) FROM message;" >/dev/null 2>&1; then
    echo "OK Inbound DB read OK"
    return 0
  fi

  echo "FAIL Cannot read chat.db (Full Disk Access likely missing)"
  return 1
}

cmd_test() {
  local to=""
  local message="Nextora iMessage test"

  while [ $# -gt 0 ]; do
    case "$1" in
      --to) to="${2:-}"; shift 2 ;;
      --message) message="${2:-Nextora iMessage test}"; shift 2 ;;
      *) echo "Unknown option: $1" >&2; exit 1 ;;
    esac
  done

  echo "Running diagnostics..."
  echo "[Inbound DB] $(test_db_access)"

  if [ -n "$to" ]; then
    if applescript_send "$to" "$message"; then
      echo "[Outbound] OK AppleScript send invoked. Check Messages app."
    else
      echo "[Outbound] FAIL AppleScript send error"
    fi
  else
    echo "[Outbound] skipped. Use --to +15551234567"
  fi
}

cmd_logs() {
  local follow="false"
  local lines="200"
  while [ $# -gt 0 ]; do
    case "$1" in
      --follow) follow="true"; shift ;;
      --lines) lines="${2:-200}"; shift 2 ;;
      *) echo "Unknown option: $1" >&2; exit 1 ;;
    esac
  done

  if [ ! -f "$LOG_FILE" ]; then
    echo "No logs yet."
    exit 0
  fi

  if [ "$follow" = "true" ]; then
    tail -f "$LOG_FILE"
  else
    tail -n "$lines" "$LOG_FILE"
  fi
}

cmd_uninstall() {
  echo "Stopping service..."
  launchctl_unload
  pkill -f "$WORKER_PATH" >/dev/null 2>&1 || true
  cleanup_legacy_launcher

  echo "Removing files..."
  rm -f "$PLIST_PATH"
  rm -rf "$BASE_DIR"
  echo "Uninstalled."
}

main() {
  local cmd="${1:-}"
  shift || true

  case "$cmd" in
    install) cmd_install "$@" ;;
    status) cmd_status ;;
    test) cmd_test "$@" ;;
    logs) cmd_logs "$@" ;;
    uninstall) cmd_uninstall ;;
    ""|-h|--help|help)
      cat <<EOF
Nextora iMessage CLI

Commands:
  install     Install and configure the headless iMessage worker
  status      Show device and service status
  test        Test outbound and inbound access
  logs        Tail worker logs
  uninstall   Remove worker and service
EOF
      ;;
    *)
      echo "Unknown command: $cmd" >&2
      exit 1
      ;;
  esac
}

main "$@"
