#!/bin/sh
# MFTPlus install script
# Usage:
#   curl -fsSL https://releases.mftplus.co.za/install.sh | sh
#   curl -fsSL https://releases.mftplus.co.za/install.sh | sh -s -- --version v0.7.0
#   curl -fsSL https://releases.mftplus.co.za/install.sh | sh -s -- --dry-run
#   curl -fsSL https://releases.mftplus.co.za/install.sh | sh -s -- --prefix ~/.local
#   curl -fsSL https://releases.mftplus.co.za/install.sh | sh -s -- --uninstall
#   curl -fsSL https://releases.mftplus.co.za/install.sh | sh -s -- --binary mft-agent-cli

set -e
unset CDPATH

# ---- constants ----
RELEASES_BASE="${RELEASES_BASE:-https://releases.mftplus.co.za}"
DEFAULT_VERSION="latest"

# ---- output helpers ----
info()  { printf '\033[32m[INFO]\033[0m %s\n' "$*"; }
warn()  { printf '\033[33m[WARN]\033[0m %s\n' "$*"; }
error() { printf '\033[31m[ERROR]\033[0m %s\n' "$*"; exit 1; }

# ---- platform detection ----
detect_platform() {
    OS=$(uname -s)
    ARCH=$(uname -m)

    case "$OS" in
        Linux)  OS="linux" ;;
        Darwin) OS="darwin" ;;
        *)      error "Unsupported OS: $OS (use PowerShell installer or manual download from https://releases.mftplus.co.za for Windows)" ;;
    esac

    case "$ARCH" in
        x86_64|amd64) ARCH="amd64" ;;
        aarch64|arm64) ARCH="aarch64" ;;
        *) error "Unsupported architecture: $ARCH (MFTPlus supports amd64 and aarch64/arm64)" ;;
    esac

    PLATFORM="${OS}_${ARCH}"
    info "Detected: $OS $ARCH"
}

# ---- set binary/archive names (after version is resolved) ----
set_names() {
    VER="${VERSION#v}"  # strip leading v

    # Different binaries have different platform availability
    case "$BINARY" in
        mftctl)
            # mftctl: Linux (amd64, aarch64), macOS (amd64, arm64, universal)
            if [ "$OS" = "darwin" ]; then
                # macOS: prefer universal, fall back to arch-specific
                BINARY_NAME="${BINARY}_${VER}_macos-universal"
                ARCHIVE_NAME="${BINARY_NAME}.tar.gz"
            else
                BINARY_NAME="${BINARY}_${VER}_${OS}_${ARCH}"
                ARCHIVE_NAME="${BINARY_NAME}.tar.gz"
            fi
            ;;
        mft-agent-cli)
            # mft-agent-cli: Linux (amd64, aarch64), macOS (universal only)
            if [ "$OS" = "darwin" ]; then
                BINARY_NAME="${BINARY}_${VER}_macos-universal"
            else
                BINARY_NAME="${BINARY}_${VER}_${OS}_${ARCH}"
            fi
            ARCHIVE_NAME="${BINARY_NAME}.tar.gz"
            ;;
        mft-discover)
            # mft-discover: Linux amd64 only
            if [ "$OS" = "darwin" ]; then
                error "mft-discover is not available for macOS (Linux and Windows only)"
            fi
            if [ "$ARCH" != "amd64" ]; then
                error "mft-discover is only available for Linux amd64 (not $ARCH)"
            fi
            BINARY_NAME="${BINARY}_${VER}_linux_amd64"
            ARCHIVE_NAME="${BINARY_NAME}.tar.gz"
            ;;
        *)
            error "Unknown binary: $BINARY (valid: mftctl, mft-agent-cli, mft-discover)"
            ;;
    esac
}

# ---- version resolution ----
resolve_version() {
    if [ "$VERSION" = "latest" ]; then
        # List the latest directory to get the version
        VERSION=$(curl -fsSL "${RELEASES_BASE}/" 2>/dev/null | grep -o 'v[0-9]\+\.[0-9]\+\.[0-9]\+' | sort -V | tail -1 || echo "")
        [ -z "$VERSION" ] && VERSION="v0.7.0"
    fi
    info "Version: $VERSION"
}

# ---- download + checksum ----
download_binary() {
    TMPDIR=$(mktemp -d) || error "Cannot create temp directory"
    trap 'rm -rf "$TMPDIR"' EXIT INT TERM

    DL_URL="${RELEASES_BASE}/${VERSION}/${ARCHIVE_NAME}"
    SUM_URL="${RELEASES_BASE}/${VERSION}/checksums.sha256"

    info "Downloading ${BINARY} from ${DL_URL} ..."
    curl -fsSL --show-error -o "${TMPDIR}/${ARCHIVE_NAME}" "$DL_URL" || \
        error "Download failed (${DL_URL})"

    # Extract archive (handles both flat and directory-wrapped archives)
    tar xzf "${TMPDIR}/${ARCHIVE_NAME}" -C "$TMPDIR" 2>/dev/null || \
        error "Failed to extract ${ARCHIVE_NAME}"

    # Find the binary (may be in a subdirectory)
    BIN_PATH=$(find "$TMPDIR" -name "${BINARY}" -type f 2>/dev/null | head -1)
    [ -z "$BIN_PATH" ] && error "Binary '${BINARY}' not found in archive"

    mv "$BIN_PATH" "${TMPDIR}/${BINARY}" 2>/dev/null || true
    chmod +x "${TMPDIR}/${BINARY}"

    # checksum verification (optional — skip if checksums unavailable)
    if SUM=$(curl -fsSL --show-error "$SUM_URL" 2>/dev/null); then
        EXPECTED=$(echo "$SUM" | grep "${ARCHIVE_NAME}" | awk '{print $1}')
        if [ -n "$EXPECTED" ]; then
            CHECK_CMD=""
            if command -v sha256sum >/dev/null 2>&1; then
                CHECK_CMD="sha256sum"
            elif command -v shasum >/dev/null 2>&1; then
                CHECK_CMD="shasum -a 256"
            fi

            if [ -n "$CHECK_CMD" ]; then
                ACTUAL=$($CHECK_CMD "${TMPDIR}/${ARCHIVE_NAME}" | awk '{print $1}')
                if [ "$ACTUAL" != "$EXPECTED" ]; then
                    error "Checksum mismatch!\n Expected: $EXPECTED\n Actual: $ACTUAL"
                fi
                info "Checksum verified"
            else
                warn "No sha256sum/shasum available — skipping checksum verification"
            fi
        else
            warn "Checksum for ${BINARY_NAME} not found in checksums.txt — skipping"
        fi
    else
        warn "Checksums unavailable at ${SUM_URL} — skipping verification"
    fi

    echo "$TMPDIR"
}

# ---- install ----
install_binary() {
    TMPDIR=$1

    mkdir -p "$PREFIX" 2>/dev/null || true
    TARGET="${PREFIX}/${BINARY}"

    if [ -w "$PREFIX" ]; then
        mv "${TMPDIR}/${BINARY}" "$TARGET"
    else
        warn "No write permission to ${PREFIX} — using sudo"
        sudo mv "${TMPDIR}/${BINARY}" "$TARGET"
    fi

    info "Installed to ${TARGET}"

    case ":$PATH:" in
        *":${PREFIX}:"*) ;;
        *) warn "${PREFIX} is not in PATH — add 'export PATH=\"${PREFIX}:\$PATH\"' to your shell profile" ;;
    esac
}

# ---- show version ----
show_version() {
    if command -v "${BINARY}" >/dev/null 2>&1; then
        "${BINARY}" --version 2>/dev/null || \
            info "${BINARY} installed (version unknown)"
    else
        warn "${BINARY} not found in PATH"
    fi
}

# ---- uninstall ----
uninstall() {
    FOUND=0
    for d in /usr/local/bin "$HOME/.local/bin"; do
        if [ -f "${d}/${BINARY}" ]; then
            info "Removing ${d}/${BINARY}"
            rm -f "${d}/${BINARY}" 2>/dev/null || sudo rm -f "${d}/${BINARY}"
            FOUND=1
        fi
    done

    if [ -f "/usr/local/bin/${BINARY}" ]; then
        rm -f "/usr/local/bin/${BINARY}" 2>/dev/null || sudo rm -f "/usr/local/bin/${BINARY}"
        FOUND=1
    fi

    [ $FOUND -eq 0 ] && warn "${BINARY} is not installed"
}

# ---- usage ----
usage() {
    cat <<EOF
MFTPlus Install Script

Install MFTPlus binaries (mftctl, mft-agent-cli, mft-discover) on Linux/macOS.

USAGE:
  curl -fsSL https://releases.mftplus.co.za/install.sh | sh [FLAGS]

FLAGS:
  --binary <name>       Binary to install: mftctl (default), mft-agent-cli, mft-discover
  --version <ver>       Version to install (default: latest)
  --prefix <path>       Install prefix (default: /usr/local/bin, or ~/.local/bin if no write access)
  --dry-run             Show what would be installed without downloading
  --uninstall           Remove the installed binary
  --help                Show this help

EXAMPLES:
  # Install latest mftctl (default)
  curl -fsSL https://releases.mftplus.co.za/install.sh | sh

  # Install specific version
  curl -fsSL https://releases.mftplus.co.za/install.sh | sh -s -- --version v0.7.0

  # Install mft-agent-cli
  curl -fsSL https://releases.mftplus.co.za/install.sh | sh -s -- --binary mft-agent-cli

  # Install to custom location
  curl -fsSL https://releases.mftplus.co.za/install.sh | sh -s -- --prefix ~/.local

  # Uninstall
  curl -fsSL https://releases.mftplus.co.za/install.sh | sh -s -- --uninstall

PLATFORM SUPPORT:
  mftctl:         Linux (amd64, aarch64), macOS (amd64, arm64, universal)
  mft-agent-cli:  Linux (amd64, aarch64), macOS (universal only)
  mft-discover:   Linux amd64 only

Windows users: Use PowerShell installer or download from https://releases.mftplus.co.za
EOF
}

# ---- main ----
main() {
    # Defaults
    BINARY="mftctl"
    VERSION="$DEFAULT_VERSION"
    PREFIX="/usr/local/bin"
    DRY_RUN=false
    UNINSTALL=false

    # Parse arguments
    while [ $# -gt 0 ]; do
        case "$1" in
            --binary)
                BINARY="$2"
                shift 2
                ;;
            --version)
                VERSION="$2"
                shift 2
                ;;
            --prefix)
                PREFIX="$2"
                shift 2
                ;;
            --dry-run)
                DRY_RUN=true
                shift
                ;;
            --uninstall)
                UNINSTALL=true
                shift
                ;;
            --help|-h)
                usage
                exit 0
                ;;
            *)
                error "Unknown option: $1 (try --help)"
                ;;
        esac
    done

    # Validate binary choice early
    case "$BINARY" in
        mftctl|mft-agent-cli|mft-discover) ;;
        *) error "Invalid binary: $BINARY (valid: mftctl, mft-agent-cli, mft-discover)" ;;
    esac

    if [ "$UNINSTALL" = true ]; then
        uninstall
        exit 0
    fi

    detect_platform
    resolve_version
    set_names

    if [ "$DRY_RUN" = true ]; then
        info "Dry run: would install ${BINARY} ${VERSION} for ${PLATFORM}"
        info "Download URL: ${RELEASES_BASE}/${VERSION}/${ARCHIVE_NAME}"
        info "Install target: ${PREFIX}/${BINARY}"
        exit 0
    fi

    TMPDIR=$(download_binary)
    install_binary "$TMPDIR"
    show_version

    info "Done! Try '${BINARY} --help' for usage."
}

main "$@"
