package com.red.circle.other.infra.database.mongo.service.live.impl;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.mongodb.BasicDBObject;
import com.red.circle.common.business.core.ReplaceString;
import com.red.circle.common.business.core.SensitiveWordFilter;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.other.infra.database.mongo.entity.live.RoomCounter;
import com.red.circle.other.infra.database.mongo.entity.live.RoomProfile;
import com.red.circle.other.infra.database.mongo.entity.live.RoomProfileManager;
import com.red.circle.other.infra.database.mongo.entity.live.RoomSetting;
import com.red.circle.other.infra.database.mongo.service.live.RoomProfileManagerService;
import com.red.circle.other.inner.asserts.DynamicErrorCode;
import com.red.circle.other.inner.model.cmd.room.RoomProfileOpsQryCmd;
import com.red.circle.other.inner.model.dto.material.UseBadgeDTO;
import com.red.circle.other.inner.model.dto.material.UsePropsDTO;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.obj.ObjectUtils;
import com.red.circle.tool.core.text.StringUtils;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

/**
 * 房间资料信息 实现.
 *
 * @author authName on 2022/2/12
 */
@Service
@RequiredArgsConstructor
public class RoomProfileManagerServiceImpl implements RoomProfileManagerService {

  private final MongoTemplate mongoTemplate;

  @Override
  public boolean existsUserRoom(Long userId) {
    return mongoTemplate.exists(Query.query(Criteria.where("userId").is(userId)),
        RoomProfileManager.class);
  }

  @Override
  public void create(RoomProfileManager profile) {
    mongoTemplate.save(profile);
  }

  @Override
  public Long getHomeownerId(Long roomId) {
    Query query = Query.query(Criteria.where("id").is(roomId));
    query.fields().include("userId");
    return Optional.ofNullable(mongoTemplate.findOne(query, RoomProfileManager.class))
        .map(RoomProfileManager::getUserId)
        .orElse(null);
  }

  @Override
  public Long getRoomId(Long userId) {
    Query query = Query.query(Criteria.where("userId").is(userId));
    query.fields().include("id");
    return Optional.ofNullable(mongoTemplate.findOne(query, RoomProfileManager.class))
        .map(RoomProfileManager::getId)
        .orElse(null);
  }

  @Override
  public String getRoomSysOrigin(Long roomId) {
    Query query = Query.query(Criteria.where("id").is(roomId));
    query.fields().include("sysOrigin");
    return Optional.ofNullable(mongoTemplate.findOne(query, RoomProfileManager.class))
        .map(RoomProfileManager::getSysOrigin)
        .orElse(null);
  }

  @Override
  public RoomProfile getProfileById(Long roomId) {
    Query query = Query.query(Criteria.where("id").is(roomId));
    ObjectUtils.getObjectField(RoomProfile.class).forEach(field -> query.fields().include(field));
    return mongoTemplate.findOne(query,
        RoomProfileManager.class);
  }

  @Override
  public RoomProfile getProfileByUserId(Long userId) {
    Query query = Query.query(Criteria.where("userId").is(userId));
    ObjectUtils.getObjectField(RoomProfile.class).forEach(field -> query.fields().include(field));
    return mongoTemplate.findOne(query,
        RoomProfileManager.class);
  }

  @Override
  public RoomProfileManager getById(Long roomId) {
    return filterExpireTimeDecorate(
        mongoTemplate.findOne(Query.query(Criteria.where("id").is(roomId)),
            RoomProfileManager.class));
  }

  @Override
  public RoomProfileManager getByUserId(Long userId) {
    return filterExpireTimeDecorate(
        mongoTemplate.findOne(Query.query(Criteria.where("userId").is(userId)),
            RoomProfileManager.class));
  }

  @Override
  public RoomProfileManager getByRoomAccount(String account) {
    return filterExpireTimeDecorate(
        mongoTemplate.findOne(Query.query(Criteria.where("roomAccount").is(account)),
            RoomProfileManager.class));
  }

  @Override
  public Map<Long, RoomProfileManager> mapByRoomIds(Set<Long> roomIds) {
    if (CollectionUtils.isEmpty(roomIds)) {
      return CollectionUtils.newHashMap();
    }
    List<RoomProfileManager> roomProfileManagers = listByRoomIds(roomIds);
    if (CollectionUtils.isEmpty(roomProfileManagers)) {
      return CollectionUtils.newHashMap();
    }
    return roomProfileManagers.stream()
        .collect(Collectors.toMap(RoomProfileManager::getId, Function.identity(),
            (k, v) -> filterExpireTimeDecorate(v)));
  }

  @Override
  public Map<Long, RoomProfile> mapProfileByRoomIds(Set<Long> roomIds) {
    if (CollectionUtils.isEmpty(roomIds)) {
      return CollectionUtils.newHashMap();
    }
    List<RoomProfile> roomProfiles = listProfileByRoomIds(roomIds);
    if (CollectionUtils.isEmpty(roomProfiles)) {
      return CollectionUtils.newHashMap();
    }
    return roomProfiles.stream()
        .collect(Collectors.toMap(RoomProfile::getId, Function.identity(),
            (k, v) -> v));
  }

  @Override
  public Map<Long, RoomProfile> mapProfileByUserIds(Set<Long> userIds) {
    if (CollectionUtils.isEmpty(userIds)) {
      return CollectionUtils.newHashMap();
    }
    List<RoomProfile> roomProfiles = listProfileByUserIds(userIds);
    if (CollectionUtils.isEmpty(roomProfiles)) {
      return CollectionUtils.newHashMap();
    }
    return roomProfiles.stream()
        .collect(Collectors.toMap(RoomProfile::getUserId, Function.identity(),
            (k, v) -> v));
  }

  @Override
  public List<RoomProfileManager> listByRoomIds(Set<Long> roomIds) {
    if (CollectionUtils.isEmpty(roomIds)) {
      return Lists.newArrayList();
    }
    return filterExpireTimeDecorate(
        mongoTemplate.find(Query.query(Criteria.where("id").in(roomIds)),
            RoomProfileManager.class)
    );
  }

  @Override
  public List<RoomProfile> listProfileByRoomIds(Set<Long> roomIds) {
    if (CollectionUtils.isEmpty(roomIds)) {
      return Lists.newArrayList();
    }
    Query query = Query.query(Criteria.where("id").in(roomIds));
    ObjectUtils.getObjectField(RoomProfile.class).forEach(field -> query.fields().include(field));
    return Optional.of(mongoTemplate.find(query, RoomProfileManager.class))
        .map(rooms -> rooms.stream().map(room -> (RoomProfile) room).collect(Collectors.toList()))
        .orElseGet(Lists::newArrayList);
  }

  @Override
  public List<RoomProfile> listProfileByUserIds(Set<Long> userIds) {
    System.out.println("id信息"+ JSON.toJSONString(userIds));
    if (CollectionUtils.isEmpty(userIds)) {
      return Lists.newArrayList();
    }
    Query query = Query.query(Criteria.where("userId").in(userIds));
    ObjectUtils.getObjectField(RoomProfile.class).forEach(field -> query.fields().include(field));
    return Optional.of(mongoTemplate.find(query, RoomProfileManager.class))
        .map(rooms -> rooms.stream().map(room -> (RoomProfile) room).collect(Collectors.toList()))
        .orElseGet(Lists::newArrayList);
  }

  @Override
  public List<RoomProfileManager> listSelectiveLimit100(String sysOrigin, String countryCode,
      List<Long> excludeIds) {

    Criteria criteria = Criteria.where("sysOrigin").in(sysOrigin)
        .and("del").is(Boolean.FALSE);
    if (StringUtils.isNotBlank(countryCode)) {
      criteria.and("countryCode").is(countryCode);
    }

    if (CollectionUtils.isNotEmpty(excludeIds)) {
      criteria.and("id").nin(excludeIds);
    }

    return filterExpireTimeDecorate(
        mongoTemplate.find(Query.query(criteria)
            .limit(100), RoomProfileManager.class)
    );
  }

  @Override
  public List<RoomProfileManager> listSelectiveLimit100(String sysOrigin,
      List<String> countryCodes, List<Long> excludeIds) {

    Criteria criteria = Criteria.where("sysOrigin").in(sysOrigin);
    if (CollectionUtils.isNotEmpty(countryCodes)) {
      criteria.and("countryCode").nin(countryCodes);
    }

    if (CollectionUtils.isNotEmpty(excludeIds)) {
      criteria.and("id").nin(excludeIds);
    }
    criteria.and("activeTime").gte(LocalDateTime.now().minusDays(7));
    return filterExpireTimeDecorate(
        mongoTemplate.find(Query.query(criteria)
            .limit(100), RoomProfileManager.class)
    );
  }

  @Override
  public List<RoomProfileManager> listNowCreateRoom(String sysOrigin, Integer limit) {
    return filterExpireTimeDecorate(
        mongoTemplate.find(Query.query(Criteria.where("sysOrigin").is(sysOrigin)
                .and("createTime").gte(LocalDate.now()))
            .with(Sort.by(Sort.Order.desc("createTime")))
            .limit(limit), RoomProfileManager.class)
    );
  }

  @Override
  public List<RoomProfileManager> listOps(RoomProfileOpsQryCmd query) {
    Criteria criteria = Criteria.where("sysOrigin").is(query.getSysOrigin());

    if (Objects.nonNull(query.getRoomId())) {
      criteria.and("id").is(query.getRoomId());
    }

    if (Objects.nonNull(query.getRoomId()) && Objects.equals(query.getRoomId(),
        query.getLastId())) {
      return CollectionUtils.newArrayList();
    }

    if (Objects.nonNull(query.getLastId())) {
      criteria.and("id").lt(query.getLastId());
    }

    if (StringUtils.isNotBlank(query.getRoomAccount())) {
      criteria.and("roomAccount").is(query.getRoomAccount());
    }

    if (Objects.nonNull(query.getUserId())) {
      criteria.and("userId").is(query.getUserId());
    }

    if (Objects.nonNull(query.getDel())) {
      criteria.and("del").is(query.getDel());
    }

    if (StringUtils.isNotBlank(query.getEvent())) {
      criteria.and("event").is(query.getEvent());
    }

    return mongoTemplate.find(Query.query(criteria)
            .with(Sort.by(Sort.Order.desc("id")))
            .limit(query.getLimit()),
        RoomProfileManager.class);
  }

  @Override
  public RoomSetting getRoomSettingById(Long roomId) {
    Query query = Query.query(Criteria.where("id").is(roomId));
    query.fields().include("setting");
    return Optional.ofNullable(mongoTemplate.findOne(query,
            RoomProfileManager.class))
        .map(RoomProfileManager::getSetting)
        .orElse(null);
  }

  @Override
  public RoomSetting getRoomSettingByUserId(Long userId) {
    Query query = Query.query(Criteria.where("userId").is(userId));
    query.fields().include("setting");
    return Optional.ofNullable(mongoTemplate.findOne(query,
            RoomProfileManager.class))
        .map(RoomProfileManager::getSetting)
        .orElse(null);
  }

  @Override
  public RoomCounter getRoomCounterById(Long roomId) {
    Query query = Query.query(Criteria.where("id").is(roomId));
    query.fields().include("counter");
    return Optional.ofNullable(mongoTemplate.findOne(query,
            RoomProfileManager.class))
        .map(RoomProfileManager::getCounter)
        .orElse(null);
  }

  @Override
  public RoomCounter getRoomCounterByUserId(Long userId) {
    Query query = Query.query(Criteria.where("userId").is(userId));
    query.fields().include("counter");
    return Optional.ofNullable(mongoTemplate.findOne(query,
            RoomProfileManager.class))
        .map(RoomProfileManager::getCounter)
        .orElse(null);
  }

  @Override
  public boolean existsSettingPassword(Long roomId) {
    return Optional.ofNullable(getRoomSettingById(roomId))
        .map(setting -> StringUtils.isNotBlank(setting.getPassword()))
        .orElse(Boolean.FALSE);
  }

  @Override
  public void incrCounterAdminAndMember(Long roomId) {
    mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(roomId)),
        new Update().set("updateTime", TimestampUtils.now())
            .inc("counter.memberCount", 1)
            .inc("counter.adminCount", 1),
        RoomProfileManager.class);
  }

  @Override
  public void incrCounterAdmin(Long roomId) {
    mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(roomId)),
        new Update().set("updateTime", TimestampUtils.now())
            .inc("counter.adminCount", 1),
        RoomProfileManager.class);
  }

  @Override
  public void incrCounterMember(Long roomId) {
    mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(roomId)),
        new Update().set("updateTime", TimestampUtils.now())
            .inc("counter.memberCount", 1),
        RoomProfileManager.class);
  }

  @Override
  public void decrCounterAdminAndMember(Long roomId) {
    mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(roomId)),
        new Update().set("updateTime", TimestampUtils.now())
            .inc("counter.memberCount", -1)
            .inc("counter.adminCount", -1),
        RoomProfileManager.class);
  }

  @Override
  public void decrCounterAdmin(Long roomId) {
    mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(roomId)),
        new Update().set("updateTime", TimestampUtils.now())
            .inc("counter.adminCount", -1),
        RoomProfileManager.class);
  }

  @Override
  public void decrCounterMember(Long roomId) {
    mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(roomId)),
        new Update().set("updateTime", TimestampUtils.now())
            .inc("counter.memberCount", -1),
        RoomProfileManager.class);
  }

  @Override
  public Boolean updateSelectiveProfile(RoomProfile roomProfile) {
    RoomProfileManager profile = getById(roomProfile.getId());
    if (Objects.isNull(profile)) {
      return Boolean.FALSE;
    }
    mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(roomProfile.getId())),
        getUpdateSelectiveProfile(roomProfile),
        RoomProfileManager.class);
    return Boolean.TRUE;
  }

  @Override
  public void updateSelectiveSetting(Long roomId, RoomSetting roomSetting) {
    mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(roomId)),
        getUpdateSelectiveSetting(getRoomSettingById(roomId), roomSetting),
        RoomProfileManager.class);
  }

  @Override
  public void updateSelectiveSettingByUserId(Long userId, RoomSetting roomSetting) {
    mongoTemplate.updateFirst(Query.query(Criteria.where("userId").is(userId)),
        getUpdateSelectiveSetting(getRoomSettingByUserId(userId), roomSetting),
        RoomProfileManager.class);
  }

  @Override
  public void updatePassword(Long roomId, String password) {
    mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(roomId)),
        new Update().set("updateTime", TimestampUtils.now())
            .set("setting.password", password),
        RoomProfileManager.class);
  }

  @Override
  public void updateRoomCoverByUserId(Long userId, String cover) {
    mongoTemplate.updateFirst(Query.query(Criteria.where("userId").is(userId)),
        new Update().set("updateTime", TimestampUtils.now())
            .set("roomCover", cover),
        RoomProfileManager.class);
  }

  @Override
  public void updateRoomActiveTime(Long roomId) {
    mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(roomId)),
        new Update().set("activeTime", TimestampUtils.now()),
        RoomProfileManager.class);
  }

  @Override
  public void updateRoomCoverByIds(List<Long> ids, String cover) {
    if (CollectionUtils.isEmpty(ids)) {
      return;
    }
    mongoTemplate.updateMulti(Query.query(Criteria.where("id").in(ids)),
        new Update().set("updateTime", TimestampUtils.now())
            .set("roomCover", cover),
        RoomProfileManager.class);
  }

  @Override
  public void updateRoomDescByIds(List<Long> ids, String roomDesc) {
    if (CollectionUtils.isEmpty(ids)) {
      return;
    }
    if (SensitiveWordFilter.checkSensitiveWord(roomDesc)){
      ResponseAssert.isTrue(DynamicErrorCode.SENSITIVE_WORD_ERROR, false);
    }
    mongoTemplate.updateMulti(Query.query(Criteria.where("id").in(ids)),
        new Update().set("updateTime", TimestampUtils.now())
            .set("roomDesc", roomDesc),
        RoomProfileManager.class);
  }

  @Override
  public void updateUserCountry(Long userId, String countryCode, String countryName) {
    mongoTemplate.updateFirst(Query.query(Criteria.where("userId").is(userId)),
        new Update().set("updateTime", TimestampUtils.now())
            .set("countryCode", countryCode)
            .set("countryName", countryName),
        RoomProfileManager.class);
  }

  @Override
  public void updateUserLangCode(Long userId, String langCode) {
    mongoTemplate.updateFirst(Query.query(Criteria.where("userId").is(userId)),
        new Update().set("updateTime", TimestampUtils.now())
            .set("langCode", StringUtils.toUpperCase(langCode)),
        RoomProfileManager.class);
  }

  @Override
  public void addBadge(Long roomId, UseBadgeDTO useBadge) {

    if (Objects.isNull(roomId) || Objects.isNull(useBadge)) {
      throw new IllegalArgumentException("添加使用徽章参数错误.");
    }

    cleanBadge(roomId, useBadge);

    mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(roomId)),
        new Update()
            .push("useBadges", useBadge)
            .set("updateTime", TimestampUtils.now()),
        RoomProfileManager.class);
  }

  @Override
  public void updateUseBadgesOverlay(Long roomId, List<UseBadgeDTO> wearBadges) {
    mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(roomId)),
        new Update()
            .set("updateTime", TimestampUtils.now())
            .set("wearBadge", filterBadgeNotAvailable(wearBadges)),
        RoomProfileManager.class);
  }

  @Override
  public void upsertCustomizeSetting(Long roomId, Map<String, String> customizeSetting) {
    if (Objects.isNull(roomId) || CollectionUtils.isEmpty(customizeSetting)) {
      return;
    }

    RoomProfileManager profile = getById(roomId);
    if (Objects.isNull(profile)) {
      return;
    }

    if (CollectionUtils.isEmpty(profile.getCustomizeSetting())) {
      profile.setCustomizeSetting(customizeSetting);
    } else {
      customizeSetting.forEach((key, val) -> profile.getCustomizeSetting().put(key, val));
    }

    mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(roomId)),
        new Update().set("updateTime", TimestampUtils.now())
            .set("customizeSetting", profile.getCustomizeSetting()),
        RoomProfileManager.class);
  }

  @Override
  public void delUserRoom(Long userId) {
    mongoTemplate.updateFirst(Query.query(Criteria.where("userId").is(userId)),
        new Update().set("updateTime", TimestampUtils.now())
            .set("del", Boolean.TRUE),
        RoomProfileManager.class);
  }

  private List<UsePropsDTO> filterPropsNotAvailable(List<UsePropsDTO> useProps) {
    if (CollectionUtils.isNotEmpty(useProps)) {
      return useProps.stream().filter(badge -> checkAvailable(badge.getExpireTime()))
          .collect(Collectors.toList());
    }
    return useProps;
  }

  private List<UseBadgeDTO> filterBadgeNotAvailable(List<UseBadgeDTO> wearBadge) {
    if (CollectionUtils.isNotEmpty(wearBadge)) {
      return wearBadge.stream().filter(badge -> checkAvailable(badge.getExpireTime()))
          .collect(Collectors.toList());
    }
    return wearBadge;
  }

  private List<RoomProfileManager> filterExpireTimeDecorate(
      List<RoomProfileManager> roomProfileManager) {
    return Optional.of(roomProfileManager)
        .map(rooms -> rooms.stream().map(this::filterExpireTimeDecorate)
            .collect(Collectors.toList()))
        .orElseGet(Lists::newArrayList);
  }

  private RoomProfileManager filterExpireTimeDecorate(RoomProfileManager roomProfileManager) {
    if (Objects.nonNull(roomProfileManager)) {
      roomProfileManager.setUseBadges(
          roomProfileManager.filterBadges(badges -> checkAvailable(badges.getExpireTime()))
      );
    }
    return roomProfileManager;
  }

  /**
   * true 可用. false 不可用.
   */
  private boolean checkAvailable(Long expireTime) {
    return Objects.isNull(expireTime) || expireTime > TimestampUtils.now().getTime();
  }

  private void cleanBadge(Long roomId, UseBadgeDTO useBadge) {
    mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(roomId)),
        new Update()
            .pull("useBadges", new BasicDBObject("expireTime",
                new BasicDBObject("$lte", TimestampUtils.now().getTime())))
            .pull("useBadges", new BasicDBObject("id",
                new BasicDBObject("$eq", useBadge.getId())))
            .set("updateTime", TimestampUtils.now()),
        RoomProfileManager.class);
  }

  private Update getUpdateSelectiveSetting(RoomSetting oldSetting, RoomSetting newSetting) {
    Update update = new Update().set("updateTime", TimestampUtils.now());

    if (Objects.isNull(newSetting)) {
      return update;
    }

    if (Objects.nonNull(newSetting.getOpenKtvMode())) {
      update.set("setting.openKtvMode", newSetting.getOpenKtvMode());
    }

    if (StringUtils.isNotBlank(newSetting.getPassword())) {
      update.set("setting.password", newSetting.getPassword());
    }

    if (StringUtils.isNotBlank(newSetting.getTakeMicRole())) {
      update.set("setting.takeMicRole", newSetting.getTakeMicRole());
    }

    if (Objects.nonNull(newSetting.getTouristMike())) {
      update.set("setting.touristMike", newSetting.getTouristMike());
    }

    if (Objects.nonNull(newSetting.getTouristMsg())) {
      update.set("setting.touristMsg", newSetting.getTouristMsg());
    }

    if (Objects.nonNull(oldSetting)) {
      if (Objects.nonNull(newSetting.getMaxMember())
          && newSetting.getMaxMember() > oldSetting.getMaxMember()) {
        update.set("setting.maxMember", newSetting.getMaxMember());
      }

      if (Objects.nonNull(newSetting.getMaxAdmin())
          && newSetting.getMaxAdmin() > oldSetting.getMaxAdmin()) {
        update.set("setting.maxAdmin", newSetting.getMaxAdmin());
      }
    }

    if (Objects.nonNull(newSetting.getJoinGolds())) {
      update.set("setting.joinGolds", newSetting.getJoinGolds());
    }

    if (Objects.nonNull(newSetting.getMikeSize())) {
      update.set("setting.mikeSize", newSetting.getMikeSize());
    }

    if (Objects.nonNull(newSetting.getAllowMusic())) {
      update.set("setting.allowMusic", newSetting.getAllowMusic());
    }

    if (Objects.nonNull(newSetting.getAdminLockSeat())) {
      update.set("setting.adminLockSeat", newSetting.getAdminLockSeat());
    }

    if (Objects.nonNull(newSetting.getShowHeartbeat())) {
      update.set("setting.showHeartbeat", newSetting.getShowHeartbeat());
    }

    if (Objects.nonNull(newSetting.getRoomSpecialMikeType())) {
      update.set("setting.roomSpecialMikeType", newSetting.getRoomSpecialMikeType());
    }
    if (Objects.nonNull(newSetting.getRoomSpecialMikeExpireTime())) {
      update.set("setting.roomSpecialMikeExpireTime", newSetting.getRoomSpecialMikeExpireTime());
    }
    if (Objects.nonNull(newSetting.getRoomSpecialMikeExpireType())) {
      update.set("setting.roomSpecialMikeExpireType", newSetting.getRoomSpecialMikeExpireType());
    }

    return update;
  }

  private Update getUpdateSelectiveProfile(RoomProfile newProfile) {
    Update update = new Update().set("updateTime", TimestampUtils.now());

    if (Objects.isNull(newProfile)) {
      return update;
    }

    if (StringUtils.isNotBlank(newProfile.getRoomCover())) {
      update.set("roomCover", newProfile.getRoomCover());
    }
    if (StringUtils.isNotBlank(newProfile.getRoomName())) {
      update.set("roomName", newProfile.getRoomName());
    }
    if (StringUtils.isNotBlank(newProfile.getRoomDesc())) {
      update.set("roomDesc", newProfile.getRoomDesc());
    }
    if (StringUtils.isNotBlank(newProfile.getEvent())) {
      update.set("event", newProfile.getEvent());
    }
    if (StringUtils.isNotBlank(newProfile.getCountryName())) {
      update.set("countryName", newProfile.getCountryName());
    }
    if (StringUtils.isNotBlank(newProfile.getCountryCode())) {
      update.set("countryCode", newProfile.getCountryCode());
    }
    if (StringUtils.isNotBlank(newProfile.getLangCode())) {
      update.set("langCode", newProfile.getLangCode());
    }
    return update;
  }
}
