class I18nContent < ApplicationRecord
  validates :key, uniqueness: true

  translates :value, touch: true
  globalize_accessors

  # flat_hash returns a flattened hash, a hash with a single level of
  # depth in which each key is composed from the keys of the original
  # hash (whose value is not a hash) by typing in the key of the route
  # from the first level of the original hash
  #
  # Examples:
  #
  # hash = {
  #   'key1' => 'value1',
  #   'key2' => { 'key3' => 'value2',
  #               'key4' => { 'key5' => 'value3' } }
  # }
  #
  # I18nContent.flat_hash(hash) = {
  #   'key1' => 'value1',
  #   'key2.key3' => 'value2',
  #   'key2.key4.key5' => 'value3'
  # }
  #
  # I18nContent.flat_hash(hash, 'string') = {
  #   'string.key1' => 'value1',
  #   'string.key2.key3' => 'value2',
  #   'string.key2.key4.key5' => 'value3'
  # }
  #
  # I18nContent.flat_hash(hash, 'string', { 'key6' => 'value4' }) = {
  #   'key6' => 'value4',
  #   'string.key1' => 'value1',
  #   'string.key2.key3' => 'value2',
  #   'string.key2.key4.key5' => 'value3'
  # }

  def self.flat_hash(input, path = nil, output = {})
    return output.update({ path => input }) unless input.is_a? Hash

    input.map { |key, value| flat_hash(value, [path, key].compact.join("."), output) }
    output
  end

  def self.content_for(tab)
    translations_for(tab).map do |string|
      I18nContent.find_or_initialize_by(key: string)
    end
  end

  def self.translations_for(tab)
    if tab.to_s == "basic"
      basic_translations
    elsif tab.to_s == "machine_learning"
      machine_learning_translations
    else
      flat_hash(translations_hash_for(tab)).keys
    end
  end

  def self.translations_hash_for(tab)
    I18n.backend.send(:init_translations) unless I18n.backend.initialized?

    I18n.backend.send(:translations)[I18n.locale].select do |key, _translations|
      key.to_s == tab.to_s
    end
  end

  def self.basic_translations
    %w[
      debates.index.section_footer.title
      debates.index.section_footer.description
      debates.index.section_footer.help_text_1
      debates.index.section_footer.help_text_2
      debates.new.info
      debates.new.info_link
      debates.new.more_info
      debates.new.recommendation_one
      debates.new.recommendation_two
      debates.new.recommendation_three
      debates.new.recommendation_four
      debates.new.recommendations_title
      proposals.index.section_footer.title
      proposals.index.section_footer.description
      proposals.new.more_info
      proposals.new.recommendation_one
      proposals.new.recommendation_two
      proposals.new.recommendation_three
      proposals.new.recommendations_title
      polls.index.section_footer.title
      polls.index.section_footer.description
      legislation.processes.index.section_footer.title
      legislation.processes.index.section_footer.description
      budgets.index.section_footer.title
      budgets.index.section_footer.description
    ]
  end

  def self.machine_learning_translations
    %w[
      admin.machine_learning.title
      machine_learning.comments_summary
      machine_learning.info_text
      admin.machine_learning.comments_summary
      admin.machine_learning.comments_summary_description
      admin.machine_learning.related_content
      admin.machine_learning.related_content_description
      admin.machine_learning.tags
      admin.machine_learning.tags_description
    ]
  end

  def self.translations_hash(locale)
    Rails.cache.fetch(translation_class.where(locale: locale)) do
      all.to_h do |content|
        [content.key, translation_class.find_by(i18n_content_id: content, locale: locale)&.value]
      end
    end
  end

  def self.update(contents, enabled_translations = Setting.enabled_locales)
    contents.each do |content|
      values = content[:values].slice(*translation_params(enabled_translations))

      unless values.empty?
        values.each do |key, value|
          locale = key.split("_").last

          if value.match(/translation missing/)
            next
          elsif value == I18n.t(content[:id], locale: locale)
            Globalize.with_locale(locale) do
              I18nContent.find_by(key: content[:id])&.update!(value: value)
            end
          else
            text = I18nContent.find_or_create_by!(key: content[:id])
            Globalize.with_locale(locale) do
              text.update!(value: value)
            end
          end
        end
      end
    end
  end

  def self.translation_params(enabled_translations)
    translated_attribute_names.product(enabled_translations).map do |attr_name, loc|
      localized_attr_name_for(attr_name, loc)
    end
  end
end
