module Bits
  class Product < Service::Base
    include Code::Justin::Tv::Commerce::Petozi
    include Google::Protobuf

    self.service_endpoint = Settings.petozi.endpoint
    self.primary_attribute = :id

    attributes :id, :display_name, :platform, :bits_type_id, :quantity, :max_purchasable_quantity, :promo, :show_when_logged_out, :pricing_id

    validates :id, :display_name, :platform, :bits_type_id, :quantity, :max_purchasable_quantity, :promo, :show_when_logged_out, :pricing_id, presence: true

    def self.twirp_client
      @twirp_client ||= PetoziClient.new(connection)
    end

    def self.all(_options = {})
      resp = twirp_client.get_bits_products(GetBitsProductsReq.new)

      raise resp.error.msg if resp.error

      products = resp.data.bits_products.map do |twirp_product|
        product = self.from_twirp_object(twirp_product)
        product.promo = ProductPromo.from_twirp_object(twirp_product.promo) if product.try(:promo)
        product
      end
      products.sort_by { |p| [p.platform, p.id] }
    end

    def self.find(id, platform)
      resp = twirp_client.get_bits_product(GetBitsProductReq.new(id: id, platform: platform))

      raise resp.error.msg if resp.error

      product = self.from_twirp_object(resp.data.bits_product)
      product.promo = ProductPromo.from_twirp_object(resp.data.bits_product.promo) if resp.data.bits_product.try(:promo)
      product
    end

    def self.platforms
      Platform.constants.sort_by { |c| Platform.resolve(c) }
    end

    def self.promo_types
      PromoType.constants.sort_by { |c| PromoType.resolve(c) }
    end

    def save
      req = PutBitsProductReq.new

      product = BitsProduct.new(
        id: @id,
        display_name: @display_name,
        platform: @platform,
        bits_type_id: @bits_type_id,
        quantity: @quantity,
        max_purchasable_quantity: @max_purchasable_quantity,
        show_when_logged_out: @show_when_logged_out,
        pricing_id: @pricing_id
      )

      if @promo
        product.promo = Promo.new(
          id: @promo.id,
          type: @promo.type,
          start: Timestamp.new(seconds: @promo.start.to_i),
          end: Timestamp.new(seconds: @promo.end.to_i)
        )
      end
      req.new_bits_product = product

      resp = self.class.twirp_client.put_bits_product(req)
      self.errors = resp.error.msg if resp.error

      return !resp.error
    end

    def include_promo?
      @promo.present?
    end
  end
end

module Bits
  class ProductPromo < Service::Base
    include Code::Justin::Tv::Commerce::Petozi

    attributes :id, :type, :start, :end
    self.primary_attribute = :id
  end
end
