#!/usr/bin/env bash
#
# install-uadmin-from-release.sh – install uAdmin panel from ENC IT release server
#
# Fresh Ubuntu 24.04 VM (as root):
#   curl -fsSL https://enc-it.hr/uadmin/install-uadmin-from-release.sh | bash
#
# or download and run:
#   curl -fsSL https://enc-it.hr/uadmin/install-uadmin-from-release.sh -o /tmp/install-uadmin-from-release.sh
#   chmod +x /tmp/install-uadmin-from-release.sh
#   sudo bash /tmp/install-uadmin-from-release.sh
#
# Non-interactive (your own passwords, otherwise generated automatically):
#   sudo UADMIN_DB_PASS='secret' MYSQL_ROOT_PASS='root-secret' \
#     UADMIN_MANIFEST_URL='https://enc-it.hr/uadmin/stable.json' \
#     bash install-uadmin-from-release.sh
#
if grep -q $'\r' "${BASH_SOURCE[0]}" 2>/dev/null; then
    sed -i 's/\r$//' "${BASH_SOURCE[0]}"
    exec bash "${BASH_SOURCE[0]}" "$@"
fi

set -euo pipefail

readonly DEFAULT_MANIFEST_URL="${UADMIN_MANIFEST_URL:-https://enc-it.hr/uadmin/stable.json}"
readonly WORK_DIR="${UADMIN_INSTALL_WORK_DIR:-/var/tmp/uadmin-install}"
readonly UADMIN_USER="${UADMIN_USER:-uadmin}"

log() { echo "[install-from-release] $*" >&2; }
warn() { echo "[install-from-release][WARN] $*" >&2; }
fail() { echo "[install-from-release][ERROR] $*" >&2; exit 1; }

require_root() {
    [[ $EUID -eq 0 ]] || fail "Run as root (sudo)."
}

check_ubuntu() {
    [[ -f /etc/os-release ]] || fail "Only Ubuntu 24.04 is supported."
    # shellcheck source=/dev/null
    source /etc/os-release
    [[ "${ID}" == "ubuntu" && "${VERSION_ID}" == "24.04" ]] \
        || fail "Ubuntu 24.04 required (current: ${PRETTY_NAME:-?})."
    log "OS: ${PRETTY_NAME}"
}

ensure_download_tools() {
    if command -v curl &>/dev/null && command -v python3 &>/dev/null; then
        return
    fi
    log "Installing curl and python3..."
    export DEBIAN_FRONTEND=noninteractive
    apt-get update -qq
    apt-get install -y -qq curl ca-certificates python3
}

fetch_manifest() {
    local url="$1" dest="$2"
    log "Manifest: ${url}"
    curl -fsSL "$url" -o "$dest"
    [[ -s "$dest" ]] || fail "Manifest is empty: ${url}"
}

parse_manifest_field() {
    local file="$1" field="$2"
    python3 -c "import json,sys; d=json.load(open(sys.argv[1], encoding='utf-8-sig')); print(d.get(sys.argv[2],''))" "$file" "$field"
}

verify_sha256() {
    local file="$1" expected="$2"
    [[ -n "$expected" ]] || return 0
    local actual
    actual="$(sha256sum "$file" | awk '{print $1}')"
    [[ "$actual" == "$expected" ]] || fail "SHA256 mismatch (expected: ${expected}, got: ${actual})"
    log "SHA256 OK"
}

download_package() {
    local url="$1" dest="$2"
    log "Downloading package..."
    log "  URL: ${url}"
    curl -fsSL "$url" -o "$dest"
    [[ -s "$dest" ]] || fail "Downloaded package is empty: ${dest}"
}

extract_package() {
    local package="$1" dest="$2"
    mkdir -p "$dest"
    case "$package" in
        *.tar.gz|*.tgz)
            tar -xzf "$package" -C "$dest"
            ;;
        *.tar)
            tar -xf "$package" -C "$dest"
            ;;
        *)
            fail "Unsupported package format: ${package}"
            ;;
    esac
}

find_extracted_root() {
    local dir="$1" version="$2"
    if [[ -f "${dir}/uadmin-${version}/artisan" ]]; then
        echo "${dir}/uadmin-${version}"
        return
    fi
    if [[ -f "${dir}/artisan" ]]; then
        echo "${dir}"
        return
    fi
    local candidate
    candidate="$(find "$dir" -maxdepth 2 -name artisan -type f 2>/dev/null | head -1)"
    [[ -n "$candidate" ]] || fail "Laravel (artisan) not found in package."
    dirname "$candidate"
}

main() {
    require_root
    check_ubuntu
    ensure_download_tools

    if id "$UADMIN_USER" &>/dev/null && [[ -L "/home/${UADMIN_USER}/app" || -f "/home/${UADMIN_USER}/app/artisan" ]]; then
        fail "uAdmin appears to be already installed (/home/${UADMIN_USER}/app). Use update-uadmin.sh to upgrade."
    fi

    local manifest_file version package_url sha256 package_path extract_dir release_root

    rm -rf "$WORK_DIR"
    mkdir -p "$WORK_DIR"
    manifest_file="${WORK_DIR}/manifest.json"
    fetch_manifest "$DEFAULT_MANIFEST_URL" "$manifest_file"

    version="$(parse_manifest_field "$manifest_file" "latest")"
    package_url="$(parse_manifest_field "$manifest_file" "package_url")"
    sha256="$(parse_manifest_field "$manifest_file" "sha256")"

    [[ -n "$version" ]] || fail "Manifest is missing the latest field"
    [[ -n "$package_url" ]] || fail "Manifest is missing the package_url field"

    log "Version to install: ${version}"

    package_path="${WORK_DIR}/uadmin-${version}.tar.gz"
    extract_dir="${WORK_DIR}/extract"

    download_package "$package_url" "$package_path"
    verify_sha256 "$package_path" "$sha256"
    extract_package "$package_path" "$extract_dir"

    release_root="$(find_extracted_root "$extract_dir" "$version")"
    [[ -f "${release_root}/install-uadmin.sh" ]] || fail "Package is missing install-uadmin.sh"

    normalize_shell_scripts() {
        local root="$1"
        local f
        while IFS= read -r -d '' f; do
            sed -i 's/\r$//' "$f"
        done < <(find "$root" -type f -name '*.sh' -print0)
    }

    log "Normalizing shell scripts (LF)..."
    normalize_shell_scripts "$release_root"

    log "Running install-uadmin.sh from ${release_root}..."
    chmod +x "${release_root}/install-uadmin.sh"

    export UADMIN_RELEASE_SERVER="${DEFAULT_MANIFEST_URL%/*}"
    export UADMIN_INSTALLED_FROM_RELEASE="1"

    cd "$release_root"
    bash ./install-uadmin.sh

    log "Removing temporary files (${WORK_DIR})..."
    rm -rf "$WORK_DIR"

    log "Release server installation complete (v${version})."
}

main "$@"
