#!/bin/bash
set -e
# Enable pipefail where supported (bash/ksh); silently skip in POSIX sh
(set -o pipefail) 2>/dev/null && set -o pipefail || true
# Default values (will be set based on detected OS)
export DEBIAN_FRONTEND=noninteractive
ACTION=""
DRIVER_VARIANT=""
UNINSTALL_REMOVED_PACKAGES=0
REPO_NAME="cix-repo-community"
DIST_CODENAME=""
REPO_URL=""
GPG_KEY_URL="https://archive.cixtech.com/ppa-gpg-public-key.asc"
DRIVER_PACKAGE_BASE=""
DRIVER_PACKAGE=""
KERNEL_VERSION="6.6"
KERNEL_BOOT_GLOB="/boot/vmlinuz-*-cix-build-generic"
TARGET_CMDLINE_EXTRA="acpi=force kasan=off"
CIX_GRUB_CONFIG_FILE="/etc/cix/grub-config.env"
CIX_GRUB_REFRESH_CMD="/usr/libexec/cix-grub-config-refresh"
PIN_PRIORITY="1001"
# Color codes for output
RED=$'\033[0;31m'
GREEN=$'\033[0;32m'
YELLOW=$'\033[1;33m'
NC=$'\033[0m' # No Color
error_exit() {
    echo "${RED}❌ $1${NC}" >&2
    exit 1
}
warn() {
    echo "${YELLOW}⚠ $1${NC}" >&2
}
success() {
    echo "${GREEN}✅ $1${NC}"
}
usage() {
    cat <<EOF
Usage: cix-repo-community.sh [OPTIONS]
Options:
  --install             Install CIX driver, Linux 6.6 (non-interactive)
  --install-full        Install full CIX driver bundle, Linux 6.6
                        (Debian 12/bookworm only, non-interactive)
  --uninstall           Uninstall CIX packages and configuration (non-interactive)
  -h, --help            Show this help message
Without any of the above action options, the script runs interactively.
EOF
}
parse_args() {
    while [ "$#" -gt 0 ]; do
        case "$1" in
            -h|--help|help)
                usage
                exit 0
                ;;
            --install)
                ACTION="install"
                DRIVER_VARIANT="base"
                ;;
            --install-full)
                ACTION="install"
                DRIVER_VARIANT="full"
                ;;
            --uninstall)
                ACTION="uninstall"
                ;;
            *)
                error_exit "Unknown argument: $1"
                ;;
        esac
        shift
    done
}
set_closed_source_install() {
    ACTION="install"
    case "$DRIVER_VARIANT" in
        full) DRIVER_PACKAGE="${DRIVER_PACKAGE_BASE}-full" ;;
        *)    DRIVER_PACKAGE="${DRIVER_PACKAGE_BASE}" ;;
    esac
    KERNEL_VERSION="6.6"
    KERNEL_BOOT_GLOB="/boot/vmlinuz-*-cix-build-generic"
    TARGET_CMDLINE_EXTRA="acpi=force kasan=off"
}
full_install_available() {
    [ "$ID" = "debian" ] && [ "$VERSION_CODENAME" = "bookworm" ]
}
select_driver_package() {
    local driver_choice=""
    # Non-interactive mode: action pre-set via command-line flags
    if [ -n "$ACTION" ]; then
        if [ "$ACTION" = "install" ]; then
            if [ "$DRIVER_VARIANT" = "full" ] && ! full_install_available; then
                error_exit "--install-full is only supported on Debian 12 (bookworm)"
            fi
            set_closed_source_install
        fi
        return 0
    fi
    if [ ! -r /dev/tty ]; then
        if full_install_available; then
            DRIVER_VARIANT="full"
        else
            DRIVER_VARIANT="base"
        fi
        set_closed_source_install
        warn "No interactive terminal detected. Defaulting to ${DRIVER_PACKAGE}."
        return 0
    fi
    echo ""
    echo "Please select the driver package version to install:"
    if full_install_available; then
        echo "  1) ${DRIVER_PACKAGE_BASE}       (Linux 6.6)"
        echo "  2) ${DRIVER_PACKAGE_BASE}-full  (Full bundle, Linux 6.6)"
        echo "  3) Uninstall CIX packages and configuration"
        echo ""
        while true; do
            read -r -p "Enter your choice [1-3, default 2]: " driver_choice < /dev/tty
            driver_choice=${driver_choice:-2}
            case "$driver_choice" in
                1)
                    DRIVER_VARIANT="base"
                    set_closed_source_install
                    break
                    ;;
                2)
                    DRIVER_VARIANT="full"
                    set_closed_source_install
                    break
                    ;;
                3)
                    ACTION="uninstall"
                    break
                    ;;
                *)
                    warn "Invalid option, please try again"
                    ;;
            esac
        done
        return 0
    fi
    echo "  1) ${DRIVER_PACKAGE_BASE}  (Linux 6.6)"
    echo "  2) Uninstall CIX packages and configuration"
    echo ""
    while true; do
        read -r -p "Enter your choice [1-2, default 1]: " driver_choice < /dev/tty
        driver_choice=${driver_choice:-1}
        case "$driver_choice" in
            1)
                DRIVER_VARIANT="base"
                set_closed_source_install
                break
                ;;
            2)
                ACTION="uninstall"
                break
                ;;
            *)
                warn "Invalid option, please try again"
                ;;
        esac
    done
}
find_latest_target_kernel() {
    # shellcheck disable=SC2086
    ls $KERNEL_BOOT_GLOB 2>/dev/null | sort -V | tail -n 1
}
write_cix_grub_config() {
    if ! chmod 644 "$CIX_GRUB_CONFIG_FILE"; then
        warn "Failed to set permissions on $CIX_GRUB_CONFIG_FILE."
        return 1
    fi
    return 0
}
configure_cix_grub() {
    GRUB_CIX_KERNEL=""
    echo "➡ Configuring cix-grub-config"
    if ! write_cix_grub_config; then
        return 1
    fi
    if [ ! -x "$CIX_GRUB_REFRESH_CMD" ]; then
        warn "cix-grub-config refresh command was not found at $CIX_GRUB_REFRESH_CMD."
        return 1
    fi
    if ! "$CIX_GRUB_REFRESH_CMD"; then
        warn "Failed to refresh GRUB through cix-grub-config."
        return 1
    fi
    GRUB_CIX_KERNEL=$(find_latest_target_kernel)
    return 0
}
remove_cix_grub_config_file() {
    if [ -f "$CIX_GRUB_CONFIG_FILE" ]; then
        echo "➡ Removing cix-grub-config runtime settings"
        if ! rm -f "$CIX_GRUB_CONFIG_FILE"; then
            warn "Failed to remove $CIX_GRUB_CONFIG_FILE."
            return 1
        fi
    fi
    return 0
}
set_driver_package_base() {
    case "$ID" in
        debian)
            case "$VERSION_CODENAME" in
                trixie)
                    DRIVER_PACKAGE_BASE="cix-debian13-k6.6.89-driver"
                    ;;
                bookworm)
                    DRIVER_PACKAGE_BASE="cix-debian12-k6.6.89-driver"
                    ;;
            esac
            ;;
        ubuntu)
            case "$VERSION_CODENAME" in
                noble)
                    DRIVER_PACKAGE_BASE="cix-ubuntu2404-driver"
                    ;;
                plucky)
                    DRIVER_PACKAGE_BASE="cix-ubuntu2504-driver"
                    ;;
                resolute)
                    DRIVER_PACKAGE_BASE="cix-ubuntu2604-driver"
                    ;;
            esac
            ;;
    esac
}
collect_named_cix_packages() {
    dpkg-query -W -f='${db:Status-Abbrev}\t${binary:Package}\t${Version}\n' 2>/dev/null | awk '
        $1 != "ii" { next }
        $2 ~ /cix/ { print $2 }
    ' | sort -u
}
collect_packages_requiring_repo_reinstall() {
    dpkg-query -W -f='${db:Status-Abbrev}\t${binary:Package}\t${Version}\n' 2>/dev/null | awk '
        $1 != "ii" { next }
        $2 ~ /cix/ { next }
        $3 ~ /(^|[+~.-])cix([+~.-]|$)/ { print $2 }
    ' | sort -u
}
remove_named_cix_packages() {
    local package_list
    package_list=$(collect_named_cix_packages)
    if [ -n "$package_list" ]; then
        echo "➡ Removing installed packages with 'cix' in the name: $package_list"
        if ! echo "$package_list" | xargs apt purge -y; then
            warn "Failed to remove one or more installed CIX-named packages."
            return 1
        fi
        UNINSTALL_REMOVED_PACKAGES=1
        success "Installed CIX-named packages removed successfully"
    else
        warn "No installed packages with 'cix' in the name were found."
    fi
    return 0
}
remove_open_source_kernel_packages() {
    local package_list
    package_list=$(dpkg-query -W -f='${db:Status-Abbrev}\t${binary:Package}\n' 2>/dev/null | awk '
        $1 != "ii" { next }
        $2 == "linux-image-7.0.0-rc5-generic" { print $2 }
        $2 == "linux-headers-7.0.0-rc5-generic" { print $2 }
        $2 == "linux-image-7.0.0-generic" { print $2 }
        $2 == "linux-headers-7.0.0-generic" { print $2 }
        $2 ~ /^linux-image-.*-cix-generic$/ { print $2 }
        $2 ~ /^linux-headers-.*-cix-generic$/ { print $2 }
    ' | sort -u)
    if [ -z "$package_list" ]; then
        return 0
    fi
    echo "➡ Removing open-source kernel packages: $package_list"
    if ! echo "$package_list" | xargs apt purge -y; then
        warn "Failed to remove one or more open-source kernel packages."
        return 1
    fi
    UNINSTALL_REMOVED_PACKAGES=1
    success "Open-source kernel packages removed successfully"
    return 0
}
refresh_package_index() {
    echo "➡ Updating package index"
    if ! apt update; then
        warn "Failed to update package index after repository cleanup."
        return 1
    fi
    success "Package index updated successfully"
    return 0
}
reinstall_repo_replaced_packages() {
    local candidate_version=""
    local install_specs=""
    local pkg_list=""
    local pkg=""
    pkg_list=$(collect_packages_requiring_repo_reinstall)
    if [ -z "$pkg_list" ]; then
        return 0
    fi
    for pkg in $pkg_list; do
        candidate_version=$(apt-cache policy "$pkg" 2>/dev/null | awk '
            /^[[:space:]]*Version table:/ {
                in_table=1
                next
            }
            !in_table {
                next
            }
            {
                line=$0
                gsub(/^[[:space:]]+/, "", line)
                sub(/^\*\*\*[[:space:]]+/, "", line)
                split(line, fields, /[[:space:]]+/)
                version=fields[1]
                priority=fields[2]
                if (version == "" || priority !~ /^[0-9]+$/) {
                    next
                }
                if (version !~ /(^|[+~.-])cix([+~.-]|$)/) {
                    print version
                    exit
                }
            }
        ')
        if [ -z "$candidate_version" ] || [ "$candidate_version" = "(none)" ]; then
            warn "No non-CIX repository version found for $pkg after removing the repository."
            return 1
        fi
        install_specs="$install_specs ${pkg}=${candidate_version}"
    done
    echo "➡ Reinstalling packages that were replaced by CIX repository versions:$install_specs"
    if ! echo "$install_specs" | xargs apt install -y --allow-downgrades --allow-change-held-packages; then
        warn "Failed to reinstall one or more packages from the default repository."
        return 1
    fi
    success "Default repository packages reinstalled successfully"
    return 0
}
cleanup_unused_dependencies() {
    if [ "$UNINSTALL_REMOVED_PACKAGES" -ne 1 ]; then
        return 0
    fi
    echo "➡ Removing automatically installed dependencies"
    if ! apt autoremove --purge -y; then
        warn "Automatic dependency cleanup encountered issues."
    else
        success "Automatic dependency cleanup completed successfully"
    fi
    return 0
}
remove_repo_configuration() {
    local removed_any=0
    if [ -f "$LIST_PATH" ]; then
        echo "➡ Removing APT source list $LIST_PATH"
        if ! rm -f "$LIST_PATH"; then
            warn "Failed to remove $LIST_PATH."
            return 1
        fi
        removed_any=1
    fi
    if [ -f "$PREFERENCES_PATH" ]; then
        echo "➡ Removing APT pin file $PREFERENCES_PATH"
        if ! rm -f "$PREFERENCES_PATH"; then
            warn "Failed to remove $PREFERENCES_PATH."
            return 1
        fi
        removed_any=1
    fi
    if [ -f "$KEYRING_PATH" ]; then
        echo "➡ Removing keyring $KEYRING_PATH"
        if ! rm -f "$KEYRING_PATH"; then
            warn "Failed to remove $KEYRING_PATH."
            return 1
        fi
        removed_any=1
    fi
    if [ "$removed_any" -eq 1 ]; then
        success "Repository configuration removed successfully"
    else
        warn "No repository configuration added by cix-repo-community was found."
    fi
    return 0
}
uninstall_cix_repo() {
    echo "➡ Uninstalling CIX packages and configuration"
    UNINSTALL_REMOVED_PACKAGES=0
    remove_named_cix_packages || return 1
    remove_open_source_kernel_packages || return 1
    remove_cix_grub_config_file || warn "Unable to fully clean cix-grub-config runtime settings automatically."
    remove_repo_configuration || return 1
    refresh_package_index || return 1
    reinstall_repo_replaced_packages || return 1
    cleanup_unused_dependencies || true
    echo ""
    echo "${YELLOW}═══════════════════════════════════════════════════${NC}"
    echo "${GREEN}🔄 Reboot to complete driver removal${NC}"
    echo "${YELLOW}═══════════════════════════════════════════════════${NC}"
    echo ""
}
parse_args "$@"
if [ "$(id -u)" -ne 0 ]; then
    error_exit "Please run this script as root"
fi
if [ ! -f /etc/os-release ]; then
    error_exit "Unable to detect operating system"
fi
. /etc/os-release
case "$ID" in
    debian)
        case "$VERSION_CODENAME" in
            trixie)
                DIST_CODENAME="trixie"
                REPO_URL="https://archive.cixtech.com/debian"
                REPO_NAME="cix-deb-repo"
                PIN_PRIORITY="100"
                success "Debian 13 (trixie) detected"
                ;;
            bookworm)
                DIST_CODENAME="bookworm"
                REPO_URL="https://archive.cixtech.com/debian"
                REPO_NAME="cix-deb-repo"
                PIN_PRIORITY="1001"
                success "Debian 12 (bookworm) detected"
                ;;
            *)
                error_exit "Unsupported Debian version: $VERSION_CODENAME"
                ;;
        esac
        ;;
    ubuntu)
        case "$VERSION_CODENAME" in
            noble)
                DIST_CODENAME="noble"
                REPO_URL="https://archive.cixtech.com/ubuntu"
                REPO_NAME="cix-ubuntu-repo"
                success "Ubuntu 24.04 LTS (noble) detected"
                ;;
            plucky)
                DIST_CODENAME="plucky"
                REPO_URL="https://archive.cixtech.com/ubuntu"
                REPO_NAME="cix-ubuntu-repo"
                success "Ubuntu 25.04 (plucky) detected"
                ;;
            resolute)
                DIST_CODENAME="resolute"
                REPO_URL="https://archive.cixtech.com/ubuntu"
                REPO_NAME="cix-ubuntu-repo"
                success "Ubuntu 26.04 (resolute) detected"
                ;;
            *)
                error_exit "Unsupported Ubuntu version: $VERSION_CODENAME (VERSION_ID=$VERSION_ID)"
                ;;
        esac
        ;;
    *)
        error_exit "Unsupported distribution: $ID (Only Debian 12/13 and Ubuntu 24.04/25.04/26.04 are supported)"
        ;;
esac
KEYRING_PATH="/usr/share/keyrings/${REPO_NAME}.gpg"
LIST_PATH="/etc/apt/sources.list.d/${REPO_NAME}.list"
PREFERENCES_PATH="/etc/apt/preferences.d/${REPO_NAME}"
set_driver_package_base
select_driver_package
if [ "$ACTION" = "uninstall" ]; then
    uninstall_cix_repo
    exit 0
fi
for cmd in curl gpg; do
    if ! command -v "$cmd" >/dev/null 2>&1; then
        error_exit "Required command '$cmd' not found. Please install it first."
    fi
done
if [ -f "$LIST_PATH" ] && [ -f "$KEYRING_PATH" ]; then
    warn "Repository already configured. Reconfiguring..."
fi
if [ ! -d "/usr/share/keyrings" ]; then
    mkdir -p /usr/share/keyrings || error_exit "Failed to create keyring directory"
fi
if [ ! -d "/etc/apt/preferences.d" ]; then
    mkdir -p /etc/apt/preferences.d || error_exit "Failed to create APT preferences directory"
fi
echo "➡ Downloading and installing GPG key"
if ! curl -fsSL "$GPG_KEY_URL" | gpg --dearmor > "$KEYRING_PATH"; then
    error_exit "Failed to download or install GPG key from $GPG_KEY_URL"
fi
if [ ! -f "$KEYRING_PATH" ] || [ ! -s "$KEYRING_PATH" ]; then
    error_exit "GPG keyring file is empty or was not created"
fi
chmod 644 "$KEYRING_PATH"
success "GPG key installed successfully"
echo "➡ Configuring APT repository"
cat > "$LIST_PATH" <<EOF
deb [signed-by=$KEYRING_PATH] $REPO_URL $DIST_CODENAME main
EOF
success "Repository configured successfully"
REPO_HOST="${REPO_URL#*://}"
REPO_HOST="${REPO_HOST%%/*}"
echo "➡ Configuring APT pin priority"
cat > "$PREFERENCES_PATH" <<EOF
Package: *
Pin: origin "$REPO_HOST"
Pin-Priority: $PIN_PRIORITY
EOF
chmod 644 "$PREFERENCES_PATH"
success "APT pin priority configured successfully"
echo "➡ Updating package index"
if ! apt update; then
    error_exit "Failed to update package index. Please check your network connection and repository configuration."
fi
success "Package index updated successfully"
echo ""
echo "${GREEN}🎉 Repository setup completed successfully!${NC}"
echo ""
echo "➡ Installing CIX driver package"
if [ -n "$DRIVER_PACKAGE" ]; then
    echo "Installing $DRIVER_PACKAGE..."
    if ! apt install -y --allow-downgrades "$DRIVER_PACKAGE"; then
        error_exit "Failed to install $DRIVER_PACKAGE"
    fi
    success "$DRIVER_PACKAGE installed successfully"
    echo ""
    if configure_cix_grub; then
        success "cix-grub-config refreshed successfully"
    else
        warn "Unable to refresh cix-grub-config automatically."
    fi
    echo ""
    echo "${YELLOW}═══════════════════════════════════════════════════${NC}"
    echo "${GREEN}🔄 Reboot to complete driver installation${NC}"
    echo "${YELLOW}═══════════════════════════════════════════════════${NC}"
    echo ""
    if [ -n "$GRUB_CIX_KERNEL" ]; then
        echo "Target kernel ${GREEN}$(basename "$GRUB_CIX_KERNEL")${NC} is now the first GRUB boot option"
    else
        echo "Please reboot and verify ${GREEN}Linux $KERNEL_VERSION${NC} is the selected GRUB kernel"
    fi
    echo "${YELLOW}═══════════════════════════════════════════════════${NC}"
    echo ""
else
    warn "No driver package found for $ID $VERSION_CODENAME"
    echo ""
    echo "You can now install packages from the CIX repository:"
    echo "  apt search <package-name>"
    echo "  apt install <package-name>"
fi
