module Subscriptions
  class Badge < Subscriptions::Base
    POSSIBLE_REQUIRED_TENURE_MONTHS = [0, 2, 3, 6, 9, 12, 24, 36, 48, 60, 72, 84, 96]

    self.primary_attribute = :id

    attributes :id,
      :channel_tenure_method_id,
      :channel_id,
      :click_action,
      :click_url,
      :description,
      :image_1x,
      :image_1x_url,
      :image_2x,
      :image_2x_url,
      :image_4x,
      :image_4x_url,
      :required_tenure_months,
      :title

    validates :channel_id, :image_1x, :image_2x, :image_4x, :required_tenure_months, presence: true

    def self.connection
      super(request: :multipart)
    end

    def self.existing_and_available_for(channel_id:)
      existing_badges = self.where(channel_id: channel_id)
      existing_badges_by_tenure = {}

      existing_badges.each do |badge|
        existing_badges_by_tenure[badge.required_tenure_months] = badge
      end

      POSSIBLE_REQUIRED_TENURE_MONTHS.map do |months|
        existing = existing_badges_by_tenure[months]

        existing || self.new(channel_id: channel_id, required_tenure_months: months)
      end
    end

    def save
      return false unless valid?

      response = post "/internal/channels/#{channel_id}/badges", body: save_params

      errors.add(:base, response.body["error"]) unless response.success?

      response.success?
    end

    def destroy
      url = "/internal/channels/#{channel_id}/badges/#{primary_attribute_value}"
      if channel_tenure_method_id
        url = "#{url}?channel_tenure_method_id=#{channel_tenure_method_id}"
      end

      response = delete url

      errors.add(:base, response.body["error"]) unless response.success?

      response.success?
    end

    private

    def self.where(channel_id:)
      response = get "/internal/channels/#{channel_id}/badges"

      return [] unless response.success? && response.body.is_a?(Array)

      response.body.map do |badge|
        badge[:channel_id] = channel_id

        from_attributes(badge)
      end
    end

    def save_params
      {
        image_1x: Faraday::UploadIO.new(image_1x.tempfile.path, "image/png"),
        image_2x: Faraday::UploadIO.new(image_2x.tempfile.path, "image/png"),
        image_4x: Faraday::UploadIO.new(image_4x.tempfile.path, "image/png"),
        required_tenure_months: required_tenure_months,
        options: {
          content_type: :multipart
        }
      }
    end
  end
end
