#!/bin/bash

# HamoniKR Repository Installer
# Copyright HamoniKR Team. All rights reserved.
#
# Script that automatically selects and installs appropriate repositories based on architecture and OS codename
#
# Usage:
# curl -fsSL https://repo.hamonikr.org/install | sudo bash
# wget -qO- https://repo.hamonikr.org/install | sudo -E bash -

set -euo pipefail
export DEBIAN_FRONTEND=noninteractive

# Global variables
SCRIPT_VERSION="2.0.0"
SCRIPT_NAME="HamoniKR Repository Installer"
VERBOSE=${VERBOSE:-false}

# Logging functions
log_info() {
    echo "[INFO] $*"
}

log_warn() {
    echo "[WARN] $*"
}

log_error() {
    echo "[ERROR] $*"
}

log_success() {
    echo "[SUCCESS] $*"
}

# Status output functions
print_status() {
    echo
    echo "## $1"
    echo
}

print_header() {
    echo
    echo "================================================================================"
    echo "  $1"
    echo "================================================================================"
    echo
}

# Error handling
bail() {
    log_error "An error occurred while executing the script: $1"
    exit 1
}

# Command execution function
exec_cmd() {
    local cmd="$1"
    local description="${2:-$cmd}"

    if [[ "$VERBOSE" == "true" ]]; then
        log_info "Executing: $description"
        log_info "Command: $cmd"
    fi

    if ! bash -c "$cmd" >/dev/null 2>&1; then
        bail "Command execution failed: $description"
    fi
}

# Detect system information
detect_system_info() {
    log_info "Detecting system information..."

    # Detect architecture
    ARCH=$(uname -m)
    case "$ARCH" in
        x86_64) ARCH_NAME="amd64" ;;
        aarch64) ARCH_NAME="arm64" ;;
        armv7l) ARCH_NAME="armhf" ;;
        *) bail "Unsupported architecture: $ARCH" ;;
    esac

    # Detect distribution information
    if ! command -v lsb_release >/dev/null 2>&1; then
        log_warn "lsb_release is not installed. Installing..."
        apt-get update -qq
        apt-get install -y lsb-release
    fi

    DISTRO_ID=$(lsb_release -i -s)
    DISTRO_RELEASE=$(lsb_release -r -s)
    DISTRO_CODENAME=$(lsb_release -c -s)
    DISTRO_DESCRIPTION=$(lsb_release -d -s)

    log_info "Detected system information:"
    log_info "  Architecture: $ARCH ($ARCH_NAME)"
    log_info "  Distribution: $DISTRO_ID"
    log_info "  Release: $DISTRO_RELEASE"
    log_info "  Codename: $DISTRO_CODENAME"
    log_info "  Description: $DISTRO_DESCRIPTION"
}

# Repository configuration database
get_repository_config() {
    local codename="$1"
    local arch="$2"

    # Repository configuration mapping table
    # Format: "codename|architecture|URL|distribution_code|components|description"
    local configs=(
        # Ubuntu 18.04 based
        "bionic|amd64|https://pkg.hamonikr.org|bionic|main|Ubuntu 18.04 LTS Bionic Beaver"
        "bionic|arm64|http://pkg.hamonikr.org/|bionic|main|Ubuntu 18.04 LTS Bionic Beaver (ARM64)"

        # Ubuntu 20.04 based
        "focal|amd64|https://pkg.hamonikr.org|focal|main|Ubuntu 20.04 LTS Focal Fossa"
        "focal|arm64|http://repo.hamonikr.org/|jetson|main|Ubuntu 20.04 LTS Focal Fossa (ARM64)"

        # Ubuntu 22.04 based
        "jammy|amd64|https://repo.hamonikr.org|jammy|main extra|Ubuntu 22.04 LTS Jammy Jellyfish"
        "jammy|arm64|http://repo.hamonikr.org/|kumkang|main extra|Ubuntu 22.04 LTS Jammy Jellyfish (ARM64)"

        # Ubuntu 24.04 based
        "noble|amd64|https://repo.hamonikr.org|noble|main contrib updates backport extra non-free|Ubuntu 24.04 LTS Noble Numbat"
        "noble|arm64|http://repo.hamonikr.org/|noble|main|Ubuntu 24.04 LTS Noble Numbat (ARM64)"

        # Ubuntu 24.10 and future versions
        "oracular|amd64|https://repo.hamonikr.org|noble|main contrib updates backport extra non-free|Ubuntu 24.10 Oracular Oriole"
        "plucky|amd64|https://repo.hamonikr.org|noble|main contrib updates backport extra non-free|Ubuntu 25.04 Plucky Puffin"

        # Linux Mint 19.x series
        "tara|amd64|https://pkg.hamonikr.org|bionic|main|Linux Mint 19 Tara"
        "tessa|amd64|https://pkg.hamonikr.org|bionic|main|Linux Mint 19.1 Tessa"
        "tina|amd64|https://pkg.hamonikr.org|bionic|main|Linux Mint 19.2 Tina"
        "tricia|amd64|https://pkg.hamonikr.org|bionic|main|Linux Mint 19.3 Tricia"

        # Linux Mint 20.x series
        "ulyana|amd64|https://update.hamonikr.org|taebaek|main extra|Linux Mint 20 Ulyana"
        "ulyssa|amd64|https://update.hamonikr.org|taebaek|main extra|Linux Mint 20.1 Ulyssa"
        "uma|amd64|https://update.hamonikr.org|taebaek|main extra|Linux Mint 20.2 Uma"
        "una|amd64|https://update.hamonikr.org|taebaek|main extra|Linux Mint 20.3 Una"

        # Linux Mint 21.x series
        "vanessa|amd64|https://repo.hamonikr.org|jammy|main extra|Linux Mint 21 Vanessa"
        "vera|amd64|https://repo.hamonikr.org|jammy|main extra|Linux Mint 21.1 Vera"
        "victoria|amd64|https://repo.hamonikr.org|jammy|main extra|Linux Mint 21.2 Victoria"
        "virginia|amd64|https://repo.hamonikr.org|jammy|main extra|Linux Mint 21.3 Virginia"
        "virginia|arm64|http://repo.hamonikr.org/|kumkang|main extra|Linux Mint 21.3 Virginia (ARM64)"

        # Linux Mint 22.x series
        "wilma|amd64|https://repo.hamonikr.org|noble|main contrib updates backport extra non-free|Linux Mint 22 Wilma"
        "xia|amd64|https://repo.hamonikr.org|noble|main contrib updates backport extra non-free|Linux Mint 22.1 Xia"

        # Debian series
        "buster|arm64|http://pkg.hamonikr.org/|buster|main|Debian 10 Buster (ARM64)"
        "bullseye|amd64|https://pkg.hamonikr.org|bullseye|main|Debian 11 Bullseye"
        "bullseye|arm64|http://repo.hamonikr.org/|jetson|main|Debian 11 Bullseye (ARM64)"
        "bookworm|amd64|https://pkg.hamonikr.org|bookworm|main|Debian 12 Bookworm"
        "bookworm|arm64|http://repo.hamonikr.org/|bookworm|main|Debian 12 Bookworm (ARM64)"
        "trixie|amd64|https://repo.hamonikr.org|trixie|main|Debian 13 Trixie"

        # HamoniKR series
        "me|amd64|https://update.hamonikr.org|taebaek|main extra|HamoniKR Me"
        "sun|amd64|https://update.hamonikr.org|taebaek|main extra|HamoniKR Sun"
        "jin|amd64|https://update.hamonikr.org|taebaek|main extra|HamoniKR Jin"
        "hanla|amd64|https://update.hamonikr.org|taebaek|main extra|HamoniKR 5.0 Hanla"
        "taebaek|amd64|https://update.hamonikr.org|taebaek|main extra|HamoniKR 6.0 Taebaek"
        "kumkang|amd64|https://repo.hamonikr.org|kumkang|main extra|HamoniKR 7.0 kumkang"
        "paektu|amd64|https://repo.hamonikr.org|paektu|main extra|HamoniKR 8.0 paektu"
        "kumkang|arm64|http://repo.hamonikr.org/|kumkang|main extra|HamoniKR Kumkang (ARM64)"
        "paektu|arm64|http://repo.hamonikr.org/|bookworm|main|HamoniKR Paektu (ARM64)"
        "sejong|amd64|https://repo.hamonikr.org|sejong|main extra|HamoniKR 9.0 sejong"

        # Special codenames
        "orion-belt|amd64|https://pkg.hamonikr.org|bookworm|main|Orion Belt"
        "orion-belt|arm64|http://repo.hamonikr.org/|bookworm|main|Orion Belt (ARM64)"
        "elsie|amd64|https://pkg.hamonikr.org|bullseye|main|Elsie"
        "groovy|amd64|https://pkg.hamonikr.org|jammy|main|Ubuntu 20.10 Groovy Gorilla"
        "hirsute|amd64|https://pkg.hamonikr.org|jammy|main|Ubuntu 21.04 Hirsute Hippo"
        "impish|amd64|https://update.hamonikr.org|jammy|main extra|Ubuntu 21.10 Impish Indri"
    )

    # Find exact match
    for config in "${configs[@]}"; do
        IFS='|' read -r cfg_codename cfg_arch cfg_url cfg_distro_code cfg_components cfg_description <<< "$config"
        if [[ "$cfg_codename" == "$codename" && "$cfg_arch" == "$arch" ]]; then
            echo "$config"
            return 0
        fi
    done

    # If no exact match, return the first one that matches architecture only
    log_warn "No exact configuration found. Looking for compatible configuration..."
    for config in "${configs[@]}"; do
        IFS='|' read -r cfg_codename cfg_arch cfg_url cfg_distro_code cfg_components cfg_description <<< "$config"
        if [[ "$cfg_arch" == "$arch" ]]; then
            log_warn "Using fallback configuration: $cfg_description"
            echo "$config"
            return 0
        fi
    done

    return 1
}

# Install GPG key
install_gpg_key() {
    print_status "Installing HamoniKR GPG key..."

    local key_file="/usr/share/keyrings/hamonikr-archive-keyring.gpg"
    local key_url="https://repo.hamonikr.org/hamonikr-pkg.key"

    # Remove existing key file
    [[ -f "$key_file" ]] && rm -f "$key_file"

    # Download and install GPG key
    if command -v curl >/dev/null 2>&1; then
        exec_cmd "curl -fsSL '$key_url' | gpg --dearmor -o '$key_file'" "GPG key download (curl)"
    elif command -v wget >/dev/null 2>&1; then
        exec_cmd "wget -qO- '$key_url' | gpg --dearmor -o '$key_file'" "GPG key download (wget)"
    else
        bail "curl or wget is required"
    fi

    # Set key file permissions
    exec_cmd "chmod 644 '$key_file'" "GPG key file permission setting"

    log_success "GPG key installed successfully"
}

# Clean up old repository configurations
cleanup_old_repositories() {
    print_status "Cleaning up old repository configurations..."

    local old_files=(
        "/etc/apt/sources.list.d/hamonikr-pkg.list"
        "/etc/apt/sources.list.d/hamonikr-app.list"
        "/etc/apt/trusted.gpg.d/hamonikr.gpg"
    )

    for file in "${old_files[@]}"; do
        if [[ -f "$file" ]]; then
            log_info "Removing old file: $file"
            rm -f "$file"
        fi
    done

    log_success "Old repository configurations cleaned up"
}

# Add repository
add_repository() {
    local config="$1"

    if [[ -z "$config" ]]; then
        bail "Repository configuration not found"
    fi

    # Parse configuration
    IFS='|' read -r codename arch url distro_code components description <<< "$config"

    print_status "Adding repository..."
    log_info "Configuration: $description"
    log_info "URL: $url"
    log_info "Architecture: $arch"
    log_info "Distribution code: $distro_code"
    log_info "Components: $components"

    local sources_file="/etc/apt/sources.list.d/hamonikr-app.list"
    local key_file="/usr/share/keyrings/hamonikr-archive-keyring.gpg"

    # Write repository configuration
    {
        echo "### HamoniKR Repository - Auto-configured by $SCRIPT_NAME v$SCRIPT_VERSION"
        echo "### $description"
        echo "### Generated on: $(date)"
        echo ""

        # Handle different URL formats
        if [[ "$url" == *"/" ]]; then
            # URL ends with / (e.g., http://repo.hamonikr.org/)
            echo "deb [arch=$arch signed-by=$key_file] $url $distro_code $components"
            echo "#deb-src [arch=$arch signed-by=$key_file] $url $distro_code $components"
        else
            # General case (e.g., https://repo.hamonikr.org)
            echo "deb [arch=$arch signed-by=$key_file] $url $distro_code $components"
            echo "#deb-src [arch=$arch signed-by=$key_file] $url $distro_code $components"
        fi

        echo ""
        echo "### End of HamoniKR Repository configuration"
    } > "$sources_file"

    log_success "Repository added successfully: $sources_file"
}

# Install prerequisites
install_prerequisites() {
    print_status "Checking and installing prerequisites..."

    local packages=()

    # Check essential packages
    [[ ! -e /usr/lib/apt/methods/https ]] && packages+=(apt-transport-https)
    [[ ! -x /usr/bin/lsb_release ]] && packages+=(lsb-release)
    [[ ! -x /usr/bin/curl ]] && [[ ! -x /usr/bin/wget ]] && packages+=(curl)
    [[ ! -x /usr/bin/gpg ]] && packages+=(gnupg)

    if [[ ${#packages[@]} -gt 0 ]]; then
        log_info "Installing the following packages: ${packages[*]}"
        exec_cmd "apt-get update -qq" "Updating package list"
        exec_cmd "apt-get install -y ${packages[*]}" "Installing essential packages"
    else
        log_info "All prerequisites are already installed"
    fi
}

# Update repositories
update_repositories() {
    print_status "Updating repository list..."
    exec_cmd "apt-get update" "Repository update"
    log_success "Repository update completed"
}

# Print completion message
print_completion_message() {
    print_header "Installation Complete!"

    echo "HamoniKR repository has been successfully installed."
    echo ""
    echo "System Information:"
    echo "  • Architecture: $ARCH ($ARCH_NAME)"
    echo "  • Distribution: $DISTRO_DESCRIPTION"
    echo "  • Codename: $DISTRO_CODENAME"
    echo ""
    echo "You can now install HamoniKR packages using the following commands:"
    echo "  sudo apt update"
    echo "  sudo apt install <package-name>"
    echo ""
    echo "For more information, please visit:"
    echo "  https://hamonikr.org"
    echo
}

# Main function
main() {
    # Print header
    print_header "$SCRIPT_NAME v$SCRIPT_VERSION"

    log_info "Starting HamoniKR repository installation..."

    # Check root privileges
    if [[ $EUID -ne 0 ]]; then
        bail "This script must be run as root. Please use 'sudo'."
    fi

    # Execute step by step
    install_prerequisites
    detect_system_info

    # Find repository configuration
    local repo_config
    if ! repo_config=$(get_repository_config "$DISTRO_CODENAME" "$ARCH_NAME"); then
        bail "Unsupported system: $DISTRO_DESCRIPTION ($DISTRO_CODENAME, $ARCH_NAME)"
    fi

    cleanup_old_repositories
    install_gpg_key
    add_repository "$repo_config"
    update_repositories

    print_completion_message

}

# Call main function only when script is executed directly
# Modified condition to support execution through pipes
if [[ "${BASH_SOURCE[0]:-}" == "${0}" ]] || [[ -z "${BASH_SOURCE[0]:-}" ]]; then
    main "$@"
fi
