#!/bin/bash
# XPyCode macOS .pkg Post-Install Script
# Runs as root after the payload has been laid down.
# Mirrors the logic of installer/windows/innosetup/xpycode_postinstall.bat
# and the Pascal CurStepChanged(ssPostInstall) block in xpycode.iss.

set -uo pipefail

INSTALL_DIR="/Applications/XPyCode"
PYTHON_DIR="${INSTALL_DIR}/python"
PYTHON_EXE="${PYTHON_DIR}/bin/python3"
PLIST_LABEL="com.xpycode.master"
LAUNCH_ARGS="--log-level INFO"

echo "============================================================"
echo "  XPyCode Post-Install"
echo "============================================================"
echo "  Install dir : ${INSTALL_DIR}"
echo "  Python dir  : ${PYTHON_DIR}"
echo "============================================================"
echo ""

# ── Resolve the real user (not root) ─────────────────────────────────────────
if [ -n "${USER:-}" ] && [ "${USER}" != "root" ]; then
    REAL_USER="${USER}"
elif [ -n "${SUDO_USER:-}" ]; then
    REAL_USER="${SUDO_USER}"
else
    REAL_USER=$(stat -f "%Su" /dev/console 2>/dev/null || echo "")
fi

run_as_user() {
    if [ -n "${REAL_USER}" ] && [ "${REAL_USER}" != "root" ]; then
        sudo -u "${REAL_USER}" "$@"
    else
        "$@"
    fi
}

user_home() {
    if [ -n "${REAL_USER}" ] && [ "${REAL_USER}" != "root" ]; then
        eval echo "~${REAL_USER}"
    else
        echo "${HOME:-/var/root}"
    fi
}

USER_HOME=$(user_home)
echo "Real user : ${REAL_USER:-<unknown>}"
echo "User home : ${USER_HOME}"
echo ""

# ── Step 0: Configuration ─────────────────────────────────────────────────────
echo "[0/8] Collecting configuration..."
LOG_LEVEL=$(run_as_user osascript -e '
set logLevel to choose from list {"DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"} ¬
    with title "XPyCode Configuration" ¬
    with prompt "Select the log level:" ¬
    default items {"INFO"}
if logLevel is false then
    return "INFO"
else
    return item 1 of logLevel
end if
' 2>/dev/null || echo "INFO")

CREATE_LOG_FILE=$(run_as_user osascript -e '
set btn to button returned of (display dialog "Create a log file for XPyCode?" ¬
    with title "XPyCode Configuration" ¬
    buttons {"No", "Yes"} ¬
    default button "Yes")
return btn
' 2>/dev/null || echo "Yes")

CREATE_DESKTOP_SHORTCUT=$(run_as_user osascript -e '
set btn to button returned of (display dialog "Create a desktop shortcut?" ¬
    with title "XPyCode Configuration" ¬
    buttons {"No", "Yes"} ¬
    default button "Yes")
return btn
' 2>/dev/null || echo "Yes")

AUTOSTART=$(run_as_user osascript -e '
set btn to button returned of (display dialog "Start XPyCode automatically at login?" ¬
    with title "XPyCode Configuration" ¬
    buttons {"No", "Yes"} ¬
    default button "Yes")
return btn
' 2>/dev/null || echo "Yes")

LAUNCH_ARGS="--log-level ${LOG_LEVEL}"
if [ "${CREATE_LOG_FILE}" = "No" ]; then
    LAUNCH_ARGS="${LAUNCH_ARGS} --no-log-file"
fi
DESKTOP_SHORTCUT_ENABLED=true
if [ "${CREATE_DESKTOP_SHORTCUT}" = "No" ]; then
    DESKTOP_SHORTCUT_ENABLED=false
fi
AUTOSTART_ENABLED=true
if [ "${AUTOSTART}" = "No" ]; then
    AUTOSTART_ENABLED=false
fi

echo "  Log level        : ${LOG_LEVEL}"
echo "  Create log file  : ${CREATE_LOG_FILE}"
echo "  Desktop shortcut : ${CREATE_DESKTOP_SHORTCUT}"
echo "  Autostart        : ${AUTOSTART}"
echo "  Note: Manifest will be registered automatically (Microsoft Store not yet available)"
echo ""

# ── Step 1: Detect architecture ───────────────────────────────────────────────
echo "[1/8] Detecting architecture..."
ARCH=$(uname -m)
if [ "${ARCH}" = "arm64" ]; then
    echo "  Architecture: Apple Silicon (arm64)"
else
    echo "  Architecture: Intel (x86_64)"
fi
echo ""

# ── Step 2: Create installation directory ─────────────────────────────────────
echo "[2/8] Creating installation directory..."
mkdir -p "${INSTALL_DIR}"
mkdir -p "${PYTHON_DIR}"
echo "  Created: ${INSTALL_DIR}"
echo ""

# ── Step 3: Install dedicated Python via official macOS .pkg ─────────────────
echo "[3/8] Installing dedicated Python..."

# The postinstall helper script copies the installer_common.py logic.
# We download the official Python macOS pkg and install the framework into
# PYTHON_DIR so the Python is fully isolated from the system.
PYTHON_VERSION="3.13.2"
PYTHON_PKG_URL="https://www.python.org/ftp/python/${PYTHON_VERSION}/python-${PYTHON_VERSION}-macos11.pkg"
PYTHON_PKG_DOWNLOAD="/tmp/python-${PYTHON_VERSION}-macos11.pkg"

echo "  Downloading Python ${PYTHON_VERSION}..."
if curl -fsSL --retry 3 --retry-delay 5 -o "${PYTHON_PKG_DOWNLOAD}" "${PYTHON_PKG_URL}"; then
    echo "  Download complete: ${PYTHON_PKG_DOWNLOAD}"
else
    echo "  ERROR: Failed to download Python from ${PYTHON_PKG_URL}"
    exit 1
fi

echo "  Installing Python framework to root volume..."
# The macOS installer CLI requires -target to be a volume mount point (like /).
# The official python.org .pkg installs to /Library/Frameworks/Python.framework/.
PYTHON_MINOR_VERSION=$(echo "${PYTHON_VERSION}" | cut -d. -f1-2)
FRAMEWORK_SRC="/Library/Frameworks/Python.framework/Versions/${PYTHON_MINOR_VERSION}"
PYTHON_MODE="dedicated"

if installer -pkg "${PYTHON_PKG_DOWNLOAD}" -target /; then
    echo "  Installer succeeded"
else
    echo "  NOTE: installer returned non-zero; will attempt to use framework if already present"
fi

# Clean up downloaded pkg
rm -f "${PYTHON_PKG_DOWNLOAD}"

# Copy the installed framework into our isolated PYTHON_DIR
if [ -d "${FRAMEWORK_SRC}" ]; then
    echo "  Copying Python framework to ${PYTHON_DIR}..."
    mkdir -p "${PYTHON_DIR}"
    cp -R "${FRAMEWORK_SRC}" "${PYTHON_DIR}/Python.framework_${PYTHON_MINOR_VERSION}"

    # Create bin/ symlinks pointing into our copied framework
    mkdir -p "${PYTHON_DIR}/bin"
    FRAMEWORK_PYTHON="${PYTHON_DIR}/Python.framework_${PYTHON_MINOR_VERSION}/bin/python${PYTHON_MINOR_VERSION}"
    if [ -x "${FRAMEWORK_PYTHON}" ]; then
        ln -sf "${FRAMEWORK_PYTHON}" "${PYTHON_EXE}"
        chmod 0755 "${PYTHON_EXE}"
        echo "  Python executable: ${PYTHON_EXE} -> ${FRAMEWORK_PYTHON}"
    else
        echo "  WARNING: Could not find python${PYTHON_MINOR_VERSION} binary in copied framework"
    fi

    # Ensure pip is available (the framework install includes it)
    if [ -x "${PYTHON_EXE}" ] && ! "${PYTHON_EXE}" -m pip --version >/dev/null 2>&1; then
        echo "  Running ensurepip to bootstrap pip..."
        "${PYTHON_EXE}" -m ensurepip --upgrade 2>/dev/null || true
    fi
else
    echo "  NOTE: Framework not found at ${FRAMEWORK_SRC}; falling back to system Python"
fi

# Verify or fall back to system Python
if [ ! -x "${PYTHON_EXE}" ]; then
    echo "  Dedicated Python not available; trying system python3..."
    SYS_PYTHON=$(command -v python3 2>/dev/null || echo "")
    if [ -n "${SYS_PYTHON}" ]; then
        mkdir -p "${PYTHON_DIR}/bin"
        ln -sf "${SYS_PYTHON}" "${PYTHON_EXE}"
        chmod 0755 "${PYTHON_EXE}"
        PYTHON_MODE="system"
        echo "  Using system Python: ${SYS_PYTHON} -> ${PYTHON_EXE}"
    else
        echo "  ERROR: No Python 3 found. Installation cannot continue."
        exit 1
    fi
fi
echo ""

# ── Step 4: Upgrade pip + setuptools ─────────────────────────────────────────
echo "[4/8] Upgrading pip and setuptools..."
"${PYTHON_EXE}" -m pip install --upgrade --no-warn-script-location pip setuptools
echo ""

# ── Step 5: Install xpycode_master ────────────────────────────────────────────
echo "[5/8] Installing xpycode_master..."
"${PYTHON_EXE}" -m pip install --upgrade --no-warn-script-location xpycode_master
echo ""

# ── Step 6: Register SSL certificates ─────────────────────────────────────────
echo "[6/8] Registering SSL certificates..."
run_as_user "${PYTHON_EXE}" -c "from xpycode_master.addin_launcher.certificate_manager import CertificateManager; CertificateManager().ensure_certificates()" \
    && echo "  SSL certificates registered" \
    || echo "  WARNING: Could not register SSL certificates - they will be generated on first run"
echo ""

# ── Step 7: Save Python executable path to service config ────────────────────
echo "[7/8] Saving service configuration..."
"${PYTHON_EXE}" -c "from xpycode_master.utils.start_config import set_python_exe; set_python_exe('${PYTHON_EXE}')" \
    && echo "  Python exe path saved" \
    || echo "  WARNING: Could not save service config"
echo ""

# ── Step 8: Apply configuration ───────────────────────────────────────────────
# Delegates to xpycode_master --apply-config which handles: SSL certificates
# (idempotent), protocol handler registration, manifest registration,
# desktop shortcut, autostart (launchd plist) and saving start_config.json.
echo "[8/8] Applying configuration..."
NO_LOG_FILE_VAL=$([ "${CREATE_LOG_FILE}" = "No" ] && echo true || echo false)
CONFIG_JSON="{\"log_level\":\"${LOG_LEVEL}\",\"no_log_file\":${NO_LOG_FILE_VAL},\"skip_manifest\":false,\"desktop_shortcut\":${DESKTOP_SHORTCUT_ENABLED},\"autostart\":${AUTOSTART_ENABLED}}"

run_as_user "${PYTHON_EXE}" -m xpycode_master --apply-config "${CONFIG_JSON}" \
    && echo "  Configuration applied successfully" \
    || echo "  WARNING: Configuration apply failed (some settings may need manual setup)"
echo ""

# ── Create uninstaller script ────────────────────────────────────────────────
UNINSTALLER="${INSTALL_DIR}/Uninstall XPyCode.command"
cat > "${UNINSTALLER}" << 'UNINSTALL'
#!/bin/bash
# XPyCode Uninstaller
set -euo pipefail

PLIST_LABEL="com.xpycode.master"
INSTALL_DIR="/Applications/XPyCode"
PYTHON_EXE="${INSTALL_DIR}/python/bin/python3"
PLIST_PATH="${HOME}/Library/LaunchAgents/${PLIST_LABEL}.plist"
HANDLER_APP="${INSTALL_DIR}/XPyCodeHandler.app"
HANDLER_APP_USER="${HOME}/Applications/XPyCodeHandler.app"
DESKTOP_SHORTCUT="${HOME}/Desktop/XPyCode.command"

echo "============================================================"
echo "  XPyCode Uninstaller"
echo "============================================================"
echo ""

read -r -p "Are you sure you want to uninstall XPyCode? [y/N]: " confirm
if [[ ! "${confirm}" =~ ^[Yy]$ ]]; then
    echo "Uninstall cancelled."
    exit 0
fi

echo ""
echo "Uninstalling XPyCode..."
echo ""

echo "[1/3] Stopping XPyCode processes..."
pkill -f "xpycode_master" 2>/dev/null || true
sleep 1
echo "  Done"

echo "[2/3] Running XPyCode teardown..."
if [ -x "${PYTHON_EXE}" ]; then
    "${PYTHON_EXE}" -m xpycode_master --teardown \
        && echo "  Teardown complete" \
        || echo "  WARNING: Teardown had errors (continuing with manual cleanup)"
else
    echo "  Python not found; performing manual cleanup..."
    # Manual fallback: remove launchd plist
    if [ -f "${PLIST_PATH}" ]; then
        CURRENT_UID=$(id -u)
        launchctl bootout "gui/${CURRENT_UID}/${PLIST_LABEL}" 2>/dev/null \
            || launchctl unload "${PLIST_PATH}" 2>/dev/null \
            || true
        rm -f "${PLIST_PATH}" && echo "  Removed: ${PLIST_PATH}" || true
    fi
    # Remove protocol handler
    [ -d "${HANDLER_APP}" ] && rm -rf "${HANDLER_APP}" && echo "  Removed: ${HANDLER_APP}" || true
    [ -d "${HANDLER_APP_USER}" ] && rm -rf "${HANDLER_APP_USER}" && echo "  Removed: ${HANDLER_APP_USER}" || true
    # Remove desktop shortcut
    rm -f "${DESKTOP_SHORTCUT}" && echo "  Removed: ${DESKTOP_SHORTCUT}" || true
fi

echo "[3/3] Removing installation directory..."
if [ -d "${INSTALL_DIR}" ]; then
    sudo rm -rf "${INSTALL_DIR}" && echo "  Removed: ${INSTALL_DIR}" || echo "  WARNING: Could not remove ${INSTALL_DIR} (may need manual removal)"
fi

echo ""
echo "============================================================"
echo "  XPyCode has been uninstalled."
echo ""
echo "  User data directory (~/.xpycode) was NOT removed."
echo "  To remove all user data, run:  rm -rf ~/.xpycode"
echo "============================================================"
UNINSTALL

chmod 0755 "${UNINSTALLER}"
echo "  Created uninstaller: ${UNINSTALLER}"
echo ""

# ── Fix ownership of everything under INSTALL_DIR ────────────────────────────
echo "Setting ownership..."
if [ -n "${REAL_USER}" ] && [ "${REAL_USER}" != "root" ]; then
    chown -R "${REAL_USER}" "${INSTALL_DIR}" 2>/dev/null \
        && echo "  Owner: ${REAL_USER}" \
        || echo "  WARNING: chown failed (non-critical)"
fi
echo ""

echo "============================================================"
echo "  XPyCode Post-Install complete!"
echo "  XPyCode will start automatically at login."
echo "  Uninstaller: ${INSTALL_DIR}/Uninstall XPyCode.command"
echo "============================================================"
exit 0
