#!/bin/bash
set -uo pipefail

source /etc/repo-update.conf 2>/dev/null || true
REPO_NAME="${REPO_NAME:-breez}"
REPO_BASE="${REPO_BASE:-/srv/repo/${REPO_NAME}}"

# Read package metadata instead of guessing from a potentially unusual name.
get_pkg_arch() {
    bsdtar -xOf "$1" .PKGINFO 2>/dev/null | awk -F ' = ' '$1 == "arch" { print $2; exit }'
}

get_pkg_field() {
    bsdtar -xOf "$1" .PKGINFO 2>/dev/null | \
        awk -F ' = ' -v field="$2" '$1 == field { print $2; exit }'
}

copy_package() {
    local package="$1"
    local destination="$2"

    cp -v -- "$package" "$destination/"
    [[ -f "${package}.sig" ]] && cp -v -- "${package}.sig" "$destination/"
}

push_packages() {
    source /etc/archrepo-publish.conf 2>/dev/null || true

    local host="${REPO_PUBLISH_HOST:-130.61.99.72}"
    local user="${REPO_PUBLISH_USER:-repo}"
    local port="${REPO_PUBLISH_PORT:-22}"
    local identity="${REPO_PUBLISH_IDENTITY:-}"
    local remote file signature basename
    local -a ssh_options

    [[ $# -gt 0 ]] || { echo "用法: repo-ctl push <pkg-file...>"; return 1; }
    [[ "${host}" =~ ^[A-Za-z0-9.-]+$ ]] || { echo "错误: REPO_PUBLISH_HOST 无效"; return 1; }
    [[ "${user}" =~ ^[A-Za-z0-9._-]+$ ]] || { echo "错误: REPO_PUBLISH_USER 无效"; return 1; }
    [[ "${port}" =~ ^[0-9]+$ ]] || { echo "错误: REPO_PUBLISH_PORT 无效"; return 1; }
    command -v ssh &>/dev/null || { echo "错误: 需要安装 openssh"; return 1; }

    if [[ -z "${identity}" && -n "${HOME:-}" && -f "${HOME}/.ssh/archrepo_publish" ]]; then
        identity="${HOME}/.ssh/archrepo_publish"
    fi

    ssh_options=(-p "${port}" -o BatchMode=yes -o StrictHostKeyChecking=accept-new)
    if [[ -n "${identity}" ]]; then
        [[ -f "${identity}" ]] || { echo "错误: SSH 私钥不存在: ${identity}"; return 1; }
        ssh_options+=(-i "${identity}" -o IdentitiesOnly=yes)
    fi
    remote="${user}@${host}"

    for file in "$@"; do
        [[ -f "${file}" && "${file}" =~ \.pkg\.tar\.(zst|xz|gz)$ ]] || {
            echo "错误: 不是有效的包文件: ${file}"
            return 1
        }
        bsdtar -tf "${file}" .PKGINFO &>/dev/null || {
            echo "错误: 包完整性检查失败: ${file}"
            return 1
        }

        basename="$(basename "$file")"
        [[ "${basename}" =~ ^[A-Za-z0-9@._+-]+\.pkg\.tar\.(zst|xz|gz)$ ]] || {
            echo "错误: 包文件名包含不支持的字符: ${basename}"
            return 1
        }

        signature="${file}.sig"
        if [[ -f "${signature}" ]]; then
            echo "上传 $(basename "$signature") ..."
            ssh "${ssh_options[@]}" "${remote}" "upload ${basename}.sig" < "$signature" || return 1
        fi

        # Upload the package last so a failed signature transfer cannot leave
        # an apparently complete unsigned package in the staging area.
        echo "上传 ${basename} ..."
        ssh "${ssh_options[@]}" "${remote}" "upload ${basename}" < "$file" || return 1
    done

    echo "发布并重建仓库索引 ..."
    ssh "${ssh_options[@]}" "${remote}" publish
}

case "${1:-}" in
    add)
        shift
        [[ $# -eq 0 ]] && { echo "用法: repo-ctl add <pkg-file...>"; exit 1; }
        result=0
        for f in "$@"; do
            if [[ -f "$f" && "$f" =~ \.pkg\.tar\.(zst|xz|gz)$ ]] && \
                    bsdtar -tf "$f" .PKGINFO &>/dev/null; then
                pkg_arch=$(get_pkg_arch "$f")
                if [[ "$pkg_arch" == "any" ]]; then
                    copied=0
                    for arch_dir in "${REPO_BASE}"/*/; do
                        [[ -d "${arch_dir}/incoming" ]] || continue
                        copy_package "$f" "${arch_dir}/incoming"
                        copied=1
                    done
                    if [[ ${copied} -eq 1 ]]; then
                        echo "✓ 已添加 $(basename "$f") (any) 到所有架构"
                    else
                        echo "✗ 没有可用的架构目录"
                        result=1
                    fi
                elif [[ -d "${REPO_BASE}/${pkg_arch}/incoming" ]]; then
                    copy_package "$f" "${REPO_BASE}/${pkg_arch}/incoming"
                    echo "✓ 已添加 $(basename "$f") 到 ${pkg_arch}"
                else
                    echo "✗ 未知架构 ${pkg_arch}，跳过: $(basename "$f")"
                    result=1
                fi
            else
                echo "✗ 跳过无效的包: $f"
                result=1
            fi
        done
        echo "提示: 运行 repo-ctl update 立即触发，或等待定时器自动处理"
        exit "${result}"
        ;;
    remove)
        shift
        [[ $# -eq 0 ]] && { echo "用法: repo-ctl remove <pkg-name> [arch]"; exit 1; }
        name="$1"
        target_arch="${2:-all}"
        result=0
        for arch_dir in "${REPO_BASE}"/*/; do
            arch=$(basename "$arch_dir")
            [[ -d "${arch_dir}/pool" ]] || continue
            [[ "$target_arch" != "all" && "$arch" != "$target_arch" ]] && continue

            shopt -s nullglob
            packages=("${arch_dir}/pool"/*.pkg.tar.{zst,xz,gz})
            shopt -u nullglob
            matched=()
            for package in "${packages[@]}"; do
                [[ "$(get_pkg_field "$package" pkgname)" == "$name" ]] && matched+=("$package")
            done

            if [[ ${#matched[@]} -eq 0 ]]; then
                echo "  [${arch}] 未找到: $name"
                continue
            fi

            cd "${arch_dir}" || exit 1
            if ! repo-remove "${REPO_NAME}.db.tar.gz" "$name"; then
                echo "✗ [${arch}] 数据库更新失败，未删除包文件: $name"
                result=1
                continue
            fi

            for package in "${matched[@]}"; do
                package_basename="$(basename "$package")"
                rm -f -- "$package" "${package}.sig" \
                    "${arch_dir}/${package_basename}" "${arch_dir}/${package_basename}.sig"
            done
            echo "✓ [${arch}] 已移除: $name"
        done
        exit "${result}"
        ;;
    list)
        found=0
        for arch_dir in "${REPO_BASE}"/*/; do
            arch=$(basename "$arch_dir")
            [[ -d "${arch_dir}/pool" ]] || continue
            shopt -s nullglob
            packages=("${arch_dir}/pool"/*.pkg.tar.{zst,xz,gz})
            shopt -u nullglob
            for package in "${packages[@]}"; do
                pkg_name="$(get_pkg_field "$package" pkgname)"
                pkg_version="$(get_pkg_field "$package" pkgver)"
                printf '[%s] %s %s\n' "$arch" "$pkg_name" "$pkg_version"
                found=1
            done
        done
        [[ ${found} -eq 1 ]] || echo "仓库为空或未初始化"
        ;;
    update)
        echo "手动触发仓库更新..."
        if [[ ${EUID} -eq 0 ]]; then
            systemctl start repo-update.service
        else
            sudo systemctl start repo-update.service
        fi
        echo "✓ 完成，查看日志: repo-ctl log"
        ;;
    push|publish)
        shift
        push_packages "$@"
        ;;
    status)
        systemctl status repo-update.timer --no-pager 2>/dev/null || true
        echo ""
        systemctl list-timers repo-update.timer --no-pager 2>/dev/null || true
        ;;
    log)
        tail -50 /var/log/repo-update.log 2>/dev/null || echo "暂无日志"
        ;;
    info)
        echo "名称:       ${REPO_NAME}"
        echo "基础目录:   ${REPO_BASE}"
        echo ""
        for arch_dir in "${REPO_BASE}"/*/; do
            arch=$(basename "$arch_dir")
            [[ -d "${arch_dir}/pool" ]] || continue
            pkg_count=$(find "${arch_dir}/pool" -name '*.pkg.tar.*' ! -name '*.sig' 2>/dev/null | wc -l)
            incoming_count=$(find "${arch_dir}/incoming" -name '*.pkg.tar.*' 2>/dev/null | wc -l)
            pool_size=$(du -sh "${arch_dir}/pool" 2>/dev/null | cut -f1)
            echo "[${arch}] ${pkg_count} 个包, ${incoming_count} 个待处理, 大小 ${pool_size}"
        done
        ;;
    *)
        echo "用法: repo-ctl <add|remove|list|update|push|status|log|info>"
        echo ""
        echo "  add <pkg-file...>          添加本地包（any 包分发到所有架构）"
        echo "  remove <name> [arch]       删除包（可指定架构，默认全部）"
        echo "  list                       列出所有包"
        echo "  update                     立即触发更新"
        echo "  push <pkg-file...>         通过受限 SSH 密钥上传并立即发布"
        echo "  status                     定时器状态"
        echo "  log                        更新日志"
        echo "  info                       仓库概览"
        ;;
esac
