require "plist"
require "tmpdir"
require_relative "../helpers/config"
require_relative "../helpers/pretty_table"

module Fastlane
  module Actions
    class AnalyzeArtifactsAction < Action
      def self.run(params)
        ipa_path = resolve_artifact_path(
          artifact_path: params[:artifact_path],
          run_url: params[:run_url],
          download_dir: params[:download_dir]
        )

        # Look up app identifier and version info from the ipa
        app_identifier = other_action.get_ipa_info_plist_value(ipa: ipa_path, key: "CFBundleIdentifier")
        version_name = other_action.get_ipa_info_plist_value(ipa: ipa_path, key: "CFBundleShortVersionString")
        version_code = other_action.get_ipa_info_plist_value(ipa: ipa_path, key: "CFBundleVersion")&.to_s&.split(".")&.first&.to_i

        # Look up build flavor based on app identifier
        build_flavor = BuildFlavor::ALL.find { |flavor| BuildConfig.for(flavor)[:app_identifier] == app_identifier }
        UI.user_error!("Unable to get build flavor for app identifier '#{app_identifier}'") if build_flavor.nil?
        build_config = BuildConfig.for(build_flavor)

        entitlements = nil

        # Look up build type based on the actual entitlements embedded in the signed app
        build_type = Dir.mktmpdir("#{build_config[:target]}-analyze") do |tmp_dir|
          Actions.sh("unzip -q #{Shellwords.escape(ipa_path)} -d #{Shellwords.escape(tmp_dir)}")
          app_bundle_path = File.join(tmp_dir, "Payload", "#{build_config[:target]}.app")
          UI.user_error!("Unable to locate app bundle at '#{app_bundle_path}' inside #{ipa_path}") unless File.directory?(app_bundle_path)

          entitlements_plist = Actions.sh("codesign -d --entitlements :- #{Shellwords.escape(app_bundle_path)} 2>/dev/null").strip
          UI.user_error!("Unable to read entitlements from '#{app_bundle_path}'") if entitlements_plist.empty?

          entitlements = Plist.parse_xml(entitlements_plist)
          UI.user_error!("Unable to parse entitlements plist from '#{app_bundle_path}'") if entitlements.nil?

          case entitlements&.[]("get-task-allow")&.to_s
          when "true"
            BuildType::DEBUG
          when "false"
            BuildType::RELEASE
          else
            UI.crash!("Invalid get-task-allow value in entitlements: #{entitlements}")
          end
        end

        build_info = {
          app_identifier: app_identifier,
          build_flavor: build_flavor,
          build_type: build_type,
          **other_action.build_version(
            build_flavor: build_flavor,
            version_name: version_name,
            version_code: version_code
          ),
          entitlements: entitlements,
        }
        PrettyTable.print(data: build_info, title: "Build Info")
        build_info
      end

      def self.resolve_artifact_path(artifact_path:, run_url:, download_dir:)
        if artifact_path
          unless File.exist?(artifact_path)
            UI.user_error!("Artifact path does not exist: #{artifact_path}")
          end
          return artifact_path
        end

        unless run_url
          UI.user_error!("Either artifact_path or run_url must be provided")
        end

        # Extract run ID from URL if it's a full GitHub Actions run URL
        # Example: https://github.com/suno-ai/app-ios/actions/runs/19447651271
        run_id = if run_url.match?(%r{/actions/runs/(\d+)})
          run_url.match(%r{/actions/runs/(\d+)})[1]
        else
          # Assume it's just a run ID
          run_url
        end

        UI.message("Downloading artifacts from run ID: #{run_id}")
        other_action.download_artifacts(
          run_id: run_id,
          download_dir: download_dir,
          extension: "ipa"
        )
      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 ipa file",
            short_option: "-p",
            type: String,
            optional: true,
            verify_block: proc do |value|
              UI.user_error!("Artifact path must be valid") unless File.exist?(value)
              UI.user_error!("Artifact path must be an ipa file") unless File.extname(value) == ".ipa"
            end),
          FastlaneCore::ConfigItem.new(key: :run_url,
            description: "GitHub Actions run URL or run ID to download artifacts from (e.g., https://github.com/suno-ai/app-ios/actions/runs/19447651271 or just 19447651271)",
            type: String,
            short_option: "-r",
            optional: true,
            verify_block: proc do |value|
              # Validate it's either a valid URL or a numeric run ID
              unless value.match?(%r{/actions/runs/\d+}) || value.match?(/^\d+$/)
                UI.user_error!("run_url must be either a GitHub Actions run URL (e.g., https://github.com/org/repo/actions/runs/12345) or a numeric run ID (e.g., 12345)")
              end
            end),
          FastlaneCore::ConfigItem.new(key: :download_dir,
            description: "Directory for downloaded artifacts when using run_url",
            default_value: File.expand_path("build/artifacts"),
            verify_block: proc do |value|
              UI.user_error!("Download directory cannot be empty") if value.nil? || value.empty?
              expanded = File.expand_path(value)
              if File.exist?(expanded) && !File.directory?(expanded)
                UI.user_error!("Download directory must be a directory")
              end
              FileUtils.mkdir_p(expanded)
            end),
        ]
      end

      def self.authors
        ["Suno"]
      end

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