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

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'
STATE_FILE='.install-state.json'
FORCE=0
RELEASE=0
UNINSTALL=0
REPO="yonggandewo12/free-code"

info() { printf "%b\n" "${CYAN}[INFO]${NC} $1"; }
ok() { printf "%b\n" "${GREEN}[OK]  ${NC} $1"; }
warn() { printf "%b\n" "${YELLOW}[WARN]${NC} $1"; }
fail() { printf "%b\n" "${RED}[ERR] ${NC} $1"; exit 1; }
command_exists() { command -v "$1" >/dev/null 2>&1; }
ensure_file_from_template() {
  local target="$1"
  local template="$2"
  local dir
  dir="$(dirname "$target")"
  mkdir -p "$dir"
  if [ ! -f "$target" ]; then
    cp "$template" "$target"
    ok "已创建默认配置: $target"
  fi
}

hash_file() {
  local path="$1"
  [ -f "$path" ] || return 0
  shasum -a 256 "$path" | awk '{print $1}'
}

read_state_value() {
  local key="$1"
  [ -f "$STATE_FILE" ] || return 0
  python3 - "$STATE_FILE" "$key" <<'PY'
import json, sys
try:
    with open(sys.argv[1], 'r', encoding='utf-8') as f:
        data = json.load(f)
    print(data.get(sys.argv[2], ''))
except Exception:
    print('')
PY
}

write_state() {
  python3 - "$STATE_FILE" "$1" "$2" <<'PY'
import json, sys
with open(sys.argv[1], 'w', encoding='utf-8') as f:
    json.dump({'dependencyHash': sys.argv[2], 'buildHash': sys.argv[3]}, f)
PY
}

compute_dependency_hash() {
  { hash_file 'package.json'; hash_file 'bun.lock'; hash_file 'bun.lockb'; } | shasum -a 256 | awk '{print $1}'
}

compute_build_hash() {
  {
    hash_file 'package.json'
    hash_file 'bun.lock'
    hash_file 'bun.lockb'
    hash_file 'scripts/build.ts'
    if [ -d 'src' ]; then
      while IFS= read -r file; do
        hash_file "$file"
      done < <(find 'src' -type f | LC_ALL=C sort)
    fi
  } | shasum -a 256 | awk '{print $1}'
}

SCRIPT_DIR="$(cd -- "$(dirname -- "$0")" && pwd)"
cd "$SCRIPT_DIR"

DEFAULT_SETTINGS_TEMPLATE="$SCRIPT_DIR/assets/default-settings.template.json"
DEFAULT_CLAUDE_TEMPLATE="$SCRIPT_DIR/assets/default-claude.template.json"
CLAUDE_CONFIG_DIR="${CLAUDE_CONFIG_DIR:-$HOME/.claude}"
SETTINGS_JSON_PATH="$CLAUDE_CONFIG_DIR/settings.json"
CLAUDE_JSON_PATH="${CLAUDE_CONFIG_DIR%/.claude}/.claude.json"

for arg in "$@"; do
  case "$arg" in
    --force)
      FORCE=1
      ;;
    --release)
      RELEASE=1
      ;;
    --uninstall)
      UNINSTALL=1
      ;;
    *)
      fail "不支持的参数: $arg (可用: --force, --release, --uninstall)"
      ;;
  esac
done

# Auto-detect: if no package.json in script dir, assume release mode
SCRIPT_DIR="$(cd -- "$(dirname -- "$0")" && pwd)"
if [ "$RELEASE" -eq 0 ] && [ "$UNINSTALL" -eq 0 ] && [ ! -f "$SCRIPT_DIR/package.json" ]; then
  RELEASE=1
  info "未检测到源码目录，自动切换为 --release 模式"
fi

case "$(uname -s)" in
  Darwin*)
    info "检测到 macOS"
    INSTALL_BIN_DIR="$HOME/.local/bin"
    PATH_HINT='export PATH="$HOME/.local/bin:$PATH"'
    ;;
  Linux*)
    info "检测到 Linux"
    INSTALL_BIN_DIR="$HOME/.local/bin"
    PATH_HINT='export PATH="$HOME/.local/bin:$PATH"'
    ;;
  MINGW*|MSYS*|CYGWIN*)
    info "检测到 Windows (Git Bash / MSYS2)"
    INSTALL_BIN_DIR="$HOME/.local/bin"
    PATH_HINT='export PATH="$HOME/.local/bin:$PATH"'
    ;;
  *)
    fail "不支持的操作系统"
    ;;
esac

mkdir -p "$INSTALL_BIN_DIR"

# ── Uninstall mode ──
if [ "$UNINSTALL" -eq 1 ]; then
  info "卸载 freecode..."

  # Remove binary and shim scripts
  for name in freecode free-code claudecode freecode-bin; do
    target="$INSTALL_BIN_DIR/$name"
    if [ -f "$target" ]; then
      rm -f "$target"
      ok "已删除: $target"
    fi
  done

  # Remove PATH entry from shell config
  SHELL_RC=""
  if [ -n "${ZSH_VERSION:-}" ] || [ "${SHELL:-}" = */zsh ]; then
    SHELL_RC="$HOME/.zshrc"
  elif [ -n "${BASH_VERSION:-}" ] || [ "${SHELL:-}" = */bash ]; then
    SHELL_RC="$HOME/.bashrc"
  fi
  [ -z "$SHELL_RC" ] && [ -f "$HOME/.zshrc" ] && SHELL_RC="$HOME/.zshrc"
  [ -z "$SHELL_RC" ] && [ -f "$HOME/.bashrc" ] && SHELL_RC="$HOME/.bashrc"
  [ -z "$SHELL_RC" ] && SHELL_RC="$HOME/.bashrc"

  if [ -f "$SHELL_RC" ] && grep -q "$INSTALL_BIN_DIR" "$SHELL_RC" 2>/dev/null; then
    sed -i.bak "\|^export PATH=\"${INSTALL_BIN_DIR}:\$PATH\"$|d" "$SHELL_RC" && rm -f "${SHELL_RC}.bak"
    ok "已从 $SHELL_RC 移除 PATH 条目"
  fi

  printf "\n%b\n\n" "${GREEN}=== 卸载成功 ===${NC}"
  printf "已移除命令: freecode, free-code, claudecode\n"
  printf "如需重新安装:\n"
  printf "  curl -fsSL https://github.com/yonggandewo12/free-code/releases/latest/download/install.sh | bash\n\n"
  exit 0
fi

# ── Release mode: download pre-built binary from GitHub Releases ──
if [ "$RELEASE" -eq 1 ]; then
  OS_LOWER="$(uname -s | tr '[:upper:]' '[:lower:]')"
  ARCH="$(uname -m)"

  case "$OS_LOWER" in
    darwin) PLATFORM="darwin" ;;
    linux)  PLATFORM="linux" ;;
    mingw*|msys*|cygwin*) PLATFORM="win32" ;;
    *) fail "不支持的平台: $OS_LOWER" ;;
  esac

  case "$ARCH" in
    x86_64|amd64)  ARCH_SUFFIX="x64" ;;
    arm64|aarch64) ARCH_SUFFIX="arm64" ;;
    *) fail "不支持的架构: $ARCH" ;;
  esac

  if [ "$PLATFORM" = "win32" ]; then
    REMOTE_NAME="cli-win32-x64.exe"
  else
    REMOTE_NAME="cli-${PLATFORM}-${ARCH_SUFFIX}"
  fi

  DOWNLOAD_URL="https://github.com/${REPO}/releases/latest/download/${REMOTE_NAME}"
  TARGET="$INSTALL_BIN_DIR/freecode-bin"

  info "下载预构建二进制 (${PLATFORM}-${ARCH_SUFFIX})..."
  if command_exists curl; then
    curl -fsSL "$DOWNLOAD_URL" -o "$TARGET"
  elif command_exists wget; then
    wget -qO "$TARGET" "$DOWNLOAD_URL"
  else
    fail "curl 和 wget 均未安装，无法下载"
  fi
  chmod +x "$TARGET"
  ok "二进制已下载: $TARGET"

  # Download and use template files from GitHub Release
  TMP_DIR="$(mktemp -d)"
  trap 'rm -rf "$TMP_DIR"' EXIT

  download_file() {
    local url="$1" local_path="$2"
    if command_exists curl; then
      curl -fsSL "$url" -o "$local_path"
    elif command_exists wget; then
      wget -qO "$local_path" "$url"
    else
      return 1
    fi
  }

  TEMPLATE_BASE="https://github.com/${REPO}/releases/latest/download"
  SETTINGS_TEMPLATE="$TMP_DIR/default-settings.template.json"
  CLAUDE_TEMPLATE="$TMP_DIR/default-claude.template.json"

  info "下载配置模板..."
  if download_file "$TEMPLATE_BASE/default-settings.template.json" "$SETTINGS_TEMPLATE" && \
     download_file "$TEMPLATE_BASE/default-claude.template.json" "$CLAUDE_TEMPLATE"; then
    ensure_file_from_template "$SETTINGS_JSON_PATH" "$SETTINGS_TEMPLATE"
    ensure_file_from_template "$CLAUDE_JSON_PATH" "$CLAUDE_TEMPLATE"
  else
    warn "无法下载配置模板，跳过默认配置创建"
  fi

  info "创建全局命令..."
  for name in freecode free-code claudecode; do
    target="$INSTALL_BIN_DIR/$name"
    content=$(cat <<EOF
#!/usr/bin/env bash
exec "$INSTALL_BIN_DIR/freecode-bin" "\$@"
EOF
)
    if [ "$FORCE" -eq 0 ] && [ -f "$target" ] && [ "$(cat "$target")" = "$content" ]; then
      continue
    fi
    printf '%s\n' "$content" > "$target"
    chmod +x "$target"
  done
  ok "命令已安装: freecode, free-code, claudecode"

  # Auto-add to PATH in shell config
  SHELL_RC=""
  if [ -n "${ZSH_VERSION:-}" ] || [ "${SHELL:-}" = */zsh ]; then
    SHELL_RC="$HOME/.zshrc"
  elif [ -n "${BASH_VERSION:-}" ] || [ "${SHELL:-}" = */bash ]; then
    SHELL_RC="$HOME/.bashrc"
  fi
  [ -z "$SHELL_RC" ] && [ -f "$HOME/.zshrc" ] && SHELL_RC="$HOME/.zshrc"
  [ -z "$SHELL_RC" ] && [ -f "$HOME/.bashrc" ] && SHELL_RC="$HOME/.bashrc"
  [ -z "$SHELL_RC" ] && SHELL_RC="$HOME/.bashrc"

  if [ -f "$SHELL_RC" ] && ! grep -q "$INSTALL_BIN_DIR" "$SHELL_RC" 2>/dev/null; then
    printf '\nexport PATH="%s:$PATH"\n' "$INSTALL_BIN_DIR" >> "$SHELL_RC"
    ok "已将 $INSTALL_BIN_DIR 写入 $SHELL_RC"
  fi

  export PATH="$INSTALL_BIN_DIR:$PATH"

  printf "\n%b\n\n" "${GREEN}=== 安装成功 (release) ===${NC}"
  printf "新开终端后即可运行:\n"
  printf "  freecode\n"
  printf "  # 或\n"
  printf "  free-code\n"
  printf "  # 或\n"
  printf "  claudecode\n\n"
  exit 0
fi

# ── Source build mode ──

ensure_file_from_template "$SETTINGS_JSON_PATH" "$DEFAULT_SETTINGS_TEMPLATE"
ensure_file_from_template "$CLAUDE_JSON_PATH" "$DEFAULT_CLAUDE_TEMPLATE"

if ! command_exists git; then
  fail "git 未安装。请先安装 git: https://git-scm.com"
fi
ok "git 已安装: $(git --version 2>/dev/null | head -1)"

if ! command_exists bun; then
  warn "bun 未安装，正在安装..."
  if command_exists curl; then
    curl -fsSL https://bun.sh/install | bash
  elif command_exists wget; then
    wget -qO- https://bun.sh/install | bash
  else
    fail "curl 和 wget 均未安装，无法下载 bun"
  fi
  export PATH="$HOME/.bun/bin:$PATH"
fi

command_exists bun || fail "bun 安装失败，请手动安装: https://bun.sh"
ok "bun 已安装: v$(bun --version 2>/dev/null)"

DEPENDENCY_HASH="$(compute_dependency_hash)"
BUILD_HASH="$(compute_build_hash)"
PREV_DEPENDENCY_HASH="$(read_state_value dependencyHash)"
PREV_BUILD_HASH="$(read_state_value buildHash)"

info "安装依赖..."
if [ "$FORCE" -eq 0 ] && [ "$DEPENDENCY_HASH" = "$PREV_DEPENDENCY_HASH" ] && [ -d 'node_modules' ]; then
  ok "依赖未变化，跳过安装"
else
  if [ -f "bun.lock" ] || [ -f "bun.lockb" ]; then
    bun install --frozen-lockfile
  else
    bun install
  fi
  ok "依赖安装完成"
fi

info "编译项目 (build:dev:full)..."
if [ "$FORCE" -eq 0 ] && [ "$BUILD_HASH" = "$PREV_BUILD_HASH" ] && [ -f 'cli-dev' ]; then
  ok "源码未变化，跳过编译"
else
  bun run build:dev:full
  ok "编译完成"
fi

info "创建全局命令..."
for name in freecode free-code claudecode; do
  target="$INSTALL_BIN_DIR/$name"
  content=$(cat <<EOF
#!/usr/bin/env bash
exec "$SCRIPT_DIR/cli-dev" "\$@"
EOF
)
  if [ "$FORCE" -eq 0 ] && [ -f "$target" ] && [ "$(cat "$target")" = "$content" ]; then
    continue
  fi
  printf '%s\n' "$content" > "$target"
  chmod +x "$target"
done
ok "命令已安装: freecode, free-code, claudecode"

write_state "$DEPENDENCY_HASH" "$BUILD_HASH"

printf "\n%b\n\n" "${GREEN}=== 安装成功 ===${NC}"
printf "运行以下命令启动:\n"
printf "  %s  # 或添加到 ~/.bashrc / ~/.zshrc\n" "$PATH_HINT"
printf "  freecode\n"
printf "  # 或\n"
printf "  free-code\n"
printf "  # 或\n"
printf "  claudecode\n\n"

if [ -n "${PSModulePath:-}" ]; then
  warn "检测到 Windows PowerShell，请优先使用 install.ps1"
fi
