# frozen_string_literal: true

module UiRules
  class BinStorageRuleRule < Base
    def generate_rules # rubocop:disable Metrics/AbcSize
      @repo = MasterfilesApp::LocationRepo.new
      @farm_repo = MasterfilesApp::FarmRepo.new
      @cultivar_repo = MasterfilesApp::CultivarRepo.new
      @fruit_repo = MasterfilesApp::FruitRepo.new
      @commodity_repo = MasterfilesApp::CommodityRepo.new
      @messcada_repo = MesscadaApp::MesscadaRepo.new
      make_form_object
      apply_form_values

      common_values_for_fields common_fields

      set_show_fields if %i[show].include? @mode
      set_set_storage_rule_fields if @mode == :set_storage_rule
      add_behaviours if %i[new edit set_storage_rule].include? @mode

      form_name 'bin_storage_rule'
    end

    def set_show_fields # rubocop:disable Metrics/AbcSize
      storage_rule_type_id_label = @repo.get(:storage_rule_types, :rule_type_name, @form_object.storage_rule_type_id)
      cultivar_group_id_label = @repo.get(:cultivar_groups, :cultivar_group_code, @form_object.cultivar_group_id)
      cultivar_id_label = @repo.get(:cultivars, :cultivar_name, @form_object.cultivar_id)
      farm_id_label = @repo.get(:farms, :farm_code, @form_object.farm_id)
      orchard_id_label = @repo.get(:orchards, :orchard_code, @form_object.orchard_id)
      main_cold_treatment_id_label = @repo.get(:treatments, :treatment_code, @form_object.cold_treatment_id)
      main_ripeness_treatment_id_label = @repo.get(:treatments, :treatment_code, @form_object.ripeness_treatment_id)
      rmt_code_id_label = @repo.get(:rmt_codes, :rmt_code, @form_object.rmt_code_id)
      actual_cold_treatment_id_label = @repo.get(:treatments, :treatment_code, @form_object.actual_cold_treatment_id)
      actual_ripeness_treatment_id_label = @repo.get(:treatments, :treatment_code, @form_object.actual_ripeness_treatment_id)
      rmt_class_id_label = @repo.get(:rmt_classes, :rmt_class_code, @form_object.rmt_class_id)
      rmt_size_id_label = @repo.get(:rmt_sizes, :size_code, @form_object.rmt_size_id)
      colour_percentage_id_label = @repo.get(:colour_percentages, :colour_percentage, @form_object.colour_percentage_id)
      fields[:description] = { renderer: :label }
      fields[:storage_rule_type_id] = { renderer: :label, with_value: storage_rule_type_id_label, caption: 'Storage Rule Type' }
      fields[:cultivar_group_id] = { renderer: :label, with_value: cultivar_group_id_label, caption: 'Cultivar Group' }
      fields[:cultivar_id] = { renderer: :label, with_value: cultivar_id_label, caption: 'Cultivar' }
      fields[:farm_id] = { renderer: :label, with_value: farm_id_label, caption: 'Farm' }
      fields[:orchard_id] = { renderer: :label, with_value: orchard_id_label, caption: 'Orchard' }
      fields[:main_cold_treatment_id] = { renderer: :label, with_value: main_cold_treatment_id_label, caption: 'Cold Treatment' }
      fields[:main_ripeness_treatment_id] = { renderer: :label, with_value: main_ripeness_treatment_id_label, caption: 'Ripeness Treatment' }
      fields[:rmt_code_id] = { renderer: :label, with_value: rmt_code_id_label, caption: 'Rmt Code' }
      fields[:actual_cold_treatment_id] = { renderer: :label, with_value: actual_cold_treatment_id_label, caption: 'Actual Cold Treatment' }
      fields[:actual_ripeness_treatment_id] = { renderer: :label, with_value: actual_ripeness_treatment_id_label, caption: 'Actual Ripeness Treatment' }
      fields[:rmt_class_id] = { renderer: :label, with_value: rmt_class_id_label, caption: 'Rmt Class' }
      fields[:rmt_size_id] = { renderer: :label, with_value: rmt_size_id_label, caption: 'Rmt Size' }
      fields[:colour_percentage_id] = { renderer: :label, with_value: colour_percentage_id_label, caption: 'Colour Percentage' }
      fields[:active] = { renderer: :label, as_boolean: true }
    end

    def common_fields # rubocop:disable Metrics/AbcSize,  Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
      rule_type = @form_object.storage_rule_type_id.nil? ? {} : @repo.find_storage_rule_type(@form_object.storage_rule_type_id)
      {
        description: {},
        storage_rule_type_id: { renderer: :select,
                                options: @repo.for_select_storage_rule_types,
                                disabled_options: @repo.for_select_inactive_storage_rule_types,
                                prompt: 'Select Storage Rule Type',
                                caption: 'Storage Rule Type',
                                required: true },
        commodity_id: { renderer: :select,
                        options: MasterfilesApp::CommodityRepo.new.for_select_commodities,
                        disabled_options: MasterfilesApp::CommodityRepo.new.for_select_inactive_commodities,
                        prompt: 'ALL',
                        caption: 'Commodity',
                        searchable: true,
                        remove_search_for_small_list: false,
                        hide_on_load: rule_type[:commodity_id] ? false : true },
        cultivar_group_id: { renderer: :select,
                             options: @cultivar_repo.for_select_cultivar_groups,
                             disabled_options: @cultivar_repo.for_select_inactive_cultivar_groups,
                             prompt: 'ALL',
                             caption: 'Cultivar Group',
                             searchable: true,
                             remove_search_for_small_list: false,
                             hide_on_load: rule_type[:cultivar_group_id] ? false : true },
        cultivar_id: { renderer: :select,
                       options: @cultivar_repo.for_select_cultivars(where: { cultivar_group_id: @form_object.cultivar_group_id }),
                       disabled_options: @cultivar_repo.for_select_inactive_cultivars,
                       prompt: 'ALL',
                       caption: 'Cultivar',
                       searchable: true,
                       remove_search_for_small_list: false,
                       hide_on_load: rule_type[:cultivar_id] ? false : true },
        farm_id: { renderer: :select,
                   options: @farm_repo.for_select_farms,
                   disabled_options: @farm_repo.for_select_inactive_farms,
                   prompt: 'ALL',
                   caption: 'Farm',
                   searchable: true,
                   remove_search_for_small_list: false,
                   hide_on_load: rule_type[:farm_id] ? false : true },
        puc_id: { renderer: :select,
                  options: @farm_repo.for_select_pucs,
                  disabled_options: @farm_repo.for_select_inactive_pucs,
                  prompt: 'ALL',
                  caption: 'PUC',
                  searchable: true,
                  remove_search_for_small_list: false,
                  hide_on_load: rule_type[:puc_id] ? false : true },
        orchard_id: { renderer: :select,
                      options: @farm_repo.for_select_orchards,
                      disabled_options: @farm_repo.for_select_inactive_orchards,
                      prompt: 'ALL',
                      caption: 'Orchard',
                      searchable: true,
                      remove_search_for_small_list: false,
                      hide_on_load: rule_type[:orchard_id] ? false : true },
        main_cold_treatment_id: { renderer: :select,
                                  options: @messcada_repo.for_select_treatments_by_type(AppConst::COLD_TREATMENT),
                                  prompt: 'No Value',
                                  caption: 'Main Cold Treatment',
                                  searchable: true,
                                  remove_search_for_small_list: false,
                                  hide_on_load: rule_type[:main_cold_treatment_id] ? false : true },
        main_ripeness_treatment_id: { renderer: :select,
                                      options: @messcada_repo.for_select_treatments_by_type(AppConst::RIPENESS_TREATMENT),
                                      prompt: 'No Value',
                                      caption: 'Main Ripeness Treatment',
                                      searchable: true,
                                      remove_search_for_small_list: false,
                                      hide_on_load: rule_type[:main_ripeness_treatment_id] ? false : true },
        rmt_code_id: { renderer: :select,
                       options: @messcada_repo.for_select_rmt_codes_by_cultivar(@form_object.cultivar_id),
                       prompt: 'ALL',
                       caption: 'Rmt Code',
                       searchable: true,
                       remove_search_for_small_list: false,
                       hide_on_load: rule_type[:rmt_code_id] ? false : true },
        actual_cold_treatment_id: { renderer: :select,
                                    options: @messcada_repo.for_select_treatments_by_type(AppConst::COLD_TREATMENT),
                                    prompt: 'No Value',
                                    caption: 'Actual Cold Treatment',
                                    searchable: true,
                                    remove_search_for_small_list: false,
                                    hide_on_load: rule_type[:actual_cold_treatment_id] ? false : true },
        actual_ripeness_treatment_id: { renderer: :select,
                                        options: @messcada_repo.for_select_treatments_by_type(AppConst::RIPENESS_TREATMENT),
                                        prompt: 'No Value',
                                        caption: 'Actual Ripeness Treatment',
                                        searchable: true,
                                        remove_search_for_small_list: false,
                                        hide_on_load: rule_type[:actual_ripeness_treatment_id] ? false : true },
        rmt_class_id: { renderer: :select,
                        options: @fruit_repo.for_select_rmt_classes,
                        disabled_options: @fruit_repo.for_select_inactive_rmt_classes,
                        caption: 'Rmt Class',
                        prompt: 'ALL',
                        searchable: true,
                        remove_search_for_small_list: false,
                        hide_on_load: rule_type[:rmt_class_id] ? false : true },
        rmt_size_id: { renderer: :select,
                       options: MasterfilesApp::RmtSizeRepo.new.for_select_rmt_sizes,
                       caption: 'Rmt Size',
                       prompt: 'ALL',
                       searchable: true,
                       remove_search_for_small_list: false,
                       hide_on_load: rule_type[:rmt_size_id] ? false : true },
        colour_percentage_id: { renderer: :select,
                                options: @commodity_repo.for_select_colour_percentages,
                                disabled_options: @commodity_repo.for_select_inactive_colour_percentages,
                                caption: 'Colour Percentage',
                                prompt: 'ALL',
                                searchable: true,
                                remove_search_for_small_list: false,
                                hide_on_load: rule_type[:colour_percentage_id] ? false : true }
      }
    end

    def set_set_storage_rule_fields
      storage_rule_type_id_label = @repo.get(:storage_rule_types, :rule_type_name, @form_object.storage_rule_type_id)
      fields[:storage_rule_type_id] = { renderer: :label,
                                        with_value: storage_rule_type_id_label,
                                        hidden_value: @form_object.storage_rule_type_id,
                                        caption: 'Storage Rule Type',
                                        include_hidden_field: true }
    end

    def make_form_object # rubocop:disable Metrics/AbcSize
      if @mode == :new
        make_new_form_object
        return
      end

      if @mode == :set_storage_rule
        hash = @options[:attrs][:bin_storage_rule_id].nil_or_empty? ? new_form_object_from_struct(MasterfilesApp::BinStorageRule) : @repo.find_bin_storage_rule(@options[:attrs][:bin_storage_rule_id])
        @form_object = OpenStruct.new(hash.to_h.merge(location_id: @options[:attrs][:location_id],
                                                      storage_rule_type_id: @options[:attrs][:storage_rule_type_id]))
        return
      end

      @form_object = @repo.find_bin_storage_rule(@options[:id])
    end

    def make_new_form_object
      @form_object = new_form_object_from_struct(MasterfilesApp::BinStorageRule)
    end

    def handle_behaviour
      case @mode
      when :storage_rule_type
        storage_rule_type_change
      when :farm
        farm_change
      when :commodity
        commodity_change
      when :cultivar_group
        cultivar_group_change
      when :cultivar
        cultivar_change
      else
        unhandled_behaviour!
      end
    end

    private

    def add_behaviours
      behaviours do |behaviour|
        behaviour.dropdown_change :storage_rule_type_id,
                                  notify: [{ url: '/masterfiles/locations/bin_storage_rules/ui_change/storage_rule_type' }]
        behaviour.dropdown_change :commodity_id,
                                  notify: [{ url: '/masterfiles/locations/bin_storage_rules/ui_change/commodity' }]
        behaviour.dropdown_change :cultivar_group_id,
                                  notify: [{ url: '/masterfiles/locations/bin_storage_rules/ui_change/cultivar_group' }]
        behaviour.dropdown_change :cultivar_id,
                                  notify: [{ url: '/masterfiles/locations/bin_storage_rules/ui_change/cultivar',
                                             param_keys: %i[bin_storage_rule_farm_id] }]
        behaviour.dropdown_change :farm_id,
                                  notify: [{ url: '/masterfiles/locations/bin_storage_rules/ui_change/farm',
                                             param_keys: %i[bin_storage_rule_cultivar_id] }]
      end
    end

    def storage_rule_type_change # rubocop:disable Metrics/AbcSize,  Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
      repo      = MasterfilesApp::LocationRepo.new
      rule_type = if params[:changed_value].blank?
                    {}
                  else
                    repo.find_storage_rule_type(params[:changed_value])
                  end
      json_actions([OpenStruct.new(type: rule_type[:commodity_id] ? :show_element : :hide_element,
                                   dom_id: 'bin_storage_rule_commodity_id_field_wrapper'),
                    OpenStruct.new(type: rule_type[:cultivar_group_id] ? :show_element : :hide_element,
                                   dom_id: 'bin_storage_rule_cultivar_group_id_field_wrapper'),
                    OpenStruct.new(type: rule_type[:cultivar_id] ? :show_element : :hide_element,
                                   dom_id: 'bin_storage_rule_cultivar_id_field_wrapper'),
                    OpenStruct.new(type: rule_type[:farm_id] ? :show_element : :hide_element,
                                   dom_id: 'bin_storage_rule_farm_id_field_wrapper'),
                    OpenStruct.new(type: rule_type[:puc_id] ? :show_element : :hide_element,
                                   dom_id: 'bin_storage_rule_puc_id_field_wrapper'),
                    OpenStruct.new(type: rule_type[:orchard_id] ? :show_element : :hide_element,
                                   dom_id: 'bin_storage_rule_orchard_id_field_wrapper'),
                    OpenStruct.new(type: rule_type[:main_cold_treatment_id] ? :show_element : :hide_element,
                                   dom_id: 'bin_storage_rule_main_cold_treatment_id_field_wrapper'),
                    OpenStruct.new(type: rule_type[:main_ripeness_treatment_id] ? :show_element : :hide_element,
                                   dom_id: 'bin_storage_rule_main_ripeness_treatment_id_field_wrapper'),
                    OpenStruct.new(type: rule_type[:rmt_code_id] ? :show_element : :hide_element,
                                   dom_id: 'bin_storage_rule_rmt_code_id_field_wrapper'),
                    OpenStruct.new(type: rule_type[:actual_cold_treatment_id] ? :show_element : :hide_element,
                                   dom_id: 'bin_storage_rule_actual_cold_treatment_id_field_wrapper'),
                    OpenStruct.new(type: rule_type[:actual_ripeness_treatment_id] ? :show_element : :hide_element,
                                   dom_id: 'bin_storage_rule_actual_ripeness_treatment_id_field_wrapper'),
                    OpenStruct.new(type: rule_type[:rmt_class_id] ? :show_element : :hide_element,
                                   dom_id: 'bin_storage_rule_rmt_class_id_field_wrapper'),
                    OpenStruct.new(type: rule_type[:rmt_size_id] ? :show_element : :hide_element,
                                   dom_id: 'bin_storage_rule_rmt_size_id_field_wrapper'),
                    OpenStruct.new(type: rule_type[:colour_percentage_id] ? :show_element : :hide_element,
                                   dom_id: 'bin_storage_rule_colour_percentage_id_field_wrapper')])
    end

    def farm_change
      repo        = MasterfilesApp::FarmRepo.new
      cultivar_id = params[:bin_storage_rule_cultivar_id]
      farm_id     = params[:changed_value]
      if farm_id.blank? || cultivar_id.blank?
        pucs     = []
        orchards = []
      else
        pucs     = repo.for_select_pucs(where: { farm_id: farm_id })
        orchards = repo.for_select_orchards_by_farm_and_cultivar(farm_id, cultivar_id)
      end
      json_actions([OpenStruct.new(type: :replace_select_options,
                                   dom_id: 'bin_storage_rule_puc_id',
                                   options_array: pucs),
                    OpenStruct.new(type: :replace_select_options,
                                   dom_id: 'bin_storage_rule_orchard_id',
                                   options_array: orchards)])
    end

    def commodity_change
      cultivar_groups = if params[:changed_value].blank?
                          []
                        else
                          MasterfilesApp::CultivarRepo.new.for_select_cultivar_groups(
                            where: { commodity_id: params[:changed_value] }
                          )
                        end
      json_replace_select_options('bin_storage_rule_cultivar_group_id', cultivar_groups)
    end

    def cultivar_group_change
      cultivars = if params[:changed_value].blank?
                    []
                  else
                    MasterfilesApp::CultivarRepo.new.for_select_cultivars(
                      where: { cultivar_group_id: params[:changed_value] }
                    )
                  end
      json_replace_select_options('bin_storage_rule_cultivar_id', cultivars)
    end

    def cultivar_change
      farm_id     = params[:bin_storage_rule_farm_id]
      cultivar_id = params[:changed_value]
      if cultivar_id.blank? || farm_id.blank?
        orchards  = []
        rmt_codes = []
      else
        orchards  = MasterfilesApp::FarmRepo.new.for_select_orchards_by_farm_and_cultivar(farm_id, cultivar_id)
        rmt_codes = MesscadaApp::MesscadaRepo.new.for_select_rmt_codes_by_cultivar(cultivar_id)
      end
      json_actions([OpenStruct.new(type: :replace_select_options,
                                   dom_id: 'bin_storage_rule_orchard_id',
                                   options_array: orchards),
                    OpenStruct.new(type: :replace_select_options,
                                   dom_id: 'bin_storage_rule_rmt_code_id',
                                   options_array: rmt_codes)])
    end
  end
end
