#!/usr/bin/env bash
set -euo pipefail

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
BUILD_DIR="$ROOT_DIR/build"
DERIVED_DATA_DIR="$BUILD_DIR/derived-data"
ARTIFACTS_DIR="$ROOT_DIR/dist"
SCHEME="iKeyMon"
PROJECT="iKeyMon.xcodeproj"
CREDENTIALS_FILE="$ROOT_DIR/.signing.env"
VERSION_FILE="$ROOT_DIR/version.json"
DERIVED_DATA_ROOT="${DERIVED_DATA_ROOT:-$HOME/Library/Developer/Xcode/DerivedData}"

find_generate_appcast() {
  if [[ -n "${SPARKLE_GENERATE_APPCAST:-}" && -x "${SPARKLE_GENERATE_APPCAST}" ]]; then
    echo "$SPARKLE_GENERATE_APPCAST"
    return
  fi

  if [[ -d "$DERIVED_DATA_ROOT" ]]; then
    local candidate
    candidate="$(find "$DERIVED_DATA_ROOT" -path "*/SourcePackages/artifacts/sparkle/Sparkle/bin/generate_appcast" -type f 2>/dev/null | head -n 1 || true)"
    if [[ -n "$candidate" ]]; then
      echo "$candidate"
      return
    fi
  fi
}

generate_appcast() {
  local generator
  generator="$(find_generate_appcast)"
  local download_prefix=""
  if [[ -n "${SPARKLE_DOWNLOAD_BASE_TEMPLATE:-}" ]]; then
    download_prefix="${SPARKLE_DOWNLOAD_BASE_TEMPLATE//\{\{VERSION\}\}/$VERSION}"
  elif [[ -n "${SPARKLE_DOWNLOAD_BASE_URL:-}" ]]; then
    download_prefix="${SPARKLE_DOWNLOAD_BASE_URL%/}/v${VERSION}"
  fi

  # Ensure the version segment is present to match Gitea's /download/vX.Y.Z/ layout.
  if [[ -n "$download_prefix" ]] && [[ "$download_prefix" != *"/$VERSION"* ]]; then
    download_prefix="${download_prefix%/}/v${VERSION}"
  fi

  if [[ -z "$generator" || -z "${SPARKLE_EDDSA_KEY_FILE:-}" || -z "$download_prefix" ]]; then
    echo "ℹ️ Skipping Sparkle appcast generation (generator/key/download prefix not configured)."
    return
  fi

  local sparkle_cache="$HOME/Library/Caches/Sparkle_generate_appcast"
  rm -rf "$sparkle_cache"

  local output="$SPARKLE_APPCAST_OUTPUT"
  mkdir -p "$(dirname "$output")"
  local staging_dir
  staging_dir="$(mktemp -d)"
  cp "$ARTIFACTS_DIR"/*.zip "$staging_dir"/ 2>/dev/null || true

  if ! ls "$staging_dir"/*.zip >/dev/null 2>&1; then
    echo "ℹ️ Skipping Sparkle appcast generation (no ZIP archives found)."
    rm -rf "$staging_dir"
    return
  fi

  echo "🧾 Generating Sparkle appcast at $output"
  if ! "$generator" \
    --download-url-prefix "$download_prefix" \
    --ed-key-file "$SPARKLE_EDDSA_KEY_FILE" \
    -o "$output" \
    "$staging_dir"; then
    echo "⚠️ Sparkle appcast generation failed."
  fi
  rm -rf "$staging_dir"
}

sign_update_artifacts() {
  local signer
  signer="$(find "$DERIVED_DATA_ROOT" -path "*/SourcePackages/artifacts/sparkle/Sparkle/bin/sign_update" -type f 2>/dev/null | head -n 1 || true)"
  if [[ -z "$signer" || -z "${SPARKLE_EDDSA_KEY_FILE:-}" ]]; then
    echo "ℹ️ Skipping Sparkle signing (sign_update or SPARKLE_EDDSA_KEY_FILE missing)."
    return
  fi
  echo "🔑 Signing ${ZIP_NAME} for Sparkle feed"
  if ! "$signer" "${ARTIFACTS_DIR}/${ZIP_NAME}" --ed-key-file "${SPARKLE_EDDSA_KEY_FILE}"; then
    echo "⚠️ sign_update failed (continuing without signature)"
  fi
}

rewrite_appcast_urls() {
  : # no-op (old helper removed)
}

submit_for_notarization() {
  local target="$1"
  local label="$2"
  echo "📝 Submitting ${label} for notarization..."
  xcrun notarytool submit "$target" \
    --apple-id "$NOTARY_APPLE_ID" \
    --team-id "$NOTARY_TEAM_ID" \
    --password "$NOTARY_PASSWORD" \
    --wait
}

notarize_app_bundle() {
  local bundle="$1"
  local label="$2"
  if [[ -z "${NOTARY_APPLE_ID:-}" || -z "${NOTARY_TEAM_ID:-}" || -z "${NOTARY_PASSWORD:-}" ]]; then
    echo "ℹ️ Skipping notarization for ${label} (NOTARY_* variables not set)."
    return 1
  fi

  local tmp_dir
  tmp_dir="$(mktemp -d)"
  local archive="$tmp_dir/$(basename "$bundle").zip"
  ditto -c -k --keepParent "$bundle" "$archive"

  submit_for_notarization "$archive" "$label"
  xcrun stapler staple "$bundle"
  rm -rf "$tmp_dir"
}

notarize_artifact() {
  local artifact="$1"
  local label="$2"
  if [[ -z "${NOTARY_APPLE_ID:-}" || -z "${NOTARY_TEAM_ID:-}" || -z "${NOTARY_PASSWORD:-}" ]]; then
    echo "ℹ️ Skipping notarization for ${label} (NOTARY_* variables not set)."
    return 1
  fi
  submit_for_notarization "$artifact" "$label"
  xcrun stapler staple "$artifact"
}

if [[ -f "$CREDENTIALS_FILE" ]]; then
  set -a
  # shellcheck disable=SC1090
  source "$CREDENTIALS_FILE"
  set +a
fi

: "${SPARKLE_APPCAST_OUTPUT:=$ROOT_DIR/Sparkle/appcast.xml}"
export SPARKLE_APPCAST_OUTPUT

"$ROOT_DIR/scripts/sync_version.sh"

rm -rf "$DERIVED_DATA_DIR" "$ARTIFACTS_DIR"
mkdir -p "$BUILD_DIR" "$ARTIFACTS_DIR"

xcodebuild \
  -project "$ROOT_DIR/$PROJECT" \
  -scheme "$SCHEME" \
  -configuration Release \
  -derivedDataPath "$DERIVED_DATA_DIR" \
  CODE_SIGNING_ALLOWED=NO \
  clean build

APP_PATH="$DERIVED_DATA_DIR/Build/Products/Release/iKeyMon.app"
if [[ ! -d "$APP_PATH" ]]; then
  echo "❌ Failed to find built app at $APP_PATH"
  exit 1
fi

if [[ -n "${CODESIGN_IDENTITY:-}" ]]; then
  echo "🔏 Codesigning Sparkle framework..."
  codesign \
    --force \
    --options runtime \
    --timestamp \
    --sign "$CODESIGN_IDENTITY" \
    "$APP_PATH/Contents/Frameworks/Sparkle.framework"

  echo "🔏 Codesigning app with identity: $CODESIGN_IDENTITY"
  codesign \
    --deep \
    --force \
    --options runtime \
    --timestamp \
    --entitlements "$ROOT_DIR/iKeyMon.entitlements" \
    --sign "$CODESIGN_IDENTITY" \
    "$APP_PATH"
else
  echo "⚠️ Skipping codesign (CODESIGN_IDENTITY not set)."
fi

notarize_app_bundle "$APP_PATH" "iKeyMon.app"

STAGING_DIR=$(mktemp -d)
mkdir -p "$STAGING_DIR"
cp -R "$APP_PATH" "$STAGING_DIR/"
ln -s /Applications "$STAGING_DIR/Applications"
mkdir -p "$STAGING_DIR/.background"
cp "$ROOT_DIR/Assets/dmg_background.png" "$STAGING_DIR/.background/background.png"

VERSION="$(python3 - <<'PY' "$VERSION_FILE"
import json, sys
with open(sys.argv[1], "r", encoding="utf-8") as handle:
    data = json.load(handle)
print(data.get("marketing_version", "dev"))
PY
)"
ZIP_NAME="iKeyMon-${VERSION}.zip"
ditto -c -k --keepParent "$APP_PATH" "$ARTIFACTS_DIR/$ZIP_NAME"

DMG_NAME="iKeyMon-${VERSION}.dmg"
hdiutil create -volname "iKeyMon" -srcfolder "$STAGING_DIR" -ov -format UDZO "$ARTIFACTS_DIR/$DMG_NAME"

sign_update_artifacts

if [[ -n "${NOTARY_APPLE_ID:-}" && -n "${NOTARY_TEAM_ID:-}" && -n "${NOTARY_PASSWORD:-}" ]]; then
  notarize_artifact "$ARTIFACTS_DIR/$DMG_NAME" "$DMG_NAME"
else
  echo "⚠️ Skipping DMG notarization (NOTARY_* variables not set)."
fi
rm -rf "$STAGING_DIR"

generate_appcast

if [[ -n "${GITEA_TOKEN:-}" && -n "${GITEA_OWNER:-}" && -n "${GITEA_REPO:-}" ]]; then
  "$ROOT_DIR/scripts/publish_release.sh" "$VERSION" "$ARTIFACTS_DIR/$ZIP_NAME" "$ARTIFACTS_DIR/$DMG_NAME"
  "$ROOT_DIR/scripts/update_homebrew_tap.sh" "$VERSION" "$ARTIFACTS_DIR/$DMG_NAME"
else
  echo "ℹ️ Skipping Gitea release publishing (GITEA_* variables not fully set)."
  echo "ℹ️ Skipping Homebrew tap update because release publishing was skipped."
fi

echo "✅ Build complete. Artifacts:"
echo "   - $ARTIFACTS_DIR/$ZIP_NAME"
echo "   - $ARTIFACTS_DIR/$DMG_NAME"
