module Fastlane
  module Actions
    class ModifyServicesAction < Action
      def self.run(params)
        require 'produce'

        Produce.config = params

        Dir.chdir(FastlaneCore::FastlaneFolder.path || Dir.pwd) do
          require 'produce/service'
          services = params[:services]

          enabled_services = services.select { |_k, v| v == true || (v != false && v.to_s != 'off') }.map { |k, v| [k, v == true || v.to_s == 'on' ? 'on' : v] }.to_h
          disabled_services = services.select { |_k, v| v == false || v.to_s == 'off' }.map { |k, v| [k, 'off'] }.to_h

          enabled_services_object = self.service_object
          enabled_services.each do |k, v|
            enabled_services_object.__hash__[k] = true
            enabled_services_object.send("#{k}=", v)
          end
          Produce::Service.enable(enabled_services_object, nil) unless enabled_services.empty?

          disabled_services_object = self.service_object
          disabled_services.each do |k, v|
            disabled_services_object.__hash__[k] = true
            disabled_services_object.send("#{k}=", v)
          end
          Produce::Service.disable(disabled_services_object, nil) unless disabled_services.empty?
        end
      end

      def self.service_object
        service_object = Object.new
        service_object.class.module_eval { attr_accessor :__hash__ }
        service_object.__hash__ = {}
        Produce::DeveloperCenter::ALLOWED_SERVICES.keys.each do |service|
          name = self.services_mapping[service]
          service_object.class.module_eval { attr_accessor :"#{name}" }
        end
        service_object
      end

      def self.services_mapping
        {
          access_wifi: 'access_wifi',
          app_attest: 'app_attest',
          app_group: 'app_group',
          apple_pay: 'apple_pay',
          associated_domains: 'associated_domains',
          auto_fill_credential: 'auto_fill_credential',
          class_kit: 'class_kit',
          icloud: 'icloud',
          custom_network_protocol: 'custom_network_protocol',
          data_protection: 'data_protection',
          extended_virtual_address_space: 'extended_virtual_address_space',
          family_controls: 'family_controls',
          file_provider_testing_mode: 'file_provider_testing_mode',
          fonts: 'fonts',
          game_center: 'game_center',
          health_kit: 'health_kit',
          hls_interstitial_preview: 'hls_interstitial_preview',
          home_kit: 'home_kit',
          hotspot: 'hotspot',
          in_app_purchase: 'in_app_purchase',
          inter_app_audio: 'inter_app_audio',
          low_latency_hls: 'low_latency_hls',
          managed_associated_domains: 'managed_associated_domains',
          maps: 'maps',
          multipath: 'multipath',
          network_extension: 'network_extension',
          nfc_tag_reading: 'nfc_tag_reading',
          personal_vpn: 'personal_vpn',
          passbook: 'passbook',
          push_notification: 'push_notification',
          sign_in_with_apple: 'sign_in_with_apple',
          siri_kit: 'siri_kit',
          system_extension: 'system_extension',
          user_management: 'user_management',
          vpn_configuration: 'vpn_configuration',
          wallet: 'wallet',
          wireless_accessory: 'wireless_accessory',
          car_play_audio_app: 'car_play_audio_app',
          car_play_messaging_app: 'car_play_messaging_app',
          car_play_navigation_app: 'car_play_navigation_app',
          car_play_voip_calling_app: 'car_play_voip_calling_app',
          critical_alerts: 'critical_alerts',
          hotspot_helper: 'hotspot_helper',
          driver_kit: 'driver_kit',
          driver_kit_endpoint_security: 'driver_kit_endpoint_security',
          driver_kit_family_hid_device: 'driver_kit_family_hid_device',
          driver_kit_family_networking: 'driver_kit_family_networking',
          driver_kit_family_serial: 'driver_kit_family_serial',
          driver_kit_hid_event_service: 'driver_kit_hid_event_service',
          driver_kit_transport_hid: 'driver_kit_transport_hid',
          multitasking_camera_access: 'multitasking_camera_access',
          sf_universal_link_api: 'sf_universal_link_api',
          vp9_decoder: 'vp9_decoder',
          music_kit: 'music_kit',
          shazam_kit: 'shazam_kit',
          communication_notifications: 'communication_notifications',
          group_activities: 'group_activities',
          health_kit_estimate_recalibration: 'health_kit_estimate_recalibration',
          time_sensitive_notifications: 'time_sensitive_notifications'
        }
      end

      def self.allowed_services_description
        return Produce::DeveloperCenter::ALLOWED_SERVICES.map do |k, v|
          "#{k}: (#{v.join('|')})(:on|:off)(true|false)"
        end.join(", ")
      end

      def self.description
        'Modifies the services of the app created on Developer Portal'
      end

      def self.details
        [
          "The options are the same as `:enable_services` in the [produce action](https://docs.fastlane.tools/actions/produce/#parameters_1)"
        ].join("\n")
      end

      def self.available_options
        require 'produce'
        user = CredentialsManager::AppfileConfig.try_fetch_value(:apple_dev_portal_id)
        user ||= CredentialsManager::AppfileConfig.try_fetch_value(:apple_id)
        [
          FastlaneCore::ConfigItem.new(key: :username,
                                       short_option: "-u",
                                       env_name: "PRODUCE_USERNAME",
                                       description: "Your Apple ID Username",
                                       default_value: user,
                                       default_value_dynamic: true),
          FastlaneCore::ConfigItem.new(key: :app_identifier,
                                       env_name: "PRODUCE_APP_IDENTIFIER",
                                       short_option: "-a",
                                       description: "App Identifier (Bundle ID, e.g. com.krausefx.app)",
                                       code_gen_sensitive: true,
                                       default_value: CredentialsManager::AppfileConfig.try_fetch_value(:app_identifier),
                                       default_value_dynamic: true),
          FastlaneCore::ConfigItem.new(key: :services,
                                       display_in_shell: false,
                                       env_name: "PRODUCE_ENABLE_SERVICES",
                                       description: "Array with Spaceship App Services (e.g. #{allowed_services_description})",
                                       type: Hash,
                                       default_value: {},
                                       verify_block: proc do |value|
                                         allowed_keys = Produce::DeveloperCenter::ALLOWED_SERVICES.keys
                                         UI.user_error!("enable_services has to be of type Hash") unless value.kind_of?(Hash)
                                         value.each do |key, v|
                                           UI.user_error!("The key: '#{key}' is not supported in `enable_services' - following keys are available: [#{allowed_keys.join(',')}]") unless allowed_keys.include?(key.to_sym)
                                         end
                                       end),
          FastlaneCore::ConfigItem.new(key: :team_id,
                                       short_option: "-b",
                                       env_name: "PRODUCE_TEAM_ID",
                                       description: "The ID of your Developer Portal team if you're in multiple teams",
                                       optional: true,
                                       code_gen_sensitive: true,
                                       default_value: CredentialsManager::AppfileConfig.try_fetch_value(:team_id),
                                       default_value_dynamic: true,
                                       verify_block: proc do |value|
                                         ENV["FASTLANE_TEAM_ID"] = value.to_s
                                       end),
          FastlaneCore::ConfigItem.new(key: :team_name,
                                       short_option: "-l",
                                       env_name: "PRODUCE_TEAM_NAME",
                                       description: "The name of your Developer Portal team if you're in multiple teams",
                                       optional: true,
                                       code_gen_sensitive: true,
                                       default_value: CredentialsManager::AppfileConfig.try_fetch_value(:team_name),
                                       default_value_dynamic: true,
                                       verify_block: proc do |value|
                                         ENV["FASTLANE_TEAM_NAME"] = value.to_s
                                       end)
        ]
      end

      def self.author
        "bhimsenpadalkar"
      end

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

      def self.example_code
        [
          'modify_services(
            username: "test.account@gmail.com",
            app_identifier: "com.someorg.app",
            services: {
              push_notification: "on",
              associated_domains: "off",
              wallet: :on,
              apple_pay: :off,
              data_protection: true,
              multipath: false
            })'
        ]
      end

      def self.category
        :misc
      end
    end
  end
end
