#!/usr/bin/env bash
# Devin (formerly Windsurf) Editor ebuild updater for nbdy_overlay
# Checks the vendor apt repository for new versions and updates ebuild + manifest.

set -euo pipefail

# Configuration
OVERLAY_DIR="$(dirname "$(dirname "$(realpath "$0")")")"
EBUILD_DIR="${OVERLAY_DIR}/app-editors/devin-desktop-bin"
PKG_NAME="devin-desktop-bin"
APT_BASE="https://windsurf-stable.codeiumdata.com/wVxQEIWkwPUEAGf3/apt"
RELEASES_URL="${APT_BASE}/dists/stable/main/binary-amd64/Packages"

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_success() { echo -e "${GREEN}[OK]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1" >&2; }

# Cleanup on failure: remove any newly created ebuild
CLEANUP_FILES=()
cleanup_on_exit() {
    local exit_code=$?
    if (( exit_code != 0 )) && (( ${#CLEANUP_FILES[@]} > 0 )); then
        log_warn "Script failed (exit $exit_code), cleaning up..."
        for f in "${CLEANUP_FILES[@]}"; do
            [[ -f "$f" ]] && rm -v "$f"
        done
    fi
}
trap cleanup_on_exit EXIT

# Get current installed version from ebuild filename
get_current_version() {
    local ebuild
    ebuild=$(ls "${EBUILD_DIR}"/*.ebuild 2>/dev/null | sort -V | tail -1)
    if [[ -z "$ebuild" ]]; then
        echo ""
        return
    fi
    basename "$ebuild" .ebuild | sed "s/${PKG_NAME}-//"
}

# Fetch latest version from the vendor apt repository (devin-desktop stanza)
get_latest_version() {
    local packages_data
    packages_data=$(curl -sfL "$RELEASES_URL" 2>/dev/null) || {
        log_error "Failed to fetch version info from $RELEASES_URL"
        return 1
    }

    # Parse the 'devin-desktop' package stanza, strip Debian revision (-NNNN)
    local version
    version=$(echo "$packages_data" | awk '
        /^Package: devin-desktop$/ { f=1; next }
        f && /^Version:/ { sub(/^Version:[ \t]*/, ""); sub(/-[0-9]+$/, ""); print; exit }
    ')

    if [[ -z "$version" ]]; then
        log_error "Could not parse devin-desktop version from Packages file"
        return 1
    fi

    echo "$version"
}

# Create new ebuild for version
create_ebuild() {
    local new_version="$1"
    local old_ebuild new_ebuild

    old_ebuild=$(ls "${EBUILD_DIR}"/*.ebuild 2>/dev/null | sort -V | tail -1)
    new_ebuild="${EBUILD_DIR}/${PKG_NAME}-${new_version}.ebuild"

    if [[ -z "$old_ebuild" ]]; then
        log_error "No existing ebuild found to copy"
        return 1
    fi

    if [[ -f "$new_ebuild" ]]; then
        log_info "Ebuild ${PKG_NAME}-${new_version}.ebuild already exists"
        return 0
    fi

    # Copy ebuild (version is derived from filename, no changes needed)
    cp "$old_ebuild" "$new_ebuild"
    CLEANUP_FILES+=("$new_ebuild")
    log_success "Created: ${PKG_NAME}-${new_version}.ebuild"
}

# Generate manifest by downloading distfile and computing checksums
generate_manifest() {
    log_info "Generating Manifest..."

    local ebuild
    ebuild=$(ls "${EBUILD_DIR}"/*.ebuild 2>/dev/null | sort -V | tail -1)

    if [[ -z "$ebuild" ]]; then
        log_error "No ebuild found"
        return 1
    fi

    # Extract version from ebuild filename
    local ebuild_name pv src_url distfile
    ebuild_name=$(basename "$ebuild" .ebuild)
    pv="${ebuild_name#${PKG_NAME}-}"
    src_url="${APT_BASE}/pool/main/d/devin-desktop/Devin-linux-x64-${pv}.deb"
    distfile="Devin-linux-x64-${pv}.deb"

    log_info "Downloading ${distfile} for checksum..."
    local tmpfile
    tmpfile=$(mktemp)
    if ! curl -sfL -o "$tmpfile" "$src_url"; then
        log_error "Failed to download ${src_url}"
        rm -f "$tmpfile"
        return 1
    fi

    local filesize blake2b sha512
    filesize=$(wc -c < "$tmpfile")
    blake2b=$(b2sum "$tmpfile" | awk '{print $1}')
    sha512=$(sha512sum "$tmpfile" | awk '{print $1}')
    rm -f "$tmpfile"

    echo "DIST ${distfile} ${filesize} BLAKE2B ${blake2b} SHA512 ${sha512}" > "${EBUILD_DIR}/Manifest"
    log_success "Manifest generated for ${distfile}"
}

# Remove old ebuilds (keep last N versions)
cleanup_old_versions() {
    local keep="${1:-1}"
    local ebuilds

    mapfile -t ebuilds < <(ls "${EBUILD_DIR}"/*.ebuild 2>/dev/null | sort -V)
    local count=${#ebuilds[@]}

    if (( count <= keep )); then
        log_info "No cleanup needed (${count} versions, keeping ${keep})"
        return
    fi

    local to_remove=$((count - keep))
    log_info "Removing ${to_remove} old version(s)..."

    for ((i = 0; i < to_remove; i++)); do
        rm -v "${ebuilds[$i]}"
    done

    log_success "Cleanup complete"
}

# Git operations
git_commit() {
    local version="$1"
    local dry_run="${2:-false}"

    cd "${OVERLAY_DIR}"

    git add "${EBUILD_DIR}/"

    if git diff --cached --quiet; then
        log_info "No changes to commit"
        return 0
    fi

    local msg="app-editors/devin-desktop-bin: bump to ${version}"

    if [[ "$dry_run" == "true" ]]; then
        log_info "[DRY-RUN] Would commit: $msg"
        git diff --cached --stat
        return 0
    fi

    git commit -m "$msg"
    log_success "Committed: $msg"
}

# Main update flow
main() {
    local dry_run=false
    local force=false
    local no_commit=false
    local keep_versions=1

    # Parse arguments
    while [[ $# -gt 0 ]]; do
        case $1 in
            -n|--dry-run)
                dry_run=true
                shift
                ;;
            -f|--force)
                force=true
                shift
                ;;
            --no-commit)
                no_commit=true
                shift
                ;;
            --no-push)
                # Legacy flag: treat as --no-commit for backward compatibility
                no_commit=true
                shift
                ;;
            --keep)
                keep_versions="$2"
                shift 2
                ;;
            -h|--help)
                echo "Usage: $0 [OPTIONS]"
                echo ""
                echo "Options:"
                echo "  -n, --dry-run    Show what would be done without making changes"
                echo "  -f, --force      Force update even if version matches"
                echo "  --no-commit      Don't git commit changes"
                echo "  --keep N         Keep last N versions (default: 1)"
                echo "  -h, --help       Show this help"
                exit 0
                ;;
            *)
                log_error "Unknown option: $1"
                exit 1
                ;;
        esac
    done

    echo "============================================"
    echo "  Devin (Windsurf) Editor Ebuild Updater"
    echo "============================================"
    echo ""

    log_info "Overlay directory: ${OVERLAY_DIR}"
    log_info "Checking for updates..."
    echo ""

    # Get versions
    local current_version latest_version
    current_version=$(get_current_version)
    latest_version=$(get_latest_version) || exit 1

    echo "Current: ${current_version:-<none>}"
    echo "Latest:  ${latest_version}"
    echo ""

    # Compare versions
    if [[ "$current_version" == "$latest_version" ]] && [[ "$force" != "true" ]]; then
        log_success "Already up to date!"
        exit 0
    fi

    if [[ "$dry_run" == "true" ]]; then
        log_info "[DRY-RUN] Would update to ${latest_version}"
        exit 0
    fi

    # Create new ebuild
    create_ebuild "$latest_version"

    # Generate manifest
    generate_manifest

    # Cleanup old versions
    cleanup_old_versions "$keep_versions"

    # Clear cleanup list on success (files are committed, not orphans)
    CLEANUP_FILES=()

    # Git operations
    if [[ "$no_commit" != "true" ]]; then
        git_commit "$latest_version" false
    fi

    echo ""
    log_success "Update complete: ${latest_version}"
}

main "$@"
