#!/usr/bin/env bash

set -euo pipefail

SCRIPT_DIR=""
TARGET_DIR="/usr/local/sbin"
BASE_URL="${THREEWWAV2MP3_BASE_URL:-}"
TMP_FILE=""
PREPARE_SYSTEM_ONLY=0
REINSTALL_SAME_VERSION=0
ASSUME_YES=0
MISSING_RUNTIME_COMMANDS=()
REQUIRED_PACKAGES=()
SCRIPT_NAME="3wwav2mp3_install.sh"
RUNTIME_NAME="3wwav2mp3"
RELEASE_VERSION="0.1.0"
COPYRIGHT_YEAR="2026"
header_printed=0

if [[ -t 1 ]]; then
    RESET=$'\033[0m'
    BRed=$'\033[1;31m'
    BGreen=$'\033[1;32m'
    BYellow=$'\033[1;33m'
    BBlue=$'\033[1;34m'
else
    RESET=""
    BRed=""
    BGreen=""
    BYellow=""
    BBlue=""
fi

usage() {
    cat <<EOF
Usage: ${SCRIPT_NAME} [--base-url URL] [--target-dir PATH] [--prepare-system] [--reinstall] [--yes] [--version]

Install:
  - ${RUNTIME_NAME}

Behavior:
  - if \`--base-url\` is set, download ${RUNTIME_NAME} from that URL
  - otherwise, install the local ./${RUNTIME_NAME} file next to this installer
  - install missing client-side runtime dependencies for the legacy script
  - \`--reinstall\` forces the selected release to be installed again even if the same version is already present
  - \`--prepare-system\` installs dependencies only and skips the ${RUNTIME_NAME} install
EOF
}

print_info() {
    printf '%sINFO%s %s\n' "${BBlue}" "${RESET}" "$1"
}

print_ok() {
    printf '%sOK%s %s\n' "${BGreen}" "${RESET}" "$1"
}

print_warn() {
    printf '%sWARN%s %s\n' "${BYellow}" "${RESET}" "$1"
}

print_error() {
    printf '%sERROR%s %s\n' "${BRed}" "${RESET}" "$1" >&2
}

fail() {
    print_error "$*"
    exit 1
}

cleanup() {
    if [[ -n "${TMP_FILE}" && -f "${TMP_FILE}" ]]; then
        rm -f "${TMP_FILE}"
    fi
}

trap cleanup EXIT

print_header() {
    if [[ "${THREEW_INSTALLER_SUPPRESS_HEADER:-0}" == "1" ]]; then
        header_printed=1
        return 0
    fi

    if [[ "${header_printed}" -eq 1 ]]; then
        return 0
    fi

    cat <<EOF
${BBlue}+------------------------------------------------------------------------------+${RESET}
${BBlue}|${RESET} ${SCRIPT_NAME} ${RELEASE_VERSION}
${BBlue}|${RESET} Copyright (c) ${COPYRIGHT_YEAR} 3W Global Corp. All rights reserved.
${BBlue}|${RESET} ${BYellow}NOTICE:${RESET} This legacy software is provided "as is", without
${BBlue}|${RESET} warranties or guarantees of any kind. Use it at your own risk. You are
${BBlue}|${RESET} solely responsible for backups, validation, and testing before production
${BBlue}|${RESET} use. 3W Global Corp shall not be liable for any loss, damage, data
${BBlue}|${RESET} corruption, or service interruption arising from its installation or use.
${BBlue}+------------------------------------------------------------------------------+${RESET}

EOF

    header_printed=1
}

print_version() {
    printf '%s %s\n' "${SCRIPT_NAME}" "${RELEASE_VERSION}"
}

check_bash_compatibility() {
    if [[ -z "${BASH_VERSION:-}" ]]; then
        fail "this installer must be run with bash"
    fi

    if [[ "${BASH_VERSINFO[0]-0}" -lt 3 ]]; then
        fail "this installer requires bash 3 or newer"
    fi
}

init_script_dir() {
    local script_source=""

    if [[ -n "${BASH_SOURCE[0]-}" ]]; then
        script_source="${BASH_SOURCE[0]}"
    elif [[ -n "${0:-}" && "${0}" != "bash" && "${0}" != "-bash" ]]; then
        script_source="${0}"
    fi

    if [[ -n "${script_source}" && -e "${script_source}" ]]; then
        SCRIPT_DIR="$(cd "$(dirname "${script_source}")" && pwd)"
    fi
}

command_exists() {
    command -v "$1" >/dev/null 2>&1
}

confirm_terms() {
    if [[ "${THREEW_INSTALLER_ASSUME_TERMS:-0}" == "1" ]]; then
        return 0
    fi

    if [[ "${ASSUME_YES}" -eq 1 ]]; then
        print_info "Proceeding with non-interactive acceptance of the license notice and terms."
        return 0
    fi

    local reply=""

    if [[ -r /dev/tty ]]; then
        printf 'Proceed and confirm that you accept the license notice and terms above? [y/N] ' > /dev/tty
        IFS= read -r reply < /dev/tty || reply=""
    elif [[ -t 0 ]]; then
        printf 'Proceed and confirm that you accept the license notice and terms above? [y/N] '
        IFS= read -r reply || reply=""
    fi

    case "${reply}" in
        y|Y|yes|YES)
            print_ok "License notice and terms accepted."
            return 0
            ;;
        *)
            print_warn "Cancelled. License notice and terms were not accepted."
            exit 1
            ;;
    esac
}

is_root() {
    [[ "$(id -u)" -eq 0 ]]
}

append_unique_package() {
    local value="$1"
    local existing=""

    for existing in "${REQUIRED_PACKAGES[@]:-}"; do
        if [[ "${existing}" == "${value}" ]]; then
            return 0
        fi
    done

    REQUIRED_PACKAGES+=("${value}")
}

collect_missing_runtime_commands() {
    local dependency=""
    local required_commands="find sort sed ls awk du bc nice lame mysql chown rm seq sleep"

    MISSING_RUNTIME_COMMANDS=()

    for dependency in ${required_commands}; do
        command_exists "${dependency}" || MISSING_RUNTIME_COMMANDS+=("${dependency}")
    done
}

package_manager_name() {
    if command_exists apt-get; then
        echo "apt-get"
        return 0
    fi
    if command_exists dnf; then
        echo "dnf"
        return 0
    fi
    if command_exists yum; then
        echo "yum"
        return 0
    fi
    if command_exists zypper; then
        echo "zypper"
        return 0
    fi
    return 1
}

map_commands_to_packages() {
    local manager="$1"
    local dependency=""

    REQUIRED_PACKAGES=()

    for dependency in "${MISSING_RUNTIME_COMMANDS[@]}"; do
        case "${dependency}" in
            find)
                append_unique_package "findutils"
                ;;
            sort|ls|du|nice|chown|rm|seq|sleep)
                append_unique_package "coreutils"
                ;;
            awk)
                append_unique_package "gawk"
                ;;
            sed)
                append_unique_package "sed"
                ;;
            bc)
                append_unique_package "bc"
                ;;
            lame)
                append_unique_package "lame"
                ;;
            mysql)
                case "${manager}" in
                    apt-get)
                        append_unique_package "default-mysql-client"
                        ;;
                    dnf|yum)
                        append_unique_package "mariadb"
                        ;;
                    zypper)
                        append_unique_package "mariadb-client"
                        ;;
                esac
                ;;
        esac
    done
}

print_dependency_install_command() {
    printf '%q ' "$@"
    echo
}

install_runtime_dependencies() {
    local manager=""
    local install_cmd=""
    local -a install_argv=()

    collect_missing_runtime_commands

    if ((${#MISSING_RUNTIME_COMMANDS[@]} == 0)); then
        print_ok "All legacy runtime dependencies currently look available."
        return 0
    fi

    print_info "This helper expects an existing PBX system and database. It does not install a database server."
    print_warn "Missing runtime commands: ${MISSING_RUNTIME_COMMANDS[*]}"

    manager="$(package_manager_name)" || {
        print_warn "No supported package manager was detected."
        print_warn "Install the required client-side runtime packages manually, then run the installer again."
        return 1
    }

    map_commands_to_packages "${manager}"
    install_argv=("${manager}" "install" "-y" "${REQUIRED_PACKAGES[@]}")
    install_cmd="$(print_dependency_install_command "${install_argv[@]}")"

    if is_root; then
        print_info "Installing required client-side packages:"
        echo "  ${install_cmd}"
        "${install_argv[@]}"
    elif command_exists sudo; then
        print_info "Installing required client-side packages with sudo:"
        echo "  sudo ${install_cmd}"
        sudo "${install_argv[@]}"
    else
        print_warn "Run this as root to install them:"
        echo "  ${install_cmd}"
        return 1
    fi

    if [[ "${manager}" == "dnf" || "${manager}" == "yum" ]]; then
        print_info "RPM note: the \`mariadb\` package above is the client package that provides \`mysql\`, not \`mariadb-server\`."
    fi
}

download_source() {
    local source_url="${BASE_URL%/}/${RUNTIME_NAME}"

    TMP_FILE="$(mktemp)"
    if command_exists curl; then
        curl -fsSL "${source_url}" -o "${TMP_FILE}"
    elif command_exists wget; then
        wget -qO "${TMP_FILE}" "${source_url}"
    else
        fail "neither curl nor wget is available to download ${source_url}"
    fi
    printf '%s\n' "${TMP_FILE}"
}

resolve_source() {
    local local_source=""

    if [[ -n "${BASE_URL}" ]]; then
        download_source
        return 0
    fi

    if [[ -n "${SCRIPT_DIR}" ]]; then
        local_source="${SCRIPT_DIR}/${RUNTIME_NAME}"
        if [[ -f "${local_source}" ]]; then
            printf '%s\n' "${local_source}"
            return 0
        fi
    fi

    fail "no local ${RUNTIME_NAME} was found and no --base-url was provided"
}

print_test_notice() {
    cat <<EOF
Run tests before production use:
  ${TARGET_DIR}/${RUNTIME_NAME}

Validate the generated MP3 output and database behavior before using this legacy script
on production recordings.
EOF
}

init_script_dir
check_bash_compatibility

while [[ $# -gt 0 ]]; do
    case "$1" in
        --base-url)
            [[ $# -ge 2 ]] || fail "--base-url requires a value"
            BASE_URL="$2"
            shift 2
            ;;
        --target-dir)
            [[ $# -ge 2 ]] || fail "--target-dir requires a value"
            TARGET_DIR="$2"
            shift 2
            ;;
        --prepare-system)
            PREPARE_SYSTEM_ONLY=1
            shift
            ;;
        --reinstall|--force-install|--clean-install)
            REINSTALL_SAME_VERSION=1
            shift
            ;;
        --yes)
            ASSUME_YES=1
            shift
            ;;
        --version)
            print_version
            exit 0
            ;;
        -h|--help)
            usage
            exit 0
            ;;
        *)
            fail "unexpected argument: $1"
            ;;
    esac
done

print_header
confirm_terms
install_runtime_dependencies

if [[ "${PREPARE_SYSTEM_ONLY}" -eq 1 ]]; then
    print_ok "System preparation complete. ${RUNTIME_NAME} was not installed."
    print_info "When you install it, run tests before production use."
    exit 0
fi

SOURCE_SCRIPT="$(resolve_source)"
[[ -f "${SOURCE_SCRIPT}" ]] || fail "missing source script at ${SOURCE_SCRIPT}"

if [[ -f "${TARGET_DIR}/${RUNTIME_NAME}" && "${REINSTALL_SAME_VERSION}" -eq 0 ]]; then
    print_warn "${RUNTIME_NAME} ${RELEASE_VERSION} is already installed at ${TARGET_DIR}/${RUNTIME_NAME}."
    if prompt_yes_no "Reinstall ${RELEASE_VERSION}? [y/N] "; then
        REINSTALL_SAME_VERSION=1
    else
        print_info "No reinstall is required."
        print_test_notice
        exit 0
    fi
fi

mkdir -p "${TARGET_DIR}"
install -m 0755 "${SOURCE_SCRIPT}" "${TARGET_DIR}/${RUNTIME_NAME}"

if [[ "${REINSTALL_SAME_VERSION}" -eq 1 ]]; then
    print_ok "Reinstalled ${TARGET_DIR}/${RUNTIME_NAME}"
else
    print_ok "Installed ${TARGET_DIR}/${RUNTIME_NAME}"
fi
print_test_notice
