class BulkUpload::Sales::Validator
  include ActiveModel::Validations

  attr_reader :bulk_upload, :path

  validate :validate_file_not_empty
  validate :validate_max_columns

  def initialize(bulk_upload:, path:)
    @bulk_upload = bulk_upload
    @path = path
  end

  def call
    row_parsers.each_with_index do |row_parser, index|
      row_parser.valid?

      row = index + row_offset + 1

      row_parser.errors.each do |error|
        bulk_upload.bulk_upload_errors.create!(
          field: error.attribute,
          error: error.type,
          purchaser_code: row_parser.field_1,
          row:,
          cell: "#{cols[field_number_for_attribute(error.attribute) + col_offset - 1]}#{row}",
        )
      end
    end
  end

private

  def field_number_for_attribute(attribute)
    attribute.to_s.split("_").last.to_i
  end

  def rows
    @rows ||= CSV.read(path, row_sep:)
  end

  def body_rows
    rows[row_offset..]
  end

  def row_offset
    5
  end

  def col_offset
    1
  end

  def cols
    @cols ||= ("A".."DV").to_a
  end

  def row_parsers
    @row_parsers ||= body_rows.map do |row|
      stripped_row = row[col_offset..]
      headers = ("field_1".."field_125").to_a
      hash = Hash[headers.zip(stripped_row)]

      BulkUpload::Sales::Year2022::RowParser.new(hash)
    end
  end

  def row_sep
    "\r\n"
    # "\n"
  end

  def validate_file_not_empty
    if File.size(path).zero?
      errors.add(:file, :blank)

      halt_validations!
    end
  end

  def validate_max_columns
    return if halt_validations?

    max_row_size = rows.map(&:size).max

    errors.add(:file, :max_row_size) if max_row_size > 126
  end

  def halt_validations!
    @halt_validations = true
  end

  def halt_validations?
    @halt_validations ||= false
  end
end