require_relative "../helpers/app"

module Fastlane
  module Actions
    class AnalyzeArtifactsAction < Action
      def self.run(params)
        bundletool_binary_path = params[:bundletool_binary_path]
        aapt_binary_path = params[:aapt_binary_path]
        artifact_path = params[:artifact_path]

        if is_app_bundle?(artifact_path, bundletool_binary_path)
          artifact_type = "AAB"
          build_type = BuildType::RELEASE
          package_name = get_bundle_manifest_property(artifact_path, "package", bundletool_binary_path)
          version_code = get_bundle_manifest_property(artifact_path, "android:versionCode", bundletool_binary_path)
          version_name = get_bundle_manifest_property(artifact_path, "android:versionName", bundletool_binary_path)
        else
          artifact_type = "APK"
          build_type = is_apk_debuggable?(artifact_path, aapt_binary_path) ? BuildType::DEBUG : BuildType::RELEASE
          package_name = get_apk_manifest_property(artifact_path, "name", aapt_binary_path)
          version_code = get_apk_manifest_property(artifact_path, "versionCode", aapt_binary_path)
          version_name = get_apk_manifest_property(artifact_path, "versionName", aapt_binary_path)
        end

        build_flavor = App.get_build_flavor(package_name)
        build_info = {
          package_name: package_name,
          artifact_type: artifact_type,
          build_type: build_type,
          build_flavor: build_flavor,
          firebase_app_id: App.get_firebase_id(build_flavor),
          **other_action.build_version(
            build_flavor: build_flavor,
            version_name: version_name,
            version_code: version_code
          )
        }
        PrettyTable.print(data: build_info, title: "Build Info")
        build_info
      end

      def self.is_app_bundle?(artifact_path, bundletool_binary_path)
        Actions.sh "#{bundletool_binary_path} validate --bundle=#{artifact_path} &>/dev/null", log: true do |status, result, command|
          status.success?
        end
      end

      def self.is_apk_debuggable?(apk_path, aapt_binary_path)
        result = `#{aapt_binary_path} dump badging #{apk_path} | grep -c application-debuggable`.strip
        if result == "1"
          true
        elsif result == "0"
          false
        else
          UI.user_error!("Failed to determine if APK is debuggable: #{result}")
        end
      end

      def self.get_bundle_manifest_property(bundle_path, property_name, bundletool_binary_path)
        Actions.sh "#{bundletool_binary_path} dump manifest --bundle #{bundle_path} --xpath /manifest/@#{property_name}", log: true do |status, result, command|
          unless status.success?
            UI.user_error!("Command #{command} (pid #{status.pid}) failed with status #{status.exitstatus}")
          end
          result.strip
        end
      end

      def self.get_apk_manifest_property(apk_path, property_name, aapt_binary_path)
        props = Actions.sh "#{aapt_binary_path} dump badging #{apk_path} | head -1", log: true do |status, result, command|
          unless status.success?
            UI.user_error!("Command #{command} (pid #{status.pid}) failed with status #{status.exitstatus}")
          end
          unless result.strip.start_with?("package: name=")
            UI.user_error!("Command #{command} (pid #{status.pid}) failed with status #{status.exitstatus}")
          end
          result.strip.gsub("package: ", "").split(" ").map do |prop|
            key, value = prop.split("=")
            [key, value[1..-2]]
          end.to_h
        end
        props[property_name]
      end

      def self.description
        "Returns the app bundle manifest properties"
      end

      def self.available_options
        [
          FastlaneCore::ConfigItem.new(key: :artifact_path,
            description: "Path to the artifact file (APK or AAB)",
            type: String,
            verify_block: proc do |value|
              UI.user_error!("Artifact path must be valid") unless File.exist?(value)
            end),
          FastlaneCore::ConfigItem.new(key: :bundletool_binary_path,
            description: "Path to the bundletool binary",
            type: String,
            default_value: "tools/bundletool.sh",
            verify_block: proc do |value|
              UI.user_error!("Bundletool binary path must be valid") unless File.exist?(value)
            end),
          FastlaneCore::ConfigItem.new(key: :aapt_binary_path,
            description: "Path to the aapt binary",
            type: String,
            default_value: "tools/aapt.sh",
            verify_block: proc do |value|
              UI.user_error!("Aapt binary path must be valid") unless File.exist?(value)
            end)
        ]
      end

      def self.authors
        ["Suno"]
      end

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