#!/bin/bash
# ispeak — iSpeak 控制命令
set -euo pipefail

resolve_script_dir() {
  local target="$1"
  if [ -L "$target" ]; then
    local link="$(readlink "$target")"
    if [[ "$link" != /* ]]; then
      target="$(cd "$(dirname "$target")" && pwd)/$link"
    else
      target="$link"
    fi
  fi
  cd "$(dirname "$target")" && pwd
}
SCRIPT_DIR="$(resolve_script_dir "$0")"
VERSION=""
if [[ -f "$SCRIPT_DIR/../package.json" ]]; then
  VERSION=$(grep -o '"version"[[:space:]]*:[[:space:]]*"[^"]*"' "$SCRIPT_DIR/../package.json" | head -1 | sed 's/.*: *"\(.*\)"/\1/')
fi
VERSION="${VERSION:-1.10.0}"
BIN_DIR="$HOME/.local/bin"
CONFIG_DIR="$HOME/.config/ispeak"
SOCK="$CONFIG_DIR/ispeak.sock"
PLIST="$HOME/Library/LaunchAgents/com.user.ispeak.plist"
BINARY_PATH="$BIN_DIR/ispeakd"
SOURCE=""

install_hook() {
  local src="$SCRIPT_DIR/../$1"
  local dst="$2"
  if [[ -f "$dst" ]]; then
    if ! diff -q "$src" "$dst" >/dev/null 2>&1; then
      cp "$dst" "${dst}.bak" 2>/dev/null || true
      echo "旧 Hook 已备份: ${dst}.bak"
    fi
  fi
  cp "$src" "$dst"
  chmod +x "$dst" 2>/dev/null || true
  echo "Hook 已安装: $dst"
}

cmd_status() {
  echo "== iSpeak =="
  if pgrep ispeakd > /dev/null 2>&1; then
    echo "  进程: $(pgrep ispeakd) ✓"
  else
    echo "  进程: 未运行 ✗"
  fi
  if [[ -S "$SOCK" ]]; then
    echo "  Socket: ✓"
  else
    echo "  Socket: ✗"
  fi
}

cmd_restart() {
  launchctl bootstrap "gui/$(id -u)" "$PLIST" 2>/dev/null || true
  launchctl kickstart -k "gui/$(id -u)/com.user.ispeak" >/dev/null 2>&1 || true

  local waited=0
  local timeout=8
  while (( waited < timeout )); do
    if [[ -S "$SOCK" ]]; then
      echo "ispeak: 已重启"
      return 0
    fi
    sleep 1
    ((waited++))
  done

  echo "ispeak: 重启失败（超时 ${timeout}s）" >&2
  launchctl print "gui/$(id -u)/com.user.ispeak" 2>/dev/null | sed -n '1,40p' >&2 || true
  exit 1
}

cmd_setup() {
  mkdir -p "$CONFIG_DIR"
  mkdir -p "$BIN_DIR"

  # 配置文件
  if [[ ! -f "$CONFIG_DIR/config.json" ]]; then
    cp "$SCRIPT_DIR/../configs/config.example.json" "$CONFIG_DIR/config.json"
    echo "配置文件已创建: $CONFIG_DIR/config.json"
    echo "请编辑并配置 API Key，然后运行 ispeak restart"
  else
    echo "配置文件已存在: $CONFIG_DIR/config.json"
  fi

  # Hook 脚本（给 AI 助手用的播报 hook）
  install_hook configs/hook-speak.sh "$CONFIG_DIR/hook-speak.sh"
  install_hook configs/ispeak.ts "$CONFIG_DIR/ispeak.ts"

  # 开机自启 plist
  if [[ ! -f "$PLIST" ]]; then
    sed "s|BINARY_PATH_PLACEHOLDER|$BINARY_PATH|g" "$SCRIPT_DIR/../configs/com.user.ispeak.plist" > "$PLIST"
    echo "开机自启已配置"
  else
    echo "开机自启已存在"
  fi

  # 加载服务
  launchctl bootstrap "gui/$(id -u)" "$PLIST" 2>/dev/null || true
  launchctl kickstart -k "gui/$(id -u)/com.user.ispeak" >/dev/null 2>&1 || true
  echo "服务已启动"
}

cmd_update() {
  npm install -g @xdfnet/ispeak
  cmd_restart
}

case "${1:-}" in
  status) cmd_status ;;
  restart) cmd_restart ;;
  setup) cmd_setup ;;
  update) cmd_update ;;
  version|-v|--version) echo "iSpeak $VERSION" ;;
  "")
    echo "iSpeak $VERSION"
    echo ""
    echo "用法:"
    echo "  ispeak \"文本\"                   默认音色播报"
    echo "  ispeak -s claude \"文本\"         Claude 音色播报"
    echo "  ispeak -s codex \"文本\"          Codex 音色播报"
    echo "  ispeak -s copilot \"文本\"        Copilot 音色播报"
    echo "  ispeak -s pi \"文本\"             Pi 音色播报"
    echo "  ispeak status                    服务状态"
    echo "  ispeak restart                   重启服务"
    echo "  ispeak setup                     首次配置"
    echo "  ispeak update                    升级到最新版"
    echo "  ispeak version                   版本"
    ;;
  *)
    if [[ "${1:-}" == "-s" || "${1:-}" == "--source" ]]; then
      if [[ $# -lt 3 ]]; then
        echo "ispeak: -s 需要参数，如: ispeak -s claude \"消息\"" >&2
        exit 1
      fi
      SOURCE="${2:-}"
      shift 2
    fi
    payload="$*"
    if [[ -n "$SOURCE" && "$payload" != \{source:* ]]; then
      payload="{source:${SOURCE}}${payload}"
    fi
    if [[ "${ISPEAK_CLI_PRINT_PAYLOAD:-}" == "1" ]]; then
      printf "%s" "$payload"
      exit 0
    fi
    printf "%s" "$payload" | nc -U -w5 "$SOCK" 2>/dev/null || echo "ispeak: socket 不可用" >&2
    ;;
esac
