require_relative "../helpers/app"

module Fastlane
  module Actions
    class MaxVersionCodeAction < Action
      def self.run(params)
        build_flavor = params[:build_flavor]
        max_retries = params[:max_retries] || 5
        base_delay = 2
        UI.message("Looking up next version_code for build flavor #{build_flavor} ...")
        retries = 0
        begin
          DistributionChannel::ALL.flat_map do |channel|
            case channel
            when DistributionChannel::FIREBASE
              max_firebase_version_code(build_flavor)
            when DistributionChannel::PLAYSTORE
              max_playstore_version_code(build_flavor)
            end
          end.compact.max || 0
        rescue => e
          retries += 1
          if retries <= max_retries
            delay = base_delay * (2**(retries - 1))
            UI.message("Retrying in #{delay} seconds (attempt #{retries}/#{max_retries})...")
            sleep(delay)
            retry
          else
            UI.error("Failed to fetch version codes after #{max_retries} attempts")
            raise e
          end
        end
      end

      def self.max_firebase_version_code(build_flavor)
        UI.important("Looking up max Firebase version code for build flavor #{build_flavor}...")
        firebase_key = other_action.firebase_credentials
        firebase_app_id = App.get_firebase_id(build_flavor)
        other_action.firebase_app_distribution_get_latest_release(
          app: firebase_app_id,
          service_credentials_json_data: firebase_key
        )&.[](:buildVersion).to_i
      end

      def self.max_playstore_version_code(build_flavor)
        playstore_key = other_action.playstore_credentials
        package_name = App.get_package_name(build_flavor)
        PlayStoreTrack::ALL.map do |track|
          UI.important("Looking up max PlayStore '#{track}' version code for build flavor #{build_flavor}...")
          version_codes = other_action.google_play_track_version_codes(
            track: track,
            json_key_data: playstore_key,
            package_name: package_name
          ) || []
          UI.verbose("Fetched version codes from #{track}: #{version_codes}")
          version_codes.max
        rescue => e
          # Workaround for https://github.com/fastlane/fastlane/issues/21500
          if e.to_s.include?("undefined method `flat_map' for nil")
            UI.important("Track is empty: #{track}")
            nil
          elsif e.to_s.include?("Package not found")
            UI.important("Unknown package name: #{package_name}")
            nil
          else
            raise e
          end
        end.compact.max
      end

      def self.description
        "Returns the next available version code for the given app"
      end

      def self.available_options
        [
          FastlaneCore::ConfigItem.new(key: :build_flavor,
            description: "Build flavor to use (#{BuildFlavor::ALL.join(", ")})",
            type: String,
            default_value: BuildFlavor::PROD,
            verify_block: proc do |value|
              UI.user_error!("Invalid flavor (must be #{BuildFlavor::ALL.join(", ")})") unless BuildFlavor::ALL.include?(value)
            end),
          FastlaneCore::ConfigItem.new(key: :max_retries,
            description: "Maximum number of retries",
            env_name: "MAX_RETRIES",
            default_value: 5,
            type: Integer,
            optional: true)
        ]
      end

      def self.authors
        ["Suno"]
      end

      def self.is_supported?(platform)
        platform == :android
      end
    end
  end
end
