class ZoomGateway
  class AuthenticationError < StandardError; end
  class MeetingExpired < StandardError; end
  class UserNotFound < StandardError; end
  class TooManyHosts < StandardError; end
  class UserAlreadyExists < StandardError; end

  class << self
    def USER_TYPE_NAME
      default = 'basic'
      env_name = ENV['ZOOM_USER_TYPE'] || default
      %w[pro basic].include?(env_name) ? env_name : default
    end

    def USER_TYPE
      self.USER_TYPE_NAME == 'pro' ? 2 : 1
    end

    def PRO_USERS_LIMIT
      (ENV['ZOOM_PRO_USERS_LIMIT'] || 3).to_i
    end

    def HOST_ROLE
      self.host_role_name(self.USER_TYPE_NAME)
    end

    def ACCOUNT_NUMBER
      ENV['ZOOM_ACCOUNT_NUMBER']
    end

    def enable_recordings?
      ENV['ZOOM_ENABLE_RECORDINGS'] == 'true'
    end

    def apply_limits?
      self.USER_TYPE_NAME == 'pro'
    end

    def host_role_name(user_type_name)
      "#{user_type_name}-directme-host"
    end
  end

  def initialize
    @client = Zoom.new
  end

  def create_meeting(host_id, **kwargs)
    recording_type = self.class.enable_recordings? ? 'cloud' : 'none'
    meeting = @client.meeting_create({ user_id: host_id,
                                       topic: kwargs[:topic],
                                       type: 1, # Instant meeting
                                       settings: {
                                         host_video: true,
                                         participant_video: true,
                                         auto_recording: recording_type,
                                       } })
    meeting["id"]
  end

  def find_meeting(meeting_id)
    meeting = @client.meeting_get(meeting_id: meeting_id)
    HashWithIndifferentAccess.new(meeting)
  rescue Zoom::APIError => e
    parse_zoom_error(e)
  end

  def create_host(host_email)
    # Find role
    host_role = @client.roles_list["roles"].try(:select) { |r| r["name"] == self.class.HOST_ROLE }.try(:first)
    raise StandardError.new("Zoom host role #{self.class.HOST_ROLE} does not exist, try running rails zoom:setup.") unless host_role.present?

    if self.class.apply_limits?
      hosts_count = @client.roles_members(role_id: host_role["id"]).try(:[], 'total_records').try(:to_i)
      raise TooManyHosts, 'The limit of hosts has been reached' if hosts_count >= self.class.PRO_USERS_LIMIT
    end

    # Create new user
    host_user = @client.user_create({
      action: "custCreate",
      email: host_email,
      type: self.class.USER_TYPE
    })

    # Assign role to user
    @client.roles_assign role_id: host_role["id"], members: [{id: host_user["id"]}]

    # Return user id
    host_user["id"]
  end

  def delete_host(host_id)
    @client.user_delete(id: host_id)
  end

  def delete_recording(meeting_id, recording_id)
    @client.recording_delete(meeting_id: meeting_id, recording_id: recording_id)
  end

  private

  def parse_zoom_error(error)
    if error.status_code == 104
      raise AuthenticationError, error.message
    elsif error.status_code == 1001
      raise UserNotFound, error.message
    elsif error.status_code == 3001
      raise MeetingExpired, error.message
    elsif error.status_code == 1005
      raise UserAlreadyExists, error.message
    else
      raise error
    end
  end
end
