module DataHelpers
  class AudioBulkUploadHelper
    class << self
      # Class convenience methods

      def create_spreadsheet(data:, template_url:, save_prefix:, first_non_header_row_index: 1)
        # use class var so we don't need to download more than once per run
        @template_path ||= FileSystemHelpers::Downloader.download(template_url).first

        Spreadsheet.open(@template_path) do |book|
          populate_spreadsheet_data(book, data, first_non_header_row_index)

          # saving spreadsheet
          File.join(Support::Paths.uploads, "#{save_prefix}_#{Time.stamp}.xls").tap do |save_location|
            book.write save_location
          end
        end
      end

      def populate_spreadsheet_data(book, data, first_non_header_row_index)
        sheet = book.worksheet 0
        header_row = sheet.row(0).map(&:to_s)

        max_row_index = first_non_header_row_index + rows_in_final_spreadsheet(data) - 1

        (first_non_header_row_index..max_row_index).each_with_index do |i| # i starts at 1 by default
          row_buffer = []
          # iterate through each column of a given row, using header_row as a guide
          header_row.each do |header|
            row_buffer << cell_content(i, header, data)
          end
          sheet.row(i).replace row_buffer
        end
      end

      # Returns the number of rows we will write to a spreadsheet, given the yml in the #initialize
      #
      # Example
      #
      # data = {
      #   'header1' => 'all rows will be this str',
      #   'header2' =>['row1'],
      #   'header3' =>['row1', 'row2', 'row3']
      # }
      # rows_in_final_spreadsheet(data)
      # => 3 # because the greatest array in the `data` hash has size 3
      #
      # Returns an integer
      def rows_in_final_spreadsheet(data)
        max = 0
        data.each do |_k, column_data|
          rows = case column_data
                 when Array
                   column_data.size
                 when nil
                   0
                 else 1
                 end
          max = rows if rows > max
        end
        max
      end

      private

      def cell_content(row, header, data)
        # Raise an exception if there is no key with the same text as the spreadsheet header:
        fail KeyError, "No key #{header} found in #{data.keys}" unless data.keys.include? header
        # Note that if el with index `i` doesn't exist for a header (i.e. the array has too few elements),
        # then `content` is an empty string:
        data[header].is_a?(Array) ? data[header][row - 1].to_s : data[header].to_s
      end
    end
  end
end
