module Support
  module Helpers
    # Class for generating valid UPCs. To create products with client-owned UPCs not generated by
    # The Orchard, we need to create a valid UPC that is unused and meets the checksum requirements.
    class UPC
      def self.generate_unused_upc
        # generate valid UPCs until we find one that's unused
        possible_upc = new
        possible_upc.generate
        possible_upc.generate until possible_upc.available?
        possible_upc.result
      end

      attr_reader :result

      # generates a UPC that meets the checksum requirements using a 11-digit number.
      def generate
        upc_seed = random_11_digit_number
        @result = upc_seed + check_digit_from_seed(upc_seed).to_s
      end

      def available?
        Support::Services::OwsProduct.upc_available?(@result)
      end

      private

      def random_11_digit_number
        rand(99_999_999_999).to_s.rjust(11, "0")
      end

      # see https://en.wikipedia.org/wiki/Check_digit#UPC
      def check_digit_from_seed(seed)
        sum_of_odd_digits = (0..6).inject(0) do |current_sum, value|
          odd_digit = seed[2 * value].to_i
          current_sum + odd_digit
        end

        sum_of_even_digits = (0..5).inject(0) do |current_sum, value|
          even_digit = seed[2 * value + 1].to_i
          current_sum + even_digit
        end

        remainder = (3 * sum_of_odd_digits + sum_of_even_digits) % 10
        if remainder.zero?
          0
        else
          10 - remainder
        end
      end
    end
  end
end
