require_relative "../helpers/config"

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
          case params[:distribution_channel]
          when DistributionChannel::FIREBASE
            max_firebase_version_code(build_flavor)
          when DistributionChannel::TESTFLIGHT
            max_testflight_version_code(build_flavor)
          end
        rescue => e
          retries += 1
          if retries <= max_retries
            delay = base_delay * (2**(retries - 1))
            UI.message("Failed to fetch version codes: #{e}".red)
            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("Checking Firebase versions codes for build flavor '#{build_flavor}'...")
        version_code = other_action.firebase_app_distribution_get_latest_release(
          googleservice_info_plist_path: BuildConfig.for(build_flavor)[:google_services_plist],
          service_credentials_json_data: other_action.firebase_credentials
        )&.[](:buildVersion)&.to_i
        if version_code.nil?
          UI.message("No builds were found in Firebase for build flavor '#{build_flavor}'")
          return 0
        end
        UI.message("Found version code #{version_code} in Firebase for build flavor '#{build_flavor}'")
        version_code
      end

      def self.max_testflight_version_code(build_flavor)
        UI.important("Checking TestFlight versions codes for build flavor '#{build_flavor}'...")

        build_config = BuildConfig.for(build_flavor)
        Spaceship::ConnectAPI.token = Spaceship::ConnectAPI::Token.from(hash: other_action.testflight_credentials)

        app = Spaceship::ConnectAPI::App.find(build_config[:app_identifier])
        UI.user_error!("Could not find app with bundle identifier #{build_config[:app_identifier]}") if app.nil?

        recent_builds = Spaceship::ConnectAPI.get_builds(
          filter: {
            "app": app.id,
            "preReleaseVersion.platform": Spaceship::ConnectAPI::Platform.map(lane_context[SharedValues::PLATFORM_NAME])
          },
          sort: "-uploadedDate",
          includes: "preReleaseVersion",
        ).map do |build|
          {
            version_code: build.version.to_s.split(".").first&.to_i,
            version_name: build.pre_release_version&.version&.to_s,
            uploaded_date: build.uploaded_date,
            processing_state: build.processing_state,
          }
        end.reject { |build| build[:version_code].nil? }

        if recent_builds.empty?
          UI.message("No builds were found in TestFlight for build flavor '#{build_flavor}'")
          return 0
        end

        PrettyTable.print(
          data: recent_builds,
          title: "Recent Builds",
        )

        version_code = recent_builds.max_by { |build| build[:version_code] }[:version_code]
        UI.message("Found version code #{version_code} in TestFlight for build flavor '#{build_flavor}'")
        version_code
      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: :distribution_channel,
            description: "Distribution channel (#{DistributionChannel::ALL.join(", ")})",
            verify_block: proc do |value|
              unless value && DistributionChannel::ALL.include?(value.to_s.strip.downcase)
                UI.user_error!("Channel must be one of: #{DistributionChannel::ALL.join(", ")}")
              end
            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 == :ios
      end
    end
  end
end
