package com.red.circle.other.inner.model.dto.user;


import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.red.circle.common.business.enums.AccountStatusEnum;
import com.red.circle.common.business.enums.ConsoleAccountStatusEnum;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.text.StringUtils;
import com.red.circle.other.inner.model.dto.user.props.UserUseBadgeDTO;
import com.red.circle.other.inner.model.dto.user.props.UserUsePropsDTO;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import lombok.Data;

import static com.red.circle.common.business.enums.AccountStatusEnum.ARCHIVE;

/**
 * 用户资料.
 *
 * @author pengliang on 2020/10/30
 */
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class UserProfileDTO implements Serializable {

  @Serial
  private static final long serialVersionUID = 1L;

  /**
   * 用户id.
   */
  @JsonSerialize(using = ToStringSerializer.class)
  private Long id;

  /**
   * 账号.
   */
  private String account;

  /**
   * 头像.
   */
  private String userAvatar;

  /**
   * 用户昵称.
   */
  private String userNickname;

  /**
   * 用户性别:0 女，1 男.
   */
  private Integer userSex;

  /**
   * 年龄.
   */
  private Integer age;

  /**
   * 账号状态.
   */
  private String accountStatus;

  /**
   * 冻结时间.
   */
  private Timestamp freezingTime;

  /**
   * 是否修改过国家  0 否，1 是.
   */
  private String isUpdateCountry;

  /**
   * 国家id.
   */
  @JsonSerialize(using = ToStringSerializer.class)
  private Long countryId;

  /**
   * 国家名称.
   */
  private String countryName;

  /**
   * 国家编码.
   */
  private String countryCode;


  /**
   * 个性签名.
   */
  private String autograph;

  /**
   * 爱好
   */
  private String hobby;


  /**
   * CP列表
   */
  private List<CpSimpleUserProfileCO> cpList;

  /**
   * 是否cp关系
   */
  private Boolean isCpRelation;

  /**
   * 家族ID
   */
  @JsonSerialize(using = ToStringSerializer.class)
  private Long familyId;

  /**
   * 背景照片列表（最多9张）
   */
  private List<PhotoItem> backgroundPhotos;

  /**
   * 个人形象照片列表（最多9张）
   */
  private List<PhotoItem> personalPhotos;


  private String inRoomId;
  private String roomIcon;

  /**
   * 如果国家code是IA强制变更ID.适配印尼分国家
   */
  public void setCountryCode(String countryCode) {
    if (Objects.nonNull(countryCode) && Objects.equals(countryCode, "IA")) {
      this.countryCode = "ID";
    } else if (Objects.nonNull(countryCode) && Objects.equals(countryCode, "EY")) {
      this.countryCode = "EG";
    } else if (Objects.nonNull(countryCode) && Objects.equals(countryCode, "AB")) {
      this.countryCode = "AE";
    } else if (Objects.nonNull(countryCode) && Objects.equals(countryCode, "MB")) {
      this.countryCode = "MA";
    } else if (Objects.nonNull(countryCode) && Objects.equals(countryCode, "SP")) {
      this.countryCode = "SA";
    } else {
      this.countryCode = countryCode;
    }
  }

  /**
   * 区域Code
   */
  private String regionCode;

  /**
   * 财富等级.
   */
  private Integer wealthLevel;

  /**
   * 魅力等级.
   */
  private Integer charmLevel;

  /**
   * 系统来源.
   */
  private String originSys;

  /**
   * 子系统.
   */
  private String sysOriginChild;

  /**
   * 0.未删除 1.已删除.
   */
  private Boolean del;

  /**
   * 创建时间.
   */
  private Timestamp createTime;

  /**
   * 出身年.
   */
  private Integer bornYear;

  /**
   * 出身月.
   */
  private Integer bornMonth;

  /**
   * 出身日.
   */
  private Integer bornDay;

  /**
   * 拥有的靓号ID.
   */
  private OwnSpecialIdDTO ownSpecialId;

  /**
   * 使用的道具.
   */
  private List<UserUsePropsDTO> useProps;

  /**
   * 是否在同区域.ture显示聊天按钮和添加好友按钮，false隐藏聊天按钮和添加好友按钮
   */
  private Boolean sameRegion;

    /**
     * 是否金币代理
     */
  private Boolean isFreightAgent;

  /**
   * 是否超级金币代理
   */
  private Boolean isSuperFreightAgent;

    /**
     * 是否未完成首充
     */
  private Boolean firstRecharge;

  /**
   * 首充金额
   */
  private BigDecimal firstRechargeAmount;

    /**
     * 首充结束时间
     */
  private Timestamp firstRechargeEndTime;

  /**
   * 用户使用的徽章.
   */
  private List<UserUseBadgeDTO> wearBadge;

    /**
     * 用户使用的荣誉.
     */
    private List<UserUseBadgeDTO> wearHonor;

  public List<UserUsePropsDTO> filterProps(Predicate<UserUsePropsDTO> predicate) {
    return Optional.ofNullable(useProps)
        .map(usePropsEntities -> usePropsEntities.stream()
            .filter(Objects::nonNull)
            .filter(predicate)
            .collect(Collectors.toList()))
        .orElseGet(CollectionUtils::newArrayList);
  }

  /**
   * 冻结解冻时间 用于返回计算后的冻结间隔时间，解决返回客户端时区问题.
   *
   * @return 时间
   */
  @JsonSerialize(using = ToStringSerializer.class)
  public Long getFreezingExpiredInterval() {
    return TimestampUtils.expiredInterval(freezingTime);
  }

  public boolean eqSysOrigin(String sysOrigin) {
    return StringUtils.startsWith(this.originSys, sysOrigin);
  }

  /**
   * 获取实际的账号.
   */
  @JsonIgnore
  public String getActualAccount() {
    return checkOwnSpecialIdAvailable() ? this.ownSpecialId.getAccount() : this.account;
  }

  /**
   * 账号是否正常.
   *
   * @return true 是， false 否
   */
  public boolean checkAccountAvailable() {
    return !checkAccountArchive() && !checkAccountFreeze();
  }

  /**
   * 账号是否为封禁状态.
   *
   * @return true 是， false 否
   */
  public boolean checkAccountArchive() {
    return AccountStatusEnum.isArchive(this.accountStatus);
  }

  /**
   * 账号是否为冻结状态.
   *
   * @return true 是， false 否
   */
  public boolean checkAccountFreeze() {
    return AccountStatusEnum.isFreeze(this.freezingTime);
  }

  /**
   * 判断纠正账号状态.
   */
  public AccountStatusEnum getAccountStatus() {
    if (this.checkAccountAvailable()) {
      return AccountStatusEnum.NORMAL;
    }

    // 封存了，但是时间过期了
    if (Objects.equals(ARCHIVE.name(), this.accountStatus) && !this.checkAccountFreeze()) {
      return AccountStatusEnum.NORMAL;
    }

    if (this.checkAccountFreeze()) {
      return AccountStatusEnum.FREEZE;
    }

    return AccountStatusEnum.valueOf(this.accountStatus);
  }

  /**
   * 检查靓号是否可用.
   */
  private boolean checkOwnSpecialIdAvailable() {
    boolean exists = Objects.nonNull(this.ownSpecialId)
        && Objects.nonNull(this.ownSpecialId.getAccount());

    if (!exists) {
      return false;
    }

    return Objects.isNull(this.ownSpecialId.getExpiredTime())
        || this.ownSpecialId.getExpiredTime().after(TimestampUtils.now());
  }

  /**
   * 获取实际的账号.
   */
  public String actualAccount() {
    return checkOwnSpecialIdAvailable() ? this.ownSpecialId.getAccount() : this.account;
  }

  /**
   * 检查账号是否可用.
   */
  public boolean checkAccountAvailable(String accountStatus, Timestamp freezingTime) {

    if (Objects.nonNull(freezingTime) && freezingTime.after(TimestampUtils.now())) {
      return false;
    }

    if (Objects.equals(AccountStatusEnum.FREEZE.name(), accountStatus)) {
      return true;
    }

    return Objects.equals(accountStatus, AccountStatusEnum.NORMAL.name());
  }


  /**
   * 账号状态名称.
   */
  public String getAccountStatusName() {
    if (Objects.nonNull(this.freezingTime) && this.freezingTime.after(
        TimestampUtils.now())) {
      return ConsoleAccountStatusEnum.FREEZE.getDesc();
    }

    if (Objects.equals(ConsoleAccountStatusEnum.FREEZE.name(), accountStatus)) {
      return ConsoleAccountStatusEnum.NORMAL.getDesc();
    }

    return ConsoleAccountStatusEnum.getDescValue(this.getActualAccountStatus());
  }

  /**
   * 账号状态.
   */
  public String getActualAccountStatus() {
    if (Objects.nonNull(this.freezingTime) && this.freezingTime.after(
        TimestampUtils.now())) {
      return AccountStatusEnum.FREEZE.name();
    }
    if (Objects.equals(AccountStatusEnum.FREEZE.name(), this.accountStatus)) {
      return AccountStatusEnum.NORMAL.name();
    }
    return this.accountStatus;
  }
}
