# frozen_string_literal: true

#
# Helper to create a modal dialog for a given model
#
module ModelModalHelper
  #
  # Render the relationship for the model, using caching to speed things up a bit
  #
  # This helper should be used on the related objects in the table, to cut down on the database queries when rendering
  # the table.
  #
  def related_modal_tag(model, relation, options = {})
    related_model = fetch_related_model(model, relation)
    return if related_model.blank?

    dynamic_related_modal(related_model, related_model_edit_path(model, relation, related_model, options), options)
  end

  #
  # Only show the trigger with the edit path, let the rest be generated later
  #
  def dynamic_related_modal(related_model, edit_path, _options = {})
    model_name = related_model.class.to_s.underscore
    datum = { view_url: edit_path.gsub('/edit', '') }
    anchor_id = "#{model_name}-#{related_model.id}"
    title = related_model.respond_to?(:short_name) ? related_model.short_name : related_model.name
    content_tag(:div) do
      concat(content_tag(:a, href: "##{anchor_id}", class: 'modal-trigger') do
        concat(content_tag(:span, title))
      end)
      concat(content_tag(:div, id: anchor_id, class: 'modal', data: datum) do
        concat(content_tag(:div, class: 'modal-content') do
          concat(content_tag(:h2, class: 'center') do
            concat(content_tag(:span, related_model.name))
          end)
          concat(content_tag(:div, class: 'center-align') do
            concat(content_tag(:div, class: 'progress red lighten-4') do
              tag(:div, class: 'indeterminate red')
            end)
          end)
        end)
        concat(model_modal_footer(related_model, edit_path))
      end)
    end
  end

  def related_model_edit_path(model, relation, related_model, options = {})
    if options[:parent].present?
      parent_model = fetch_related_model(model, options[:parent])
      send("edit_#{options[:parent]}_#{relation}_path", parent_model, related_model)
    else
      send("edit_#{relation}_path", related_model)
    end
  end

  def fetch_related_model(model, relation)
    # First get the relationship from cache
    related_id = model.send("#{relation}_id")
    key = "model_modal::#{relation}::#{related_id}"
    Rails.cache.fetch(key, expires_in: 6.hours) { model.send(relation) }
  end

  #
  # Render a modal tag for the given model object
  #
  def model_modal_tag(model, edit_path, options = {})
    model_modal_action(model, options) + model_modal(model, edit_path, options)
  end

  def model_modal_action(model, _options = {})
    content_tag(:a, class: 'modal-trigger', href: "#modal-#{model.id}") do
      concat(model.name.titleize)
    end
  end

  def model_modal(model, edit_path, options = {})
    content_tag(:div, class: 'modal', id: "modal-#{model.id}") do
      concat(model_modal_content(model, options))
      concat(model_modal_footer(model, edit_path))
    end
  end

  def dynamic_model_modal(model, options = {})
    model_modal_content(model, options) + model_modal_footer(model, "#{request.url}/edit")
  end

  def model_modal_content(model, options = {})
    content_tag(:div, class: 'modal-content') do
      concat(content_tag(:h2) { model.name })
      concat(content_tag(:div, class: 'row') do
        concat(model_modal_tabs(model, options))
        concat(model_modal_fields_tab(model, options))
        concat(model_modal_standard_tab(model, options))
        concat(model_modal_logs_tab(model, options)) if model.respond_to?(:logs)
      end)
    end
  end

  def model_modal_tabs(model, _options = {})
    content_tag(:div, class: 'col s12') do
      concat(content_tag(:ul, class: 'tabs tabs-fixed-width') do
        concat(content_tag(:li, class: 'tab') do
          content_tag(:a, href: "#field-tab-#{model.id}") { model.class.to_s.titleize }
        end)
        concat(content_tag(:li, class: 'tab') { content_tag(:a, href: "#standard-tab-#{model.id}") { 'Details' } })
        if model.respond_to?(:logs)
          concat(content_tag(:li, class: 'tab') { content_tag(:a, href: "#logs-tab-#{model.id}") { 'Logs' } })
        end
      end)
    end
  end

  def model_modal_standard_tab(model, options = {})
    content_tag(:div, id: "standard-tab-#{model.id}", class: 'col s12') do
      concat(model_modal_standard(model, options))
    end
  end

  def model_modal_fields_tab(model, options = {})
    content_tag(:div, id: "field-tab-#{model.id}", class: 'col s12') do
      concat(model_modal_fields(model, options))
    end
  end

  def model_modal_logs_tab(model, _options = {})
    content_tag(:div, id: "logs-tab-#{model.id}", class: 'col s12') do
      content_tag(:table, class: 'center-align') do
        concat(content_tag(:thead) do
          concat(content_tag(:tr) do
            concat(content_tag(:th) { 'Created' })
            concat(content_tag(:th) { 'Command' })
            concat(content_tag(:th) { 'Message' })
          end)
        end)
        concat(content_tag(:tbody) do
          model.logs.each do |log|
            concat(model_modal_log(log))
          end
        end)
      end
    end
  end

  def model_modal_log(log)
    content_tag(:tr) do
      concat(content_tag(:td) { log.created_at })
      concat(content_tag(:td) { log.display_message })
    end
  end

  def model_modal_fields(model, _options = {})
    content_tag(:table, class: 'center-align') do
      concat(content_tag(:tbody) do
        model.class.allowed_param_names.sort.each do |field_name|
          concat(model_modal_field(model, field_name))
        end
      end)
    end
  end

  def model_modal_standard(model, _options = {})
    content_tag(:table, class: 'center-align highlight') do
      concat(content_tag(:tbody) do
        %w[_id _type created_at updated_at search_text sort_text].each do |field_name|
          concat(model_modal_field(model, field_name))
        end
      end)
    end
  end

  def model_modal_field(model, field_name)
    content_tag(:tr) do
      concat(content_tag(:th, class: 'right-align') do
        field_name.titleize
      end)
      concat(content_tag(:td) do
        model_modal_field_value(model, field_name)
      end)
    end
  end

  def model_modal_field_value(model, field_name)
    value = model.respond_to?(field_name) ? model.send(field_name) : ''
    case value
    when BSON::ObjectId
      if field_name.eql?('_id')
        value.to_s
      else
        related_model = fetch_related_model(model, field_name.chomp('_id'))
        related_model.present? ? related_model.name : 'N/A'
      end
    when FalseClass
      'No'
    when TrueClass
      'Yes'
    when Mongoid::Boolean, Boolean
      value ? 'Yes' : 'No'
    when Date, DateTime, Time
      current_user.local_time(value, :long)
    when Integer, Array
      value.to_s
    else
      value
    end
  end

  def model_modal_footer(model, edit_path)
    content_tag(:div, class: 'modal-footer') do
      concat(edit_modal_tag(model, edit_path))
    end
  end
end