// Halflight Android release-signing config plugin.
//
// Background: `android/` is gitignored and regenerated on every
// `npx expo prebuild`. The default Expo template ships
// `release { signingConfig signingConfigs.debug }`, so a local
// `gradlew :app:bundleRelease` produces an APK signed with the world-known
// Android debug key (`7bb0d8c…`) — anyone could ship a same-signature update
// package. EAS Build solves this on its own infrastructure (it appends an
// `apply from: 'eas-build.gradle'` at remote build time that overrides the
// signing config) but local builds remain mis-signed.
//
// This plugin runs at prebuild time and:
//   1. Splices a `signingConfigs.release` block next to the existing `debug`.
//   2. Rewrites `release { signingConfig signingConfigs.debug }` to use
//      `signingConfigs.release` when the upload-key Gradle properties are
//      present, falling back to `signingConfigs.debug` otherwise. Dev
//      machines and CI without secrets keep working unchanged.
//
// To enable real release signing, generate the upload key once:
//
//   keytool -genkeypair -v -keystore halflight-upload.keystore \
//     -alias halflight-upload -keyalg RSA -keysize 2048 -validity 10000
//
// Then add to `~/.gradle/gradle.properties` (NEVER commit):
//
//   HALFLIGHT_UPLOAD_STORE_FILE=/Users/you/keys/halflight-upload.keystore
//   HALFLIGHT_UPLOAD_STORE_PASSWORD=…
//   HALFLIGHT_UPLOAD_KEY_ALIAS=halflight-upload
//   HALFLIGHT_UPLOAD_KEY_PASSWORD=…
//
// Then enrol the upload key in Google Play App Signing at first release.
//
// Verification:
//   gradlew :app:bundleRelease
//   apksigner verify --print-certs android/app/build/outputs/bundle/release/app-release.aab
// → should print OUR cert subject, not `androiddebugkey`.

const { withAppBuildGradle } = require('@expo/config-plugins')

const MARKER = '// halflight-release-signing-injected'

const SIGNING_CONFIG_BLOCK = `
        release {
            ${MARKER}
            if (project.hasProperty('HALFLIGHT_UPLOAD_STORE_FILE')) {
                storeFile file(project.findProperty('HALFLIGHT_UPLOAD_STORE_FILE'))
                storePassword project.findProperty('HALFLIGHT_UPLOAD_STORE_PASSWORD')
                keyAlias project.findProperty('HALFLIGHT_UPLOAD_KEY_ALIAS')
                keyPassword project.findProperty('HALFLIGHT_UPLOAD_KEY_PASSWORD')
            }
        }`

const RELEASE_SIGNING_CONFIG = `signingConfig project.hasProperty('HALFLIGHT_UPLOAD_STORE_FILE') ? signingConfigs.release : signingConfigs.debug`

function injectReleaseSigning(contents) {
  // Idempotent — re-running prebuild without `--clear` would otherwise
  // double-inject the block on every invocation.
  if (contents.includes(MARKER)) return contents

  // Step 1: splice a `release { … }` block into `signingConfigs { debug { … } }`.
  // Anchor on the close of the debug block; the Expo template's debug block
  // has no nested braces so the lazy `[\s\S]*?` cannot escape.
  const debugBlockEnd = /(signingConfigs\s*\{[\s\S]*?debug\s*\{[\s\S]*?\})/
  if (!debugBlockEnd.test(contents)) {
    throw new Error(
      'withReleaseSigning: could not locate signingConfigs.debug block in build.gradle — has the Expo Android template changed?'
    )
  }
  let out = contents.replace(debugBlockEnd, `$1${SIGNING_CONFIG_BLOCK}`)

  // Step 2: rewrite the buildTypes.release.signingConfig line to the
  // conditional. Anchor on `buildTypes { … release {` (NOT just `release {`)
  // because after step 1 the file has TWO `release {` blocks — the new
  // signingConfigs.release block, and buildTypes.release. Only the latter
  // contains a `signingConfig signingConfigs.debug` line that needs rewriting.
  const releaseBuildType = /(buildTypes\s*\{[\s\S]*?release\s*\{[\s\S]*?)signingConfig\s+signingConfigs\.debug/
  if (!releaseBuildType.test(out)) {
    throw new Error(
      'withReleaseSigning: could not locate buildTypes.release.signingConfig in build.gradle — has the Expo Android template changed?'
    )
  }
  out = out.replace(releaseBuildType, `$1${RELEASE_SIGNING_CONFIG}`)

  return out
}

function withReleaseSigning(config) {
  return withAppBuildGradle(config, (cfg) => {
    cfg.modResults.contents = injectReleaseSigning(cfg.modResults.contents)
    return cfg
  })
}

module.exports = withReleaseSigning
// Exported for tests; not part of the plugin contract.
module.exports.injectReleaseSigning = injectReleaseSigning
