default_platform(:ios)

require "json"
require "tmpdir"
require "spaceship"
require "fileutils"

TARGET_VERSION = "1.0.21"
TARGET_BUILD = "116"
RELEASE_NOTES_PATH = File.expand_path("metadata/en-US/release_notes.txt", __dir__)
RELEASE_NOTES = File.read(RELEASE_NOTES_PATH).strip

def bao_secret_for_team(team_id)
  org_id = ENV["A0_ORG_ID"]
  UI.user_error!("A0_ORG_ID is not set; cannot read ASC credentials from bao") if org_id.to_s.empty?

  raw = sh("bao kv get -format=json secret/orgs/#{org_id}/credentials/app-store-connect/#{team_id}", log: false)
  JSON.parse(raw).fetch("data").fetch("data")
end

def api_key_json_path_for_team(team_id)
  path = File.join(Dir.tmpdir, "asc-fastlane-#{team_id}.json")
  File.write(path, bao_secret_for_team(team_id).fetch("api_key_json"))
  File.chmod(0o600, path)
  path
end

def asc_api_key_for_team(team_id)
  json = JSON.parse(bao_secret_for_team(team_id).fetch("api_key_json"))
  app_store_connect_api_key(
    key_id: json.fetch("key_id"),
    issuer_id: json.fetch("issuer_id"),
    key_content: json.fetch("key"),
    is_key_content_base64: false,
  )
end

def verify_pods_complete!(project_root)
  xcconfig = File.join(
    project_root,
    "ios/Pods/Target Support Files/ReactCodegen/ReactCodegen.release.xcconfig",
  )
  return if File.exist?(xcconfig)

  UI.user_error!(
    "pod install left ReactCodegen unconfigured (#{xcconfig} missing).\n" \
    "This usually means the codegen post-install hook aborted silently.\n" \
    "Recover with:\n" \
    "  cd ios && pod deintegrate && rm -rf Pods Podfile.lock && cd .. && npx pod-install ios\n" \
    "Then re-run this lane.",
  )
end

def ensure_app_store_version!(app_identifier:, version:)
  app = Spaceship::ConnectAPI::App.find(app_identifier)
  UI.user_error!("Could not find ASC app #{app_identifier}") unless app

  app.ensure_version!(version, platform: Spaceship::ConnectAPI::Platform::IOS)
  app.get_edit_app_store_version(platform: Spaceship::ConnectAPI::Platform::IOS)
end

def sync_release_notes!(app_identifier:, version:)
  app = Spaceship::ConnectAPI::App.find(app_identifier)
  UI.user_error!("Could not find ASC app #{app_identifier}") unless app

  version_model = app.get_app_store_versions(filter: { platform: Spaceship::ConnectAPI::Platform::IOS }).find do |candidate|
    candidate.version_string == version
  end
  UI.user_error!("Could not find App Store version #{version}") unless version_model

  localizations = version_model.get_app_store_version_localizations
  UI.user_error!("No App Store localizations found for version #{version}") if localizations.empty?

  localizations.each do |localization|
    localization.update(attributes: { whats_new: RELEASE_NOTES })
  end
end

platform :ios do
  lane :testflight do
    team_id = ENV["TEAM_ID"]
    app_id = ENV["APP_IDENTIFIER"]
    UI.user_error!("TEAM_ID is required") if team_id.to_s.empty?
    UI.user_error!("APP_IDENTIFIER is required") if app_id.to_s.empty?

    asc_api_key = asc_api_key_for_team(team_id)
    api_key_path = api_key_json_path_for_team(team_id)

    begin
      match(
        type: "appstore",
        app_identifier: app_id,
        team_id: team_id,
        readonly: true,
        api_key_path: api_key_path,
      )
    rescue => e
      UI.important("Readonly appstore match failed: #{e.message}")
      match(
        type: "appstore",
        app_identifier: app_id,
        team_id: team_id,
        readonly: false,
        api_key_path: api_key_path,
      )
    end

    sh("cd .. && npx expo prebuild --platform ios --clean --no-install")

    project_root = File.expand_path("..", __dir__)
    sh("mkdir -p #{project_root}/ios/build/generated/ios && touch #{project_root}/ios/build/generated/ios/RCTAppDependencyProvider.h")
    sh("cd .. && npx pod-install ios")
    verify_pods_complete!(project_root)

    workspace_path = Dir.glob("#{project_root}/ios/*.xcworkspace").first
    xcodeproj_path = Dir.glob("#{project_root}/ios/*.xcodeproj").first
    UI.user_error!("No iOS workspace generated by expo prebuild") unless workspace_path
    UI.user_error!("No iOS xcodeproj generated by expo prebuild") unless xcodeproj_path
    scheme = File.basename(workspace_path, ".xcworkspace")

    increment_version_number(
      version_number: TARGET_VERSION,
      xcodeproj: xcodeproj_path,
    )
    increment_build_number(
      build_number: TARGET_BUILD,
      xcodeproj: xcodeproj_path,
    )

    update_code_signing_settings(
      path: xcodeproj_path,
      use_automatic_signing: false,
      team_id: team_id,
      code_sign_identity: "Apple Distribution",
      profile_name: ENV["sigh_#{app_id}_appstore_profile-name"],
    )

    gym(
      workspace: workspace_path,
      scheme: scheme,
      export_method: "app-store",
      output_directory: "#{project_root}/build",
      output_name: "app.ipa",
      clean: true,
    )

    upload_to_testflight(
      api_key: asc_api_key,
      ipa: "#{project_root}/build/app.ipa",
      skip_waiting_for_build_processing: true,
    )
  end

  lane :submit_review do
    team_id = ENV["TEAM_ID"]
    app_id = ENV["APP_IDENTIFIER"]
    UI.user_error!("TEAM_ID is required") if team_id.to_s.empty?
    UI.user_error!("APP_IDENTIFIER is required") if app_id.to_s.empty?

    asc_api_key = asc_api_key_for_team(team_id)
    Spaceship::ConnectAPI.token = Spaceship::ConnectAPI::Token.from(hash: asc_api_key)
    ensure_app_store_version!(app_identifier: app_id, version: TARGET_VERSION)
    sync_release_notes!(app_identifier: app_id, version: TARGET_VERSION)

    upload_to_app_store(
      api_key: asc_api_key,
      app_identifier: app_id,
      app_version: TARGET_VERSION,
      build_number: TARGET_BUILD,
      skip_binary_upload: true,
      skip_metadata: true,
      skip_screenshots: true,
      submit_for_review: true,
      automatic_release: false,
      force: true,
      run_precheck_before_submit: false,
      precheck_include_in_app_purchases: false,
      submission_information: {
        export_compliance_uses_encryption: false,
      },
    )
  end
end