shared_context 'with example memberships' do
  let(:id) { "#{role_id}:#{member_user_id}" }
  let(:role_id) { 'role-id' }
  let(:role_name) { 'role-name' }

  let(:member_user_id) { 'member-user-id' }
  let(:member_expires_at) { Time.parse('2020-05-06') }
  let(:member_expires_at_date) { Time.parse('2020-05-06').to_date }
  let(:member_expires_at_twirp) do
    Google::Protobuf::Timestamp.new(seconds: member_expires_at.to_i)
  end
  let(:perm_id) { 'perm-id' }
  let(:perm_name) { 'perm-name' }

  let(:membership) do
    BeefCake::Membership.new(
      id: id,
      role_id: role_id,
      uid: member_user_id,
      expires_at: member_expires_at.to_date
    )
  end

  let(:twirp_membership) do
    Twitch::Fulton::Beefcake::Role::UserMembership.new(
      user_id: member_user_id,
      expiration: member_expires_at_twirp
    )
  end

  let(:twirp_role) do
    r = Twitch::Fulton::Beefcake::Role.new(
      id: role_id,
      name: role_name
    )
    r.user_memberships.replace([twirp_membership])
    r
  end
end

shared_context 'with example permissions' do
  let(:perm_id) { 'my-perm-id' }
  let(:perm_description) { 'my-perm-description' }
  let(:perm_name) { 'my-perm-name' }
  let(:role_id) { 'role_id' }
  let(:role_name) { 'role_name' }

  let(:permission) do
    BeefCake::Permission.new(
      id: perm_id,
      canonical_name: perm_id,
      description: perm_description,
      name: perm_name,
      roles: [BeefCake::Role.new(id: role_id, name: role_name)]
    )
  end

  let(:twirp_permission) do
    p = Twitch::Fulton::Beefcake::LegacyPermission.new(
      id: perm_id,
      description: perm_description,
      name: perm_name
    )
    p.roles.replace([
                      Twitch::Fulton::Beefcake::LegacyPermission::Role.new(
                        id: role_id,
                        name: role_name
                      )
                    ])
    p
  end
end

shared_context 'with example roles' do
  let(:role_id) { 'role-id' }
  let(:role_name) { 'role-name' }
  let(:member_user_id) { 'member-user-id' }
  let(:member_expires_at) { Time.parse('2020-05-06') }
  let(:member_expires_at_date) { Time.parse('2020-05-06').to_date }
  let(:member_expires_at_twirp) do
    Google::Protobuf::Timestamp.new(seconds: member_expires_at.to_i)
  end
  let(:perm_id) { 'perm-id' }
  let(:perm_name) { 'perm-name' }
  let(:role_perm_id) { 'my-role-perm-id' }
  let(:perm_scope) do
    [
      Twitch::Fulton::Beefcake::PermissionScope.new(
        channel_payout: Twitch::Fulton::Beefcake::PermissionScope::ChannelPayoutType::AFFILIATE
      )
    ]
  end
  let(:perm_scope_s) do
    ['AFFILIATE']
  end

  let(:permission) do
    BeefCake::Permission.from_attributes(
      id: perm_id,
      canonical_name: perm_id,
      name: perm_name
    )
  end
  let(:role) do
    r = BeefCake::Role.new(
      id: role_id,
      name: role_name,
      memberships: [BeefCake::Membership.from_attributes(
        id: "#{role_id}:#{member_user_id}",
        uid: member_user_id,
        role_id: role_id,
        expires_at: member_expires_at_date
      )],
      permissions: [permission]
    )
    r.attached_permissions = [BeefCake::AttachedPermission.from_attributes(
      id: role_perm_id,
      role: r,
      permission: permission,
      scope: perm_scope
    )]
    r
  end
  let(:attached_permission) do
    role.attached_permissions[0]
  end

  let(:twirp_role) do
    r = Twitch::Fulton::Beefcake::Role.new(
      id: role_id,
      name: role_name
    )
    r.user_memberships.replace([
                                 Twitch::Fulton::Beefcake::Role::UserMembership.new(
                                   user_id: member_user_id,
                                   expiration: member_expires_at_twirp
                                 )
                               ])
    r.permissions.replace([
                            Twitch::Fulton::Beefcake::AttachedPermission.new(
                              id: role_perm_id,
                              permission: Twitch::Fulton::Beefcake::Permission.new(
                                legacy: Twitch::Fulton::Beefcake::Permission::LegacyPermission.new(
                                  id: perm_id,
                                  name: perm_name
                                )
                              ),
                              scope: perm_scope
                            )
                          ])
    r
  end
end

shared_context 'with example users' do
  let(:role_id) { 'my-role-id' }
  let(:role_name) { 'my-role-name' }
  let(:role_perm_id) { 'my-role-perm-id' }
  let(:perm_id) { 'my-perm-id' }
  let(:perm_name) { 'my-perm-name' }
  let(:user_id) { 'my-user-id' }
  let(:user_email) { 'my-user-email' }
  let(:user_name) { 'my-user-email' }

  let(:user) do
    described_class.from_attributes(
      ldap_login: user_id,
      memberships: [BeefCake::Membership.from_attributes(
        id: BeefCake::Membership.composite_key(
          role_id: role_name,
          uid: user_id
        ),
        uid: user_id,
        role_id: role_id,
        role_name: role_name,
        expires_at: nil
      )],
      attached_permissions: {
        perm_id => BeefCake::AttachedPermission.from_attributes(
          id: role_perm_id,
          permission: BeefCake::Permission.from_attributes(
            id: perm_id,
            canonical_name: perm_id,
            name: perm_name
          ),
          scope: []
        )
      },
      permissions: [BeefCake::Permission.from_attributes(
        id: perm_id,
        canonical_name: perm_id
      )],
      roles: [BeefCake::Role.new(id: role_id, name: role_name)]
    )
  end

  let(:guardian_user) do
    Guardian::User.new(
      ldap_login: user_id,
      email: user_email,
      name: user_name
    )
  end

  let(:twirp_user) do
    user = Twitch::Fulton::Beefcake::User.new(
      id: user_id
    )
    user.role_memberships.replace(twirp_role_memberships)
    user.permissions.replace(twirp_permissions)
    user
  end

  let(:twirp_role_memberships) do
    [
      Twitch::Fulton::Beefcake::User::RoleMembership.new(
        id: role_id,
        name: role_name
      )
    ]
  end

  let(:twirp_permissions) do
    [
      # non legacy permissions should be ignored
      Twitch::Fulton::Beefcake::AttachedPermission.new(
        id: 'non-legacy',
        permission: Twitch::Fulton::Beefcake::Permission.new(
          twitch_user: Twitch::Fulton::Beefcake::Permission::TwitchUserPermission.new
        )
      ),
      Twitch::Fulton::Beefcake::AttachedPermission.new(
        id: role_perm_id,
        permission: Twitch::Fulton::Beefcake::Permission.new(
          legacy: Twitch::Fulton::Beefcake::Permission::LegacyPermission.new(
            id: perm_id,
            name: perm_name
          )
        )
      )
    ]
  end

  let(:legacy_permission) do
    Twitch::Fulton::Beefcake::AttachedPermission.new(
      permission: Twitch::Fulton::Beefcake::Permission.new(
        legacy: Twitch::Fulton::Beefcake::Permission::LegacyPermission.new(
          id: perm_id,
          name: perm_name
        )
      )
    )
  end
end
