# This file contains the fastlane.tools configuration
# You can find the documentation at https://docs.fastlane.tools
#
# For a list of all available actions, check out
#
#     https://docs.fastlane.tools/actions
#
# For a list of all available plugins, check out
#
#     https://docs.fastlane.tools/plugins/available-plugins
#

# Uncomment the line if you want fastlane to automatically update itself
# update_fastlane

require "shellwords"
require "tmpdir"

default_platform(:ios)

platform :ios do
  def project_root
    File.expand_path("../..", __dir__)
  end

  # tool/release.sh exports an App Store Connect key; with it these lanes run
  # with nobody at the keyboard, and without it they fall back to the
  # interactive Apple ID login they have always used.
  def asc_key
    return nil unless ENV["ASC_KEY_ID"] && ENV["ASC_KEY_P8"]

    app_store_connect_api_key(
      key_id: ENV.fetch("ASC_KEY_ID"),
      issuer_id: ENV.fetch("ASC_ISSUER_ID"),
      key_content: ENV.fetch("ASC_KEY_P8"),
      is_key_content_base64: true,
      in_house: false,
    )
  end

  # pubspec's +build is a floor, not the last word: TestFlight knows what it
  # has already accepted, and a duplicate number is refused outright. So a
  # release no longer depends on remembering `make bump` first — bump when the
  # version should change, and the build number takes care of itself.
  def next_build_number(key)
    return ENV.fetch("RELEASE_BUILD", "1").to_i if key.nil?

    latest = latest_testflight_build_number(
      api_key: key,
      app_identifier: "com.meshcore.sar.meshcoreSarApp",
      version: ENV["RELEASE_VERSION"],
      initial_build_number: 0,
    )
    [ENV.fetch("RELEASE_BUILD", "0").to_i, latest + 1].max
  end

  # gym has no api_key option — it shells out to xcodebuild, so the key goes in
  # as authentication flags pointing at a file. Only the archive needs them:
  # gym adds the same flags to the export itself, and xcodebuild rejects a
  # repeated -authenticationKeyPath.
  def with_archive_args(build_number = nil)
    return yield(nil) unless ENV["ASC_KEY_ID"] && ENV["ASC_KEY_P8"]

    path = File.join(Dir.tmpdir, "AuthKey_#{ENV.fetch('ASC_KEY_ID')}.p8")
    File.binwrite(path, ENV.fetch("ASC_KEY_P8").unpack1("m"))
    File.chmod(0o600, path)
    args = [
      "-allowProvisioningUpdates",
      "-authenticationKeyPath", Shellwords.escape(path),
      "-authenticationKeyID", Shellwords.escape(ENV.fetch("ASC_KEY_ID")),
      "-authenticationKeyIssuerID", Shellwords.escape(ENV.fetch("ASC_ISSUER_ID")),
    ]
    # A build setting on the command line outranks any xcconfig, so the number
    # the caller decided survives the archive regenerating Generated.xcconfig.
    if ENV["RELEASE_VERSION"]
      args << "FLUTTER_BUILD_NAME=#{ENV.fetch('RELEASE_VERSION')}"
      args << "FLUTTER_BUILD_NUMBER=#{build_number}" if build_number
    end
    begin
      yield(args.join(" "))
    ensure
      File.delete(path) if File.exist?(path)
    end
  end

  def beta_app_info
    {
      "en-US" => {
        description: "Field-ready SAR coordination over MeshCore with chat, voice, images, offline maps, and live team context.",
        feedback_email: "hey@dz0ny.dev",
        marketing_url: "https://github.com/dz0ny/meshcore-sar",
        privacy_policy_url: "https://github.com/dz0ny/meshcore-sar"
      }
    }
  end

  def beta_build_info
    {
      "en-US" => {
        whats_new: "Test MeshCore SAR field coordination flows: messaging, maps, contacts, voice, images, and SAR markers."
      }
    }
  end

  desc "Push a new release build to the App Store"
  lane :release do
    key = asc_key
    build = next_build_number(key)
    UI.message("building #{ENV['RELEASE_VERSION'] || 'pubspec version'} (#{build})")
    with_archive_args(build) { |args| build_app(workspace: "Runner.xcworkspace", scheme: "Runner", xcargs: args) }
    upload_to_testflight(
      api_key: key,
      skip_waiting_for_build_processing: true,
      localized_app_info: beta_app_info,
      localized_build_info: beta_build_info,
      changelog: "Test MeshCore SAR field coordination flows: messaging, maps, contacts, voice, images, and SAR markers."
    )
  end

  desc "Push a new beta build to TestFlight"
  lane :beta do
    key = asc_key
    build = next_build_number(key)
    UI.message("building #{ENV['RELEASE_VERSION'] || 'pubspec version'} (#{build})")
    with_archive_args(build) { |args| build_app(workspace: "Runner.xcworkspace", scheme: "Runner", xcargs: args) }
    upload_to_testflight(
      api_key: key,
      skip_waiting_for_build_processing: true,
      localized_app_info: beta_app_info,
      localized_build_info: beta_build_info,
      changelog: "Test MeshCore SAR field coordination flows: messaging, maps, contacts, voice, images, and SAR markers."
    )
  end

  desc "Capture iOS screenshots for App Store Connect"
  lane :screenshots do
    sh("cd #{project_root} && scripts/take_screenshots.sh --ios")
  end

  desc "Upload App Store screenshots"
  lane :store_assets do
    upload_to_app_store(
      api_key: asc_key,
      skip_binary_upload: true,
      skip_metadata: true,
      skip_screenshots: false,
      submit_for_review: false,
      force: true
    )
  end
end
