class WorkflowInstance::IndexCsvBuilder < CsvBuilder
  BASE_COLUMNS = %i[]

  def headers
    columns = [workflow_instance_class.model_name.human]
    columns += BASE_COLUMNS.map{|c| workflow_instance_class.human_attribute_name(c)}
    # Workflow steps
    workflow_step_mapping.each do |klass, attributes|
      columns << klass.model_name.human # state column
      columns += attributes.map{|attr| klass.human_attribute_name(attr)}
    end
    columns
  end

  def workflow_instances
    resource
  end

  # It could all be done using a .map instead of a find_each with fallback each into
  # an array, but for large exports this does not blow up the queries that may have many
  # association includes. Therefore the .find_each can be useful for exports of over
  # 5000 records
  def serialized_rows
    rows = []
    iteration_method = workflow_instances.respond_to?(:find_each) ? :find_each : :each
    workflow_instances.public_send(iteration_method) do |workflow_instance|
      rows.push serialize_row(workflow_instance)
    end
    rows
  end

  def serialize_row(record)
    columns = [record.try(:presentation_name)]
    columns += BASE_COLUMNS.map{|c| record_attribute(record, c) }
    # Workflow steps
    workflow_step_mapping.each do |workflow_step_class, attributes|
      unless workflow_step = record.public_send(workflow_step_class.process_name)
        columns += Array.new(1 + attributes.size) # state + attributes Empty fill
        next
      end
      columns << workflow_step.state
      columns += attributes.map{|attr| record_attribute(workflow_step, attr) }
    end
    columns
  end

  # Create a mapping of (klass => attributes):
  #   {
  #     WorkflowStepClass => ['notes', 'workflow_step_action_executed', ...],
  #     ....
  #   }
  def workflow_step_mapping
    @workflow_step_mapping ||= begin
      workflow_instance_class.workflow_step_classes.each.with_object({}) do |klass, h|
        attributes = klass.collection.attributes.keys
        attributes -= ['notes'] unless options[:include_notes].present?
        h[klass] = attributes
      end
    end
  end

  def workflow_instance_class
    controller.workflow_instance_class
  end

  def file_name
    "#{Rails.application.config.application_name}-export-#{date_number}.csv"
  end
end
