module PayoutEntities
  class BulkInvitation < PayoutEntities::Base
    attributes :user_ids, :user_category, :terms, :is_esports

    validates :user_ids, :user_category, presence: true
    validates :terms, presence: true, if: :partner?

    AUDIT_ACTION_INVITE = "invite"
    AUDIT_TWITCH_USER = "twitch_user"
    AUDIT_LDAP_USER = "ldap_user"
    AUDIT_CHANGE_CATEGORY = "category"
    AUDIT_CHANGE_TAGS = "tags"
    AUDIT_CHANGE_FEATURES = "features"

    CATEGORY_0CPM = "0cpm"
    CATEGORY_AFFILIATE = "Affiliate"
    CATEGORY_PARTNER = "Partner"

    TERMS_STANDARD = "Standard"
    TERMS_PREMIUM = "Premium"
    TERMS_CUSTOM = "Custom"

    def save(options = {})
      return false unless valid?

      usernames_by_id = {}
      user_ids.strip().split(/[\s,]+/).each do |id|
        begin
          user = Twitch::User.find(id)
        rescue RuntimeError
          self.errors.add(:base, "Invalid channel ID(s) provided")
          return false
        end

        if user.blank?
          self.errors.add(:base, "User #{id} does not exist")
          return false
        end
        usernames_by_id[id] = user.login

        warnings.append("<strong>Warning: #{user.login}</strong> (#{id}) was invited and is a staff user. If this was intentional, please contact HR immediately so this user can be paid via payroll") if user.admin
        warnings.append("<strong>Warning: #{user.login}</strong> (#{id}) was invited but is TOS banned") if user.terms_of_service_violation
        warnings.append("<strong>Warning: #{user.login}</strong> (#{id}) was invited but is DMCA banned") if user.dmca_violation
        warnings.append("<strong>Warning: #{user.login}</strong> (#{id}) was invited but is deactivated") if user.deleted_on

        channel_ids.append(id)
      end

      response = post "/payout/invites", body: save_params.to_json, headers: PayoutEntity.ldap_headers(options)

      unless response.success?
        msg = response.body["message"].present? ? response.body["message"] : "Internal server error"
        self.errors.add(:base, msg)

        return false
      end

      response.body.each do |result|
        if result["success"]
          successes.append("<strong>#{usernames_by_id[result['channel_id']]}</strong> (#{result['channel_id']}) successfully invited")
          audit_invite(result["channel_id"], options)
        else
          self.errors.add(:base, "<strong>Error for #{usernames_by_id[result['channel_id']]}:</strong> #{result['error_message']}")
        end
      end

      response.success?
    end

    def save_params
      {
        channel_ids: @channel_ids,
        category: category
      }
    end

    def audit_invite(channel_id, options)
      category_change = History::ChangeSet.new(
        attribute: AUDIT_CHANGE_CATEGORY,
        new_value: user_category.downcase()
      )
      tags_change = History::ChangeSet.new(
        attribute: AUDIT_CHANGE_TAGS,
        new_value: tags.join(", ")
      )
      features_change = History::ChangeSet.new(
        attribute: AUDIT_CHANGE_FEATURES,
        new_value: features
      )

      changes = [category_change, tags_change, features_change]

      ldap_login = options[:ldap_login] || ""
      audit = History::Audit.new(
        action: AUDIT_ACTION_INVITE,
        user_type: AUDIT_LDAP_USER,
        user_id: ldap_login,
        resource_type: AUDIT_TWITCH_USER,
        resource_id: channel_id,
        description: "",
        changes: changes
      )

      History::AddAudit.add(audit)
    end

    def channel_ids
      @channel_ids ||= []
    end

    def successes
      @successes ||= []
    end

    def warnings
      @warnings ||= []
    end

    def affiliate?
      user_category == CATEGORY_AFFILIATE
    end

    def partner?
      user_category == CATEGORY_PARTNER
    end

    def esports?
      self.class.booleanize is_esports
    end

    def category
      {
        category: user_category.downcase(),
        tags: tags,
        features: features
      }
    end

    def tags
      tags = []
      tags.append(terms.downcase()) if terms.present?
      tags.append("esports") if esports?
      tags
    end

    def features
      features = {}
      if affiliate?
        features = {
          subs: true,
          bits: true,
          pre_roll_ads: false,
          post_roll_ads: false
        }
      elsif partner?
        features = {
          subs: true,
          bits: true,
          pre_roll_ads: true,
          post_roll_ads: true
        }
      end
      features
    end
  end
end
