package com.ruoyi.xq.manager;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.BeanConvertUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.xq.domain.*;
import com.ruoyi.xq.dto.app.common.UserPicturesDTO;
import com.ruoyi.xq.dto.app.user.AddPicturesReq;
import com.ruoyi.xq.dto.app.user.UpdateBaseInfoReq;
import com.ruoyi.xq.dto.app.user.UpdateUserAuthInfoReq;
import com.ruoyi.xq.dto.app.user.UpdateUserFullInfoReq;
import com.ruoyi.xq.dto.app.user.vo.*;
import com.ruoyi.xq.enums.common.AuditEnum;
import com.ruoyi.xq.enums.common.SystemConfigEnum;
import com.ruoyi.xq.enums.user.UserAuthTypeEnum;
import com.ruoyi.xq.enums.user.UserInfoAuditTypeEnum;
import com.ruoyi.xq.enums.userauth.UserAuthJobAuthTypeEnum;
import com.ruoyi.xq.enums.userinfo.UserGenderEnum;
import com.ruoyi.xq.lock.LockKey;
import com.ruoyi.xq.service.*;
import com.ruoyi.xq.util.AgeUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.BooleanUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class CurrentUserManager {
    @Autowired
    private UserService userService;
    @Autowired
    private UserPicturesService userPicturesService;
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private UserAuthService userAuthService;
    @Autowired
    private UserAuthAuditService userAuthAuditService;
    @Autowired
    private UserInfoAuditService userInfoAuditService;
    @Autowired
    private SystemConfigManager systemConfigManager;
    @Autowired
    private AreaCodeService areaCodeService;
    @Autowired
    private UserVipService userVipService;
    @Autowired
    private UserExtendService userExtendService;


    public CurrentUserFullInfoVo currentFullInfo(){
        Long userId = LoginHelper.getUserId();
        User user = userService.getById(userId);
        UserInfo userInfo = userInfoService.getByUserId(userId);
        CurrentUserFullInfoVo result = new CurrentUserFullInfoVo();
        BeanConvertUtil.copyProperties(userInfo,result);
        BeanConvertUtil.copyProperties(user,result);
        UserInfoAudit avatarAudit = userInfoAuditService.getAuditingDataByUserIdAndType(userId, UserInfoAuditTypeEnum.AVATAR);
        AvatarMinAuditDTO avatarAuditInfo = new AvatarMinAuditDTO();
        avatarAuditInfo.setAvatar(user.getAvatar());
        avatarAuditInfo.setAuditStatus(AuditEnum.NO.getCode());
        if(avatarAudit != null){
            avatarAuditInfo.setAvatar(avatarAudit.getAuditContent());
            avatarAuditInfo.setAuditStatus(avatarAudit.getAuditStatus());
        }
        result.setAvatarAudit(avatarAuditInfo);

        UserInfoAudit remarkAudit = userInfoAuditService.getAuditingDataByUserIdAndType(userId, UserInfoAuditTypeEnum.REMARK);
        RemarkMinAuditDTO remarkAuditInfo = new RemarkMinAuditDTO();
        remarkAuditInfo.setRemark(user.getRemark());
        remarkAuditInfo.setAuditStatus(AuditEnum.NO.getCode());
        if(remarkAudit != null){
            remarkAuditInfo.setRemark(remarkAudit.getAuditContent());
            remarkAuditInfo.setAuditStatus(remarkAudit.getAuditStatus());
        }
        result.setRemarkAudit(remarkAuditInfo);

        List<UserPictures> userPictures = userPicturesService.listByUserIdAuditingAndSuccess(user.getId());
        result.setUserPicturesList(BeanConvertUtil.convertListTo(userPictures, UserPicturesDTO::new));
        return result;
    }
    public CurrentUserInfoVo currentBaseInfo() {
        Long userId = LoginHelper.getUserId();
        User user = userService.getById(userId);
        CurrentUserInfoVo vo = new CurrentUserInfoVo();
        vo.setUserId(user.getId());
        vo.setUsercode(user.getUsercode());
        vo.setType(user.getType());
        vo.setNickname(user.getNickname());
        vo.setMobile(user.getMobile());
        vo.setAvatar(user.getAvatar());
        vo.setGender(user.getGender());
        vo.setBirthday(user.getBirthday());
        vo.setAge(AgeUtil.getAge(user.getBirthday()));
        vo.setResidenceCityName(user.getResidenceCityName());
        vo.setResidenceCityCode(user.getResidenceCityCode());
        vo.setResidenceCode(user.getResidenceCode());
        vo.setResidenceName(user.getResidenceName());
        vo.setAddressCode(user.getAddressCode());
        vo.setAddressName(user.getAddressName());
        vo.setStatus(user.getStatus());
        vo.setFinishBaseStatus(user.getFinishBaseStatus());
        vo.setBaseStep(user.getBaseStep());
        vo.setImToken(user.getImToken());
        vo.setWxCode(user.getWxCode());
        UserAuth userAuth = userAuthService.getByUserId(userId);
        vo.setAlreadyAuthNum(userAuth.getAlreadyAuthNum());
        List<UserPictures> userPictures = userPicturesService.listByUserIdAuditingAndSuccess(user.getId());
        vo.setUserPicturesList(BeanConvertUtil.convertListTo(userPictures, UserPicturesDTO::new));
        if(user.getOpenVip() != null){
            vo.setOpenVip(user.getOpenVip());
            vo.setVipType(user.getVipType());
            vo.setVipTimeout(user.getVipTimeout());
        }
        UserExtend userExtend = userExtendService.getByUserId(userId);
        vo.setIncomeCoin(userExtend.getIncomeCoin());
        vo.setWxTransNum(userExtend.getWxTransNum());
        return vo;
    }

    /**
     * 更新基础信息
     * @param req
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateBaseInfo(UpdateBaseInfoReq req) {
        Long userId = LoginHelper.getUserId();
        User updateUser = BeanConvertUtil.convertTo(req, User::new);
        UserGenderEnum userGenderEnum = UserGenderEnum.getByCode(req.getGender());
        if(userGenderEnum != null){
            String cos = systemConfigManager.getSystemConfig(SystemConfigEnum.COS_DOMAIN);
            updateUser.setAvatar(cos + userGenderEnum.getDefaultAvatar());
        }
        if(req.getAddressCode() != null){
            AreaCode areaCode = areaCodeService.getById(req.getAddressCode());
            updateUser.setAddressCode(req.getAddressCode());
            updateUser.setAddressName(areaCode.getName());
        }
        if(req.getResidenceCode() != null){
            AreaCode areaCode = areaCodeService.getById(req.getResidenceCode());
            updateUser.setResidenceCode(req.getResidenceCode());
            updateUser.setResidenceName(areaCode.getName());
            updateUser.setResidenceCityCode(areaCode.getCityCode());
            updateUser.setResidenceCityName(areaCode.getCityName());
        }
        if(req.getHeight() != null){
            updateUser.setHeight(req.getHeight());
        }
        if(req.getBirthday() != null){
            updateUser.setAge(AgeUtil.getAge(req.getBirthday()));
        }
        if(req.getWeight() != null){
            updateUser.setWeight(req.getWeight());
        }
        updateUser.setUpdateTime(LocalDateTime.now());
        updateUser.setId(userId);
        userService.updateById(updateUser);

        UserInfo updateUserInfo = BeanConvertUtil.convertTo(req, UserInfo::new);
        UserInfo userInfo = userInfoService.getByUserId(userId);
        updateUserInfo.setUpdateTime(LocalDateTime.now());
        updateUserInfo.setId(userInfo.getId());
        userInfoService.updateById(updateUserInfo);
        // 检查finishStatus
        userService.checkFinishStatus(userId);
    }

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 更新备注信息
     */
    public void updateRemark(String remark){
        Long userId = LoginHelper.getUserId();
        User user = userService.getById(userId);
        RLock lock = redissonClient.getLock(LockKey.getUserInfoAuditLock(userId));
        try {
            if(lock.isLocked()){
                log.warn("点击太快了，等一等，dealInviteId");
                return;
            }
            lock.lock(5,TimeUnit.SECONDS);
            UserInfoAudit audit = userInfoAuditService.getAuditingDataByUserIdAndType(userId, UserInfoAuditTypeEnum.REMARK);
            if(audit == null){
                audit = new UserInfoAudit();
                audit.setUserId(userId);
                audit.setUsercode(user.getUsercode());
                audit.setInfoType(UserInfoAuditTypeEnum.REMARK.getCode());
                audit.setAuditBeforeContent(user.getRemark());
                audit.setAuditContent(remark);
                audit.setAuditStatus(AuditEnum.AUDITING.getCode());
                userInfoAuditService.save(audit);
            }else{
                userInfoAuditService.update(Wrappers.lambdaUpdate(UserInfoAudit.class)
                        .set(UserInfoAudit::getAuditContent, remark)
                        .set(UserInfoAudit::getAuditBeforeContent, user.getRemark())
                        .eq(UserInfoAudit::getId, audit.getId()));
            }
        } finally {
            lock.unlockAsync();
        }
    }

    public void updateAvatar(String avatar){
        Long userId = LoginHelper.getUserId();
        User user = userService.getById(userId);
        RLock lock = redissonClient.getLock(LockKey.getUserInfoAuditLock(userId));
        try {
            if(lock.isLocked()){
                log.warn("点击太快了，等一等，dealInviteId");
                return;
            }
            lock.lock(5,TimeUnit.SECONDS);
            UserInfoAudit audit = userInfoAuditService.getAuditingDataByUserIdAndType(userId, UserInfoAuditTypeEnum.AVATAR);
            if(audit == null){
                audit = new UserInfoAudit();
                audit.setUserId(userId);
                audit.setUsercode(user.getUsercode());
                audit.setInfoType(UserInfoAuditTypeEnum.AVATAR.getCode());
                audit.setAuditBeforeContent(user.getAvatar());
                audit.setAuditContent(avatar);
                audit.setAuditStatus(AuditEnum.AUDITING.getCode());
                userInfoAuditService.save(audit);
            }else{
                userInfoAuditService.update(Wrappers.lambdaUpdate(UserInfoAudit.class)
                        .set(UserInfoAudit::getAuditContent, avatar)
                        .set(UserInfoAudit::getAuditBeforeContent, user.getAvatar())
                        .eq(UserInfoAudit::getId, audit.getId()));
            }
        } finally {
            lock.unlockAsync();
        }
    }

    public void updateInfo(UpdateUserFullInfoReq req) {
        Long userId = LoginHelper.getUserId();
        User updateUser = BeanConvertUtil.convertTo(req, User::new);
        if(req.getAddressCode() != null){
            AreaCode areaCode = areaCodeService.getById(req.getAddressCode());
            updateUser.setAddressCode(req.getAddressCode());
            updateUser.setAddressName(areaCode.getFullname());
        }
        if(req.getResidenceCode() != null){
            AreaCode areaCode = areaCodeService.getById(req.getResidenceCode());
            updateUser.setResidenceCode(req.getResidenceCode());
            updateUser.setResidenceName(areaCode.getFullname());
            updateUser.setResidenceCityName(areaCode.getPname());
        }
        if(req.getBirthday() != null){
            updateUser.setAge(AgeUtil.getAge(req.getBirthday()));
        }
        updateUser.setId(userId);
        userService.updateById(updateUser);

        UserInfo updateUserInfo = BeanConvertUtil.convertTo(req, UserInfo::new);
        if(req.getFilterResidenceCode() != null){
            AreaCode areaCode = areaCodeService.getById(req.getResidenceCode());
            updateUserInfo.setFilterResidenceCode(req.getFilterResidenceCode());
            updateUserInfo.setFilterResidence(areaCode.getFullname());
        }
        UserInfo userInfo = userInfoService.getByUserId(userId);
        updateUserInfo.setId(userInfo.getId());
        updateUserInfo.setUpdateTime(LocalDateTime.now());
        userInfoService.updateById(updateUserInfo);
    }

    public UserAuthInfoVo currentAuthInfo() {
        Long userId = LoginHelper.getUserId();
        UserAuth userAuth = userAuthService.getByUserId(userId);
        return BeanConvertUtil.convertTo(userAuth, UserAuthInfoVo::new);
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateInfoAuth(UpdateUserAuthInfoReq req) {
        Long userId = LoginHelper.getUserId();
        User user = userService.getById(userId);
        if(BooleanUtils.isTrue(req.getPushCarAuth())){ // 车辆认证
            if(req.getCarPic() == null){
                throw new ServiceException("请上传车辆认证照片");
            }
            boolean update = userAuthService.update(Wrappers.lambdaUpdate(UserAuth.class)
                    .eq(UserAuth::getUserId, userId)
                    .in(UserAuth::getCarAuth, AuditEnum.NO.getCode(), AuditEnum.FAIL.getCode())
                    .set(UserAuth::getCarAuth, AuditEnum.AUDITING.getCode()));
            if(!update){
                throw new ServiceException("车辆认证正在审核中，请勿重复提交");
            }
            userAuthAuditService.saveAuthAudit(user,UserAuthTypeEnum.CAR,req.getCarPic());
        }
        if(BooleanUtils.isTrue(req.getPushHouseAuth())){ // 房子认证
            if(req.getHousePic() == null){
                throw new ServiceException("请上传房产认证照片");
            }
            boolean update = userAuthService.update(Wrappers.lambdaUpdate(UserAuth.class)
                    .eq(UserAuth::getUserId, userId)
                    .in(UserAuth::getHouseAuth, AuditEnum.NO.getCode(), AuditEnum.FAIL.getCode())
                    .set(UserAuth::getHouseAuth, AuditEnum.AUDITING.getCode()));
            if(!update){
                throw new ServiceException("房产认证正在审核中，请勿重复提交");
            }
            userAuthAuditService.saveAuthAudit(user,UserAuthTypeEnum.HOUSE,req.getHousePic());
        }
        if(BooleanUtils.isTrue(req.getPushEducationAuth())){ // 学历认证
            if(req.getEducationPic() == null){
                throw new ServiceException("请上传最高学历认证照片");
            }
            boolean update = userAuthService.update(Wrappers.lambdaUpdate(UserAuth.class)
                    .eq(UserAuth::getUserId, userId)
                    .in(UserAuth::getEducationAuth, AuditEnum.NO.getCode(), AuditEnum.FAIL.getCode())
                    .set(UserAuth::getEducationAuth, AuditEnum.AUDITING.getCode()));
            if(!update){
                throw new ServiceException("房产认证正在审核中，请勿重复提交");
            }
            userAuthAuditService.saveAuthAudit(user,UserAuthTypeEnum.EDUCATION,req.getEducationPic());
        }
        if(BooleanUtils.isTrue(req.getPushMarriageAuth())){ // 婚况认证
            if(req.getMarriagePic() == null){
                throw new ServiceException("请上传婚况认证照片");
            }
            boolean update = userAuthService.update(Wrappers.lambdaUpdate(UserAuth.class)
                    .eq(UserAuth::getUserId, userId)
                    .in(UserAuth::getMarriageAuth, AuditEnum.NO.getCode(), AuditEnum.FAIL.getCode())
                    .set(UserAuth::getMarriageAuth, AuditEnum.AUDITING.getCode()));
            if(!update){
                throw new ServiceException("房产认证正在审核中，请勿重复提交");
            }
            userAuthAuditService.saveAuthAudit(user,UserAuthTypeEnum.MARRIAGE,req.getMarriagePic());
        }
        if(BooleanUtils.isTrue(req.getPushJobAuthBoo())){ // 工作认证
            UserAuthJobAuthTypeEnum userAuthJobAuthTypeEnum = UserAuthJobAuthTypeEnum.getByCode(req.getJobAuthType());
            if(userAuthJobAuthTypeEnum == null){
                throw new ServiceException("请选择工作认证方式");
            }
            if(req.getJobPic() == null){
                throw new ServiceException("请上传工作认证照片");
            }
            boolean update = userAuthService.update(Wrappers.lambdaUpdate(UserAuth.class)
                    .eq(UserAuth::getUserId, userId)
                    .in(UserAuth::getJobAuth, AuditEnum.NO.getCode(), AuditEnum.FAIL.getCode())
                    .set(UserAuth::getJobAuth, AuditEnum.AUDITING.getCode()));
            if(!update){
                throw new ServiceException("房产认证正在审核中，请勿重复提交");
            }
            String authRemark = String.format("【%s】工作认证", userAuthJobAuthTypeEnum.getText());
            userAuthAuditService.saveAuthAudit(user,UserAuthTypeEnum.JOB,req.getJobPic(),authRemark);
        }
    }


    public void addUserPicture(AddPicturesReq req) {
        Long userId = LoginHelper.getUserId();
        User user = userService.getById(userId);
        UserPictures userPictures = new UserPictures();
        userPictures.setUserId(user.getId());
        userPictures.setUsercode(user.getUsercode());
        userPictures.setPicture(req.getPicture());
        userPictures.setAuditStatus(AuditEnum.AUDITING.getCode());
        userPicturesService.save(userPictures);
    }

    public void removeUserPictures(List<Long> ids) {
        Long userId = LoginHelper.getUserId();
        userPicturesService.remove(Wrappers.lambdaQuery(UserPictures.class)
                .eq(UserPictures::getUserId,userId)
                .in(UserPictures::getId, ids));
    }
}
