#!/usr/bin/env bash
#
# Verification script for WolfPanel Agent releases.
# Validates that all required files exist under PUBLIC_ROOT.
#
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"

cd "${PROJECT_ROOT}"

# Locate and parse configuration file
CONFIG_PATH="deploy/release.conf"
if [ ! -f "${CONFIG_PATH}" ]; then
  echo "Error: Configuration file not found at ${CONFIG_PATH}!" >&2
  exit 1
fi

PUBLIC_ROOT=""
while IFS='=' read -r key value; do
  # Skip comments and empty lines
  [[ "$key" =~ ^#.* ]] && continue
  [[ -z "$key" ]] && continue
  
  if [ "$key" = "PUBLIC_ROOT" ]; then
    PUBLIC_ROOT=$(echo "$value" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' -e 's/^"//' -e 's/"$//' -e "s/^'//" -e "s/'$//")
  fi
done < "${CONFIG_PATH}"

if [ -z "${PUBLIC_ROOT}" ]; then
  echo "Error: PUBLIC_ROOT is not defined in ${CONFIG_PATH}!" >&2
  exit 1
fi

# Parse channel
CHANNEL="${1:-stable}"
if [[ "$CHANNEL" != "stable" && "$CHANNEL" != "beta" && "$CHANNEL" != "dev" ]]; then
  echo "Error: Invalid channel '$CHANNEL'. Must be stable, beta, or dev." >&2
  exit 1
fi

echo "Verifying WolfPanel Agent deployment at: ${PUBLIC_ROOT} for channel: ${CHANNEL}"

# Required files checklist
REQUIRED_FILES=(
  "${PUBLIC_ROOT}/install.sh"
  "${PUBLIC_ROOT}/uninstall.sh"
  "${PUBLIC_ROOT}/${CHANNEL}/latest.json"
  "${PUBLIC_ROOT}/${CHANNEL}/latest.tar.gz"
  "${PUBLIC_ROOT}/${CHANNEL}/checksums.txt"
)

ERRORS=0
for FILE in "${REQUIRED_FILES[@]}"; do
  if [ ! -f "${FILE}" ]; then
    echo "Verification Error: Required file missing -> ${FILE}" >&2
    ERRORS=$((ERRORS + 1))
  else
    echo "Verified: ${FILE} exists."
  fi
done

# Dynamic validation of latest.json
LATEST_JSON="${PUBLIC_ROOT}/${CHANNEL}/latest.json"
if [ -f "${LATEST_JSON}" ]; then
  echo "Validating ${LATEST_JSON} content..."
  
  # Helper to parse flat json fields.
  #
  # NOTE: under `set -o pipefail`, grep finding no match exits 1, and that
  # propagates through head/sed even though they succeed -- which would kill
  # this whole script (set -e) the instant an optional/absent field (e.g. the
  # deliberately-absent "url") is looked up, before any validation logic
  # below gets a chance to run. `|| true` neutralizes that.
  json_field() {
    local key="$1" file="$2"
    { grep -o "\"${key}\"[[:space:]]*:[[:space:]]*\"[^\"]*\"" "$file" || true; } \
      | head -n1 | sed -E 's/.*:[[:space:]]*"([^"]*)"/\1/'
  }

  # Helper to parse flat json numeric fields (supports quoted or unquoted digits)
  json_field_num() {
    local key="$1" file="$2"
    { grep -o "\"${key}\"[[:space:]]*:[[:space:]]*[0-9\"]*" "$file" || true; } \
      | head -n1 | sed -E 's/.*:[[:space:]]*"?([0-9]*)"?/\1/'
  }
  
  V_MANIFEST_VERSION=$(json_field_num manifest_version "${LATEST_JSON}")
  V_CHANNEL=$(json_field channel "${LATEST_JSON}")
  V_VERSION=$(json_field version "${LATEST_JSON}")
  V_FILE=$(json_field file "${LATEST_JSON}")
  V_SHA256=$(json_field sha256 "${LATEST_JSON}")
  V_SIGNATURE=$(json_field signature "${LATEST_JSON}")
  V_SIZE_BYTES=$(json_field_num size_bytes "${LATEST_JSON}")
  V_PUBLISHED_AT=$(json_field published_at "${LATEST_JSON}")
  V_URL=$(json_field url "${LATEST_JSON}")

  if [ "${V_MANIFEST_VERSION}" != "1" ] || [ -z "${V_VERSION}" ] || [ -z "${V_FILE}" ] || [ -z "${V_SHA256}" ] || [ -z "${V_SIGNATURE}" ] || [ -z "${V_CHANNEL}" ] || [ -z "${V_SIZE_BYTES}" ] || [ -z "${V_PUBLISHED_AT}" ]; then
    echo "Verification Error: latest.json is missing required fields or has invalid manifest_version!" >&2
    echo "  manifest_version: ${V_MANIFEST_VERSION} (expected 1)" >&2
    echo "  channel: ${V_CHANNEL}" >&2
    echo "  version: ${V_VERSION}" >&2
    echo "  file: ${V_FILE}" >&2
    echo "  sha256: ${V_SHA256}" >&2
    echo "  signature: ${V_SIGNATURE:0:20}..." >&2
    echo "  size_bytes: ${V_SIZE_BYTES}" >&2
    echo "  published_at: ${V_PUBLISHED_AT}" >&2
    ERRORS=$((ERRORS + 1))
  elif [ -n "${V_URL}" ]; then
    echo "Verification Error: latest.json must not contain a 'url' field (installers derive the URL from release_base/channel/file)!" >&2
    ERRORS=$((ERRORS + 1))
  elif [ "${V_CHANNEL}" != "${CHANNEL}" ]; then
    echo "Verification Error: manifest channel '${V_CHANNEL}' does not match requested channel '${CHANNEL}'!" >&2
    ERRORS=$((ERRORS + 1))
  else
    echo "latest.json fields look good."

    # Check if target file exists
    TARBALL_PATH="${PUBLIC_ROOT}/${CHANNEL}/${V_FILE}"
    if [ ! -f "${TARBALL_PATH}" ]; then
      echo "Verification Error: Tarball file not found at ${TARBALL_PATH}!" >&2
      ERRORS=$((ERRORS + 1))
    else
      echo "Verified: Referenced tarball ${V_FILE} exists."

      # Verify size_bytes
      echo "Verifying size_bytes of tarball..."
      if command -v stat >/dev/null 2>&1 && stat -c%s "${TARBALL_PATH}" >/dev/null 2>&1; then
        ACTUAL_SIZE=$(stat -c%s "${TARBALL_PATH}")
      elif command -v stat >/dev/null 2>&1 && stat -f%z "${TARBALL_PATH}" >/dev/null 2>&1; then
        ACTUAL_SIZE=$(stat -f%z "${TARBALL_PATH}")
      else
        ACTUAL_SIZE=$(wc -c < "${TARBALL_PATH}" | tr -d '[:space:]')
      fi

      if [ "${ACTUAL_SIZE}" != "${V_SIZE_BYTES}" ]; then
        echo "Verification Error: size_bytes mismatch!" >&2
        echo "  Expected: ${V_SIZE_BYTES}" >&2
        echo "  Actual:   ${ACTUAL_SIZE}" >&2
        ERRORS=$((ERRORS + 1))
      else
        echo "Verified: size_bytes matches (${ACTUAL_SIZE})."
      fi

      # Verify SHA-256
      echo "Verifying SHA-256 of tarball..."
      if command -v sha256sum >/dev/null 2>&1; then
        ACTUAL_SHA256=$(sha256sum "${TARBALL_PATH}" | awk '{print $1}')
      elif command -v shasum >/dev/null 2>&1; then
        ACTUAL_SHA256=$(shasum -a 256 "${TARBALL_PATH}" | awk '{print $1}')
      else
        ACTUAL_SHA256=$(openssl dgst -sha256 "${TARBALL_PATH}" | awk '{print $NF}')
      fi
      
      if [ "${ACTUAL_SHA256}" != "${V_SHA256}" ]; then
        echo "Verification Error: SHA-256 checksum mismatch!" >&2
        echo "  Expected: ${V_SHA256}" >&2
        echo "  Actual:   ${ACTUAL_SHA256}" >&2
        ERRORS=$((ERRORS + 1))
      else
        echo "Verified: SHA-256 checksum matches."
      fi
      
      # Verify Cryptographic Signature
      echo "Verifying cryptographic signature..."
      if command -v openssl >/dev/null 2>&1; then
        PUBKEY_TMP=$(mktemp)
        cat > "${PUBKEY_TMP}" <<'PEMEOF'
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr34uui+vpx2AqxiC4zsC
ifojuxRTqR7JzxjwgKlrs1Mmp1AEm/DlfP5ZbGqJept5SHSW1RAMt2cXSLVKQSaA
qSG4K01rn/A4UHAIVxymDD+VFrc7yeGdLmcg1EfkNjoikxVdPJxkHPHLHoKneo+Y
V45yBBz0gImJ5ByTntfaXW5TNBKD9brEz/XMLDFFO5taA7364Nz6DgQFKFeg+fig
4xCO66+Bb2qtuo0NBSHrgQtpUHthdschOgwtF+oOY6+jsByPqR+qG1V1XNPM90wm
RmZ7W6ET5IX4Wlyn+8zb6CjrbOEhwlRWKadz4vhGh96wIuMtLyM2q/FX0Ntz//to
ZQIDAQAB
-----END PUBLIC KEY-----
PEMEOF
        
        SIG_BIN_TMP=$(mktemp)
        # Helper to decode hex to bin
        decode_hex_to_bin() {
          local hex="$1" dest="$2"
          if command -v python3 >/dev/null 2>&1 && python3 --version >/dev/null 2>&1; then
            python3 -c 'import sys; sys.stdout.buffer.write(bytes.fromhex(sys.argv[1]))' "$hex" > "$dest"
          elif command -v python >/dev/null 2>&1 && python --version >/dev/null 2>&1; then
            python -c 'import sys; sys.stdout.buffer.write(bytes.fromhex(sys.argv[1]))' "$hex" > "$dest"
          elif command -v xxd >/dev/null 2>&1; then
            echo -n "$hex" | xxd -r -p > "$dest"
          else
            return 1
          fi
        }
        
        if decode_hex_to_bin "${V_SIGNATURE}" "${SIG_BIN_TMP}"; then
          if openssl dgst -sha256 -verify "${PUBKEY_TMP}" -signature "${SIG_BIN_TMP}" "${TARBALL_PATH}" >/dev/null 2>&1; then
            echo "Verified: Cryptographic signature is VALID."
          else
            echo "Verification Error: Cryptographic signature is INVALID!" >&2
            ERRORS=$((ERRORS + 1))
          fi
        else
          echo "Verification Error: Failed to decode signature hex!" >&2
          ERRORS=$((ERRORS + 1))
        fi
        
        rm -f "${PUBKEY_TMP}" "${SIG_BIN_TMP}"
      else
        echo "Warning: openssl not found, skipping signature verification."
      fi
    fi
  fi
fi

if [ ${ERRORS} -ne 0 ]; then
  echo "Verification failed with ${ERRORS} errors!" >&2
  exit 1
fi

echo "Verification successful! All required files and metadata are correct."
echo ""
echo "=== Final Public Directory Tree ==="
if command -v find >/dev/null 2>&1; then
  find "${PUBLIC_ROOT}" -maxdepth 3
else
  ls -laR "${PUBLIC_ROOT}"
fi
