#!/bin/bash
# GitLink CLI 一键安装脚本（改进版）
# 自动检测平台，下载预编译二进制，安装 skills
# 用法: curl -sSL https://www.gitlink.org.cn/Gitlink/gitlink-cli/raw/master/install.sh | bash
# 支持: VERSION=0.1.0 INSTALL_DIR=$HOME/.local/bin bash install.sh

set -e

REPO_OWNER="Gitlink"
REPO_NAME="gitlink-cli"
BINARY_NAME="gitlink-cli"
API_BASE="https://www.gitlink.org.cn"
INSTALL_DIR="${INSTALL_DIR:-auto}"
SKILLS_DIR="${HOME}/.gitlink/skills"
VERSION="${VERSION:-latest}"
MAX_ATTEMPTS=3
DEBUG="${DEBUG:-false}"

# ---------- 颜色输出 ----------
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
BLUE='\033[0;34m'
NC='\033[0m'

info()  { echo -e "${GREEN}[INFO]${NC}  $*"; }
warn()  { echo -e "${YELLOW}[WARN]${NC}  $*"; }
error() { echo -e "${RED}[ERROR]${NC} $*"; }
step()  { echo -e "${CYAN}[STEP]${NC}  $*"; }
debug() { [[ "${DEBUG}" == "true" ]] && echo -e "${BLUE}[DEBUG]${NC} $*"; }

# ---------- 环境检测 ----------
check_environment() {
    step "检查安装环境..."

    # 检查必需命令
    local required_commands=("curl" "tar")
    for cmd in "${required_commands[@]}"; do
        if ! command -v "$cmd" >/dev/null 2>&1; then
            error "缺少必需命令: $cmd"
            error "请安装后再试:"
            error "  Ubuntu/Debian: sudo apt-get install $cmd"
            error "  CentOS/RHEL: sudo yum install $cmd"
            error "  macOS: brew install $cmd"
            exit 1
        fi
    done
    debug "必需命令检查通过"

    # 检查磁盘空间（至少50MB）
    local available_space
    available_space=$(df -m "$HOME" | tail -1 | awk '{print $4}')
    if [ "$available_space" -lt 50 ]; then
        error "磁盘空间不足（需要至少50MB，可用: ${available_space}MB）"
        exit 1
    fi
    debug "磁盘空间检查通过: ${available_space}MB"

    # 检查网络连接
    if ! curl -sSL --connect-timeout 5 "${API_BASE}" >/dev/null 2>&1; then
        error "无法连接到 GitLink 服务器: ${API_BASE}"
        error "请检查网络连接"
        exit 1
    fi
    debug "网络连接检查通过"

    info "环境检查通过"
}

# ---------- 智能权限处理 ----------
select_install_dir() {
    local dirs=("$HOME/.local/bin" "$HOME/bin" "/usr/local/bin")
    local selected_dir=""

    if [ "${INSTALL_DIR}" != "auto" ]; then
        echo "${INSTALL_DIR}"
        return
    fi

    step "选择安装目录..."

    # 优先级：用户目录 > 系统目录
    for dir in "${dirs[@]}"; do
        if [ -w "$dir" ] 2>/dev/null || mkdir -p "$dir" 2>/dev/null; then
            selected_dir="$dir"
            info "选择用户目录: $selected_dir"
            break
        fi
    done

    # 如果用户目录都不可写，尝试系统目录
    if [ -z "$selected_dir" ]; then
        warn "无法写入用户目录，将使用系统目录（需要sudo权限）"
        selected_dir="/usr/local/bin"
    fi

    echo "$selected_dir"
}

# ---------- 下载重试机制 ----------
download_with_retry() {
    local url="$1"
    local output="$2"
    local attempt=1

    while [ $attempt -le $MAX_ATTEMPTS ]; do
        step "下载 (尝试 $attempt/$MAX_ATTEMPTS): $(basename "$url")"

        if curl -sSL --connect-timeout 10 --max-time 120 --progress-bar "$url" -o "$output" 2>&1; then
            if [ -s "$output" ]; then
                info "下载成功: $(basename "$output") ($(du -h "$output" | cut -f1))"
                return 0
            else
                warn "下载文件为空"
            fi
        else
            warn "下载失败"
        fi

        if [ $attempt -lt $MAX_ATTEMPTS ]; then
            local wait_time=$((attempt * 2))
            warn "等待 ${wait_time}s 后重试..."
            sleep $wait_time
        fi

        attempt=$((attempt + 1))
    done

    error "下载失败，已尝试 $MAX_ATTEMPTS 次"
    error "URL: $url"
    error "请检查网络连接或手动下载"
    return 1
}

# ---------- 平台检测 ----------
detect_platform() {
    local os arch
    case "$(uname -s)" in
        Linux)  os="linux" ;;
        Darwin) os="darwin" ;;
        MINGW*|MSYS*|CYGWIN*) os="windows" ;;
        *) error "不支持的操作系统: $(uname -s)"; exit 1 ;;
    esac
    case "$(uname -m)" in
        x86_64|amd64) arch="amd64" ;;
        aarch64|arm64) arch="arm64" ;;
        *) error "不支持的架构: $(uname -m)"; exit 1 ;;
    esac
    echo "${os}/${arch}"
}

# ---------- 获取最新版本 ----------
fetch_latest_version() {
    local releases_url="${API_BASE}/api/${REPO_OWNER}/${REPO_NAME}/releases.json"

    info "获取最新版本..."

    local releases
    releases=$(curl -sSL --connect-timeout 10 --max-time 30 "${releases_url}" 2>/dev/null || true)

    if [ -z "$releases" ]; then
        error "无法获取发布列表: ${releases_url}"
        exit 1
    fi

    # 尝试解析第一个 release 的 tag_name
    local tag
    tag=$(echo "$releases" | grep -o '"tag_name"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"\([^"]*\)"$/\1/')

    if [ -z "$tag" ]; then
        # 备选：尝试直接匹配数组第一个元素的 tag_name
        tag=$(echo "$releases" | grep -oP '"tag_name"\s*:\s*"\K[^"]+' | head -1)
    fi

    echo "${tag:-v0.1.0}"
}

# ---------- 显示已安装版本 ----------
show_installed_version() {
    if command -v "${BINARY_NAME}" >/dev/null 2>&1; then
        "${BINARY_NAME}" version 2>/dev/null || echo "未知版本"
    elif [ -x "${INSTALL_DIR}/${BINARY_NAME}" ]; then
        "${INSTALL_DIR}/${BINARY_NAME}" version 2>/dev/null || echo "未知版本"
    else
        echo "未安装"
    fi
}

# ---------- 列出可用版本 ----------
list_versions() {
    step "查询可用版本..."
    local releases_url="${API_BASE}/api/${REPO_OWNER}/${REPO_NAME}/releases.json"
    curl -sSL "$releases_url" | grep -o '"tag_name"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*"\([^"]*\)"$/\1/' | head -10
}

# ---------- 回滚功能 ----------
rollback_version() {
    local target_version="$1"

    if [ -z "$target_version" ]; then
        error "请指定要回滚到的版本"
        exit 1
    fi

    step "回滚到版本: ${target_version}"

    # 重新安装指定版本
    VERSION="$target_version"
    main
}

# ---------- 卸载功能 ----------
uninstall() {
    step "卸载 ${BINARY_NAME}..."

    # 删除二进制
    if [ -f "${INSTALL_DIR}/${BINARY_NAME}" ]; then
        if [ -w "${INSTALL_DIR}" ]; then
            rm -f "${INSTALL_DIR}/${BINARY_NAME}"
            info "已删除: ${INSTALL_DIR}/${BINARY_NAME}"
        else
            sudo rm -f "${INSTALL_DIR}/${BINARY_NAME}"
            info "已删除: ${INSTALL_DIR}/${BINARY_NAME} (使用sudo)"
        fi
    fi

    # 删除skills
    if [ -d "${SKILLS_DIR}" ]; then
        rm -rf "${SKILLS_DIR}"
        info "已删除: ${SKILLS_DIR}"
    fi

    # 删除配置（可选）
    echo -n "是否删除配置文件? [y/N] "
    read -r response
    if [[ "$response" =~ ^[Yy]$ ]]; then
        rm -rf "$HOME/.config/gitlink-cli"
        rm -rf "$HOME/.gitlink"
        info "已删除配置文件"
    fi

    info "卸载完成"
    exit 0
}

# ---------- 下载二进制 ----------
download_binary() {
    local platform="$1"
    local version="$2"
    local os="${platform%/*}"
    local arch="${platform#*/}"
    local archive_name="${BINARY_NAME}_${version}_${os}_${arch}.tar.gz"
    local download_url="${API_BASE}/api/${REPO_OWNER}/${REPO_NAME}/releases/${version}/assets/${archive_name}"

    info "下载: ${archive_name}"
    debug "URL: ${download_url}"

    local tmpdir
    tmpdir="$(mktemp -d)"
    trap "rm -rf ${tmpdir}" EXIT

    if ! download_with_retry "${download_url}" "${tmpdir}/${archive_name}"; then
        error "请确认以下版本已发布: ${version}"
        error "发布页: ${API_BASE}/${REPO_OWNER}/${REPO_NAME}/releases"
        exit 1
    fi

    step "解压..."
    tar -xzf "${tmpdir}/${archive_name}" -C "${tmpdir}"

    local binary_path="${tmpdir}/${BINARY_NAME}"
    if [ ! -f "${binary_path}" ]; then
        # 可能在子目录中
        binary_path=$(find "${tmpdir}" -name "${BINARY_NAME}" -type f 2>/dev/null | head -1)
    fi

    if [ ! -f "${binary_path}" ]; then
        error "解压后未找到二进制文件"
        exit 1
    fi

    chmod +x "${binary_path}"

    # ---------- 安装 ----------
    step "安装到 ${INSTALL_DIR}/${BINARY_NAME}"

    if [ ! -w "${INSTALL_DIR}" ]; then
        warn "需要管理员权限写入 ${INSTALL_DIR}"
        sudo mkdir -p "${INSTALL_DIR}"
        sudo mv "${binary_path}" "${INSTALL_DIR}/${BINARY_NAME}"
        sudo chmod +x "${INSTALL_DIR}/${BINARY_NAME}"
    else
        mkdir -p "${INSTALL_DIR}"
        mv "${binary_path}" "${INSTALL_DIR}/${BINARY_NAME}"
    fi

    info "二进制: ${INSTALL_DIR}/${BINARY_NAME}"
}

# ---------- 安装 skills ----------
install_skills() {
    local version="$1"
    step "安装 skills..."

    mkdir -p "${SKILLS_DIR}"

    local skills_url="${API_BASE}/api/${REPO_OWNER}/${REPO_NAME}/releases/${version}/assets/${BINARY_NAME}_${version}_skills.tar.gz"
    local tmpdir
    tmpdir="$(mktemp -d)"

    if download_with_retry "${skills_url}" "${tmpdir}/skills.tar.gz" 2>/dev/null; then
        tar -xzf "${tmpdir}/skills.tar.gz" -C "${SKILLS_DIR}" 2>/dev/null || true
        info "Skills 安装到: ${SKILLS_DIR}"
    else
        warn "Skills 包不可用（可稍后通过 gitlink-cli-install-skills 安装）"
    fi

    rm -rf "${tmpdir}"
}

# ---------- 验证安装 ----------
verify() {
    step "验证安装..."
    if command -v "${BINARY_NAME}" >/dev/null 2>&1; then
        info "安装成功! $("${BINARY_NAME}" version 2>/dev/null || echo "${BINARY_NAME}")"
    elif [ -x "${INSTALL_DIR}/${BINARY_NAME}" ]; then
        info "安装成功! $("${INSTALL_DIR}/${BINARY_NAME}" version 2>/dev/null || echo "${INSTALL_DIR}/${BINARY_NAME}")"
        warn "请将 ${INSTALL_DIR} 添加到 PATH: export PATH=${INSTALL_DIR}:\$PATH"
    else
        error "安装验证失败"
        exit 1
    fi
}

# ---------- 显示帮助 ----------
show_help() {
    cat << EOF
GitLink CLI 安装脚本

用法:
  curl -sSL https://www.gitlink.org.cn/Gitlink/gitlink-cli/raw/master/install.sh | bash [选项]

选项:
  VERSION=0.1.0        指定版本
  INSTALL_DIR=/path     指定安装目录
  DEBUG=true           显示调试信息

环境变量:
  INSTALL_DIR           安装目录（默认: auto，自动选择）
  VERSION               版本（默认: latest）

命令:
  list                 列出可用版本
  uninstall            卸载
  rollback VERSION     回滚到指定版本

示例:
  # 安装最新版本
  curl -sSL https://www.gitlink.org.cn/Gitlink/gitlink-cli/raw/master/install.sh | bash

  # 安装指定版本
  VERSION=0.1.0 curl -sSL https://www.gitlink.org.cn/Gitlink/gitlink-cli/raw/master/install.sh | bash

  # 安装到用户目录
  INSTALL_DIR=$HOME/.local/bin curl -sSL https://www.gitlink.org.cn/Gitlink/gitlink-cli/raw/master/install.sh | bash

  # 列出可用版本
  curl -sSL https://www.gitlink.org.cn/Gitlink/gitlink-cli/raw/master/install.sh | bash -s -- list

  # 卸载
  curl -sSL https://www.gitlink.org.cn/Gitlink/gitlink-cli/raw/master/install.sh | bash -s -- uninstall
EOF
}

# ---------- main ----------
main() {
    echo ""
    echo "  ╔══════════════════════════════════════╗"
    echo "  ║       GitLink CLI 一键安装           ║"
    echo "  ╚══════════════════════════════════════╝"
    echo ""

    # 处理命令行参数
    case "${1:-}" in
        list)
            list_versions
            exit 0
            ;;
        uninstall)
            INSTALL_DIR="${INSTALL_DIR:-$(select_install_dir)}"
            uninstall
            ;;
        rollback)
            rollback_version "$2"
            ;;
        help|--help|-h)
            show_help
            exit 0
            ;;
    esac

    # 环境检测
    check_environment

    # 选择安装目录
    INSTALL_DIR=$(select_install_dir)
    export INSTALL_DIR

    local platform
    platform=$(detect_platform)
    info "检测到平台: ${platform}"

    local version
    if [ "${VERSION}" = "latest" ]; then
        version=$(fetch_latest_version)
        info "最新版本: ${version}"
    else
        version="${VERSION}"
        info "指定版本: ${version}"
    fi

    download_binary "${platform}" "${version}"
    install_skills "${version}"
    verify

    echo ""
    info "快速开始:"
    info "  gitlink-cli auth login   # 登录账号"
    info "  gitlink-cli --help        # 查看所有命令"
    info "  gitlink-cli version       # 查看版本信息"
    echo ""
}

main "$@"
