# frozen_string_literal: true

require 'open_food_network/column_preference_defaults'

class ColumnPreference < ApplicationRecord
  extend OpenFoodNetwork::ColumnPreferenceDefaults

  # Non-persisted attributes that only have one
  # setting (ie. the default) for a given column
  attr_accessor :name

  belongs_to :user, class_name: "Spree::User"

  validates :action_name, presence: true, inclusion: { in: proc { known_actions } }
  validates :column_name, presence: true, inclusion: { in: proc { |p|
                                                             valid_columns_for(p.action_name)
                                                           } }
  scope :bulk_edit_product, -> { where(action_name: 'products_v3_index') }

  def self.for(user, action_name)
    stored_preferences = where(user_id: user.id, action_name:)
    default_preferences = get_default_preferences(action_name, user)
    filter(default_preferences, user, action_name)
    default_preferences.each_with_object([]) do |(column_name, default_attributes), preferences|
      stored_preference = stored_preferences.find_by(column_name:)
      if stored_preference
        stored_preference.assign_attributes(default_attributes.select{ |k, _v|
                                              stored_preference[k].nil?
                                            } )
        preferences << stored_preference
      else
        attributes = default_attributes.merge(user_id: user.id, action_name:,
                                              column_name:)
        preferences << ColumnPreference.new(attributes)
      end
    end
  end

  def self.valid_columns_for(action_name)
    get_default_preferences(action_name, Spree::User.new).keys.map(&:to_s)
  end

  def self.known_actions
    OpenFoodNetwork::ColumnPreferenceDefaults.private_instance_methods
      .select{ |m| m.to_s.end_with?("_columns") }.map{ |m| m.to_s.sub /_columns$/, '' }
  end

  # Arbitrary filtering of default_preferences
  def self.filter(default_preferences, user, action_name)
    return unless action_name == 'order_cycles_index'

    return if user.admin? || user.enterprises.where(enable_subscriptions: true).any?

    default_preferences.delete(:schedules)
  end

  def self.get_default_preferences(action_name, user)
    case action_name
    when 'products_v3_index'
      products_v3_index_columns(user)
    else
      __send__("#{action_name}_columns")
    end
  end
end
