package com.fdkankan.platform.user.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fdkankan.common.constant.*;
import com.fdkankan.common.exception.BusinessException;
import com.fdkankan.common.response.ResultData;
import com.fdkankan.common.user.SSOLoginHelper;
import com.fdkankan.common.user.SSOUser;
import com.fdkankan.common.util.Base64Converter;
import com.fdkankan.common.util.FileUtils;
import com.fdkankan.common.util.SsoUtil;
import com.fdkankan.common.validation.Variable;
import com.fdkankan.fyun.qiniu.QiniuUpload;
import com.fdkankan.platform.common.CameraTypeEnum;
import com.fdkankan.platform.goods.entity.Camera;
import com.fdkankan.platform.goods.entity.CameraDetail;
import com.fdkankan.platform.goods.entity.CameraDetailNumEntity;
import com.fdkankan.platform.goods.service.ICameraDetailService;
import com.fdkankan.platform.goods.service.ICameraService;
import com.fdkankan.platform.user.entity.ReceiverInfo;
import com.fdkankan.platform.user.entity.User;
import com.fdkankan.platform.user.entity.UserIncrement;
import com.fdkankan.platform.user.mapper.IUserMapper;
import com.fdkankan.platform.user.request.RequestCamera;
import com.fdkankan.platform.user.request.RequestUser;
import com.fdkankan.platform.user.service.IReceiverInfoService;
import com.fdkankan.platform.user.service.IUserIncrementService;
import com.fdkankan.platform.user.service.IUserService;
import com.fdkankan.platform.user.service.sso.RegisterService;
import com.fdkankan.platform.user.vo.ReceiverInfoVo;
import com.fdkankan.platform.user.vo.ResponseCamera;
import com.fdkankan.platform.user.vo.ResponseUser;
import com.fdkankan.platform.user.vo.SSOUserVo;
import com.fdkankan.redis.util.RedisUtil;
import com.fdkankan.scene.api.feign.SceneUserSceneClient;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户信息表 服务实现类
 * </p>
 *
 * @author
 * @since 2021-12-24
 */
@Service
public class UserServiceImpl extends ServiceImpl<IUserMapper, User> implements IUserService {

    @Value("${admin.register.validCode}")
    private  String registerValidCode;
    @Autowired
    private RegisterService registerService;
    @Autowired
    private SSOLoginHelper ssoLoginHelper;
    @Autowired
    private IUserIncrementService userIncrementService;
    @Autowired
    private IReceiverInfoService receiverInfoService;
    @Autowired
    private ICameraService cameraService;
    @Autowired
    private ICameraDetailService cameraDetailService;
    @Autowired
    private SceneUserSceneClient sceneUserSceneClient;
    @Autowired
    RedisUtil redisUtil;
    @Resource
    private IUserMapper userMapper;

    @Override
    public String register(RequestUser user) {
        if (!user.getMsgAuthCode().equals(registerValidCode)) {
            //对前端传的密码解密
            String password = Base64Converter.decode(Base64Converter.subText(user.getPassword()));
            user.setPassword(password);

            String confirPwd = Base64Converter.decode(Base64Converter.subText(user.getConfirmPwd()));
            user.setConfirmPwd(confirPwd);
        }else{
            user.setCountry("86");
        }
        registerService.register(user);

        return ServerCode.SUCCESS.message();
    }

    @Override
    public String changePassword(RequestUser param) {
        return registerService.changePassword(param);
    }

    @Override
    public User getUserByUserName(String userName){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(User::getTbStatus,TbStatus.VALID.code());
        queryWrapper.lambda().eq(User::getUserName,userName);
        List<User> list = this.list(queryWrapper);
        if(list == null || list.size()<=0){
            return null;
        }
        return list.get(0);
    }

    @Override
    public SSOUser getSsoUserByUserName(User userEntity, String phoneNum) {
        SSOUser user = null;
        if (userEntity != null){
            user = new SSOUser();
            user.setId(userEntity.getId());
            user.setUserName(userEntity.getUserName());
            user.setEmail(userEntity.getEmail());
            user.setPassword(userEntity.getPassword());
        }
        return user;
    }

    @Override
    public SSOUserVo getUserInfoByUser(Integer cameraType, User dbUser, String token) {
        ResponseUser vo = new ResponseUser();
        BeanUtils.copyProperties(dbUser,vo);
        Integer cameraCount = cameraDetailService.getListByUserId(dbUser.getId(),Long.valueOf(cameraType)).size();
        Long sceneCount = (Long) sceneUserSceneClient.getSceneCount(null,dbUser.getId(),cameraType).getData();
        vo.setSceneCount(sceneCount.intValue());
        vo.setCameraCount(cameraCount);
        SSOUserVo ssoUserVo = new SSOUserVo();
        ssoUserVo.setToken(token);
        ssoUserVo.setResponseUser(vo);
        return ssoUserVo;
    }

    @Override
    public ResponseUser getUserInfoByParam(RequestUser param,String token) {
        User dbUser = this.getDbUserByToken(token);
        SSOUserVo ssoUserVo = this.getUserInfoByUser(param.getCameraType(), dbUser, token);
        ResponseUser vo = ssoUserVo.getResponseUser();
        Integer incrementCount = userIncrementService.getCountByUserId(dbUser.getId(),0);
        Integer incrementBindCount = userIncrementService.getCountBindByUserId(dbUser.getId());
        vo.setIncrementNum(incrementCount);
        vo.setIncrementBindNum(incrementBindCount);
        return vo;
    }
    @Override
    public ResponseUser getUserInfoBySsoUserVo(SSOUserVo ssoUserVo) {
        ResponseUser vo = ssoUserVo.getResponseUser();
        Integer incrementCount = userIncrementService.getCountByUserId(vo.getId(),0);
        Integer incrementBindCount = userIncrementService.getCountBindByUserId(vo.getId());
        vo.setIncrementNum(incrementCount);
        vo.setIncrementBindNum(incrementBindCount);
        return vo;
    }

    @Override
    public String uploadHead(RequestUser param,String token) throws Exception{
        if (StringUtils.isEmpty(param.getImgdata())){
            throw new BusinessException(ErrorCode.MISSING_REQUIRED_PARAMETERS);
        }
        User dbUser = this.getDbUserByToken(token);

        StringBuilder sb = new StringBuilder().append("head")
                .append(File.separator).append(dbUser.getUserName()).append(File.separator)
                .append("head").append("_").append(new Date().getTime()).append(".png");
        StringBuilder qiniuPath = new StringBuilder().append("head")
                .append("/").append(dbUser.getUserName()).append("/")
                .append("head").append("_").append(new Date().getTime()).append(".png");
        FileUtils.uploadImg(ConstantFilePath.USER_IMAGES_PATH + sb.toString(), param.getImgdata());
        dbUser.setHead(ConstantUrl.PREFIX_QINIU + qiniuPath.toString()+"?m="+System.currentTimeMillis());
        this.updateById(dbUser);
        //上传头像到七牛云
        try {
            QiniuUpload.delete(qiniuPath.toString());
        } catch (Exception e) { }
        if (QiniuUpload.setFileToBucket(qiniuPath.toString(), ConstantFilePath.USER_IMAGES_PATH + sb.toString())) {
            FileUtils.deleteFile(ConstantFilePath.USER_IMAGES_PATH + sb.toString());
        }
        QiniuUpload.refresh(dbUser.getHead());
        return dbUser.getHead();
    }
    private User getDbUserByToken(String token){
        SSOUser ssoUser = ssoLoginHelper.loginCheck(token);
        if(ssoUser == null){
            throw new BusinessException(ErrorCode.USER_NOT_LOGIN);
        }
        User dbUser = this.getUserByUserName(ssoUser.getUserName());
        if(dbUser == null){
            throw new BusinessException(ErrorCode.USER_NOT_LOGIN);
        }
        return dbUser;
    }
    @Override
    public SSOUser getSSOUserByToken(String token){
        SSOUser ssoUser = ssoLoginHelper.loginCheck(token);
        if(ssoUser == null){
            throw new BusinessException(ErrorCode.USER_NOT_LOGIN);
        }
        return ssoUser;
    }

    @Override
    public String insertAddress(RequestUser user,String token) {
        if (StringUtils.isEmpty(user.getShipAddress()) || StringUtils.isEmpty(user.getShipAreaPath())
                || StringUtils.isEmpty(user.getProvince()) || StringUtils.isEmpty(user.getCity())){
            throw new BusinessException(ErrorCode.MISSING_REQUIRED_PARAMETERS);
        }
        SSOUser ssoUser = getSSOUserByToken(token);
        return receiverInfoService.saveByParam(user,ssoUser.getId());
    }

    @Override
    public String updateDefaultAddress(RequestUser user, String token) {
        if (user.getId() == null || StringUtils.isEmpty(user.getShipAddress()) || StringUtils.isEmpty(user.getShipAreaPath())
                || StringUtils.isEmpty(user.getProvince()) || StringUtils.isEmpty(user.getCity())){
            throw new BusinessException(ErrorCode.MISSING_REQUIRED_PARAMETERS);
        }
        SSOUser ssoUser = getSSOUserByToken(token);
        return receiverInfoService.updateDefaultAddress(user,ssoUser.getId());
    }

    @Override
    public ReceiverInfoVo getUserDefaultReceiver(String token) {
        SSOUser ssoUser = getSSOUserByToken(token);
        ReceiverInfo receiverInfoEntity = receiverInfoService.getDefaultByUserId(ssoUser.getId());
        ReceiverInfoVo responseReceiverInfo = new ReceiverInfoVo();
        if(receiverInfoEntity!=null){
            BeanUtils.copyProperties(receiverInfoEntity,responseReceiverInfo);
        }
        return responseReceiverInfo;
    }

    @Override
    public String removeAddress(Long paramId) {
        if (paramId == null ){
            throw new BusinessException(ErrorCode.MISSING_REQUIRED_PARAMETERS);
        }
        if(!receiverInfoService.removeById(paramId)){
            throw new BusinessException(ErrorCode.ERROR_MSG);
        }
        return ServerCode.SUCCESS.message();
    }

    @Override
    public List<ReceiverInfoVo> getReceiverList(String token) {
        SSOUser ssoUser = getSSOUserByToken(token);
        List<ReceiverInfo> list = receiverInfoService.getListByUserId(ssoUser.getId());
        List<ReceiverInfoVo> voList = list.parallelStream().map(receiverInfo -> {
            ReceiverInfoVo receiverInfoVo = new ReceiverInfoVo();
            BeanUtils.copyProperties(receiverInfo, receiverInfoVo);
            return receiverInfoVo;
        }).collect(Collectors.toList());
        return voList;
    }

    @Override
    public String updateEmail(RequestUser param, String token) {
        if (StringUtils.isEmpty(param.getEmail())){
            throw new BusinessException(ErrorCode.MISSING_REQUIRED_PARAMETERS);
        }
        if(param.getEmail() != null && !param.getEmail().matches(ConstantRegex.EMAIL_REGEX)){
            throw new BusinessException(ErrorCode.EMAIL_ERROR);
        }
        User user = this.getByEmail(param.getEmail());
        SSOUser ssoUser = this.getSSOUserByToken(token);
        if(user!=null && !user.getId().equals(ssoUser.getId())){
            throw new BusinessException(ErrorCode.EMAIL_EXIST);
        }
        User dbUser = this.getById(ssoUser.getId());
        dbUser.setEmail(param.getEmail());
        if(!this.updateById(dbUser)){
            throw new BusinessException(ErrorCode.ERROR_MSG);
        }
        return ServerCode.SUCCESS.message();
    }

    @Override
    public String updateNickName(RequestUser param, String token) {
        if (StringUtils.isEmpty(param.getNickName())){
            throw new BusinessException(ErrorCode.MISSING_REQUIRED_PARAMETERS);
        }
        //检验昵称敏感词
        Set<String> set = Variable.sensitiveWord.getSensitiveWord(param.getNickName(), 1);
        if (set != null && set.size() > 0){
            throw new BusinessException(ErrorCode.NICKNAME_ERROR);
        }
        SSOUser ssoUser = this.getSSOUserByToken(token);
        User dbUser = this.getById(ssoUser.getId());
        dbUser.setNickName(param.getNickName());
        if(!this.updateById(dbUser)){
            throw new BusinessException(ErrorCode.ERROR_MSG);
        }
        return ServerCode.SUCCESS.message();
    }

    @Override
    public String updateUserDetail(RequestUser param, String token) {
        if (param.getNickName() != null){
            //检验昵称敏感词
            Set<String> set = Variable.sensitiveWord.getSensitiveWord(param.getNickName(), 1);
            if (set != null && set.size() > 0){
                throw new BusinessException(ErrorCode.NICKNAME_ERROR);
            }
        }

        if(param.getEmail() != null && !param.getEmail().matches(ConstantRegex.EMAIL_REGEX)){
            throw new BusinessException(ErrorCode.EMAIL_ERROR);
        }
        SSOUser ssoUser = this.getSSOUserByToken(token);
        User emailUser = getByEmail(param.getEmail());
        if(emailUser != null && emailUser.getId().longValue() != ssoUser.getId().longValue()){
            throw new BusinessException(ErrorCode.EMAIL_EXIST);
        }

        User dbUser = this.getById(ssoUser.getId());
        dbUser.setNickName(param.getNickName());
        dbUser.setEmail(param.getEmail());
        dbUser.setIsNotice(param.getIsNotice());
        if(!this.updateById(dbUser)){
            throw new BusinessException(ErrorCode.ERROR_MSG);
        }
        return ServerCode.SUCCESS.message();
    }

    private User getByEmail(String email){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(User ::getTbStatus,TbStatus.VALID.code());
        queryWrapper.lambda().eq(User ::getEmail,email);
        List<User> list = this.list(queryWrapper);
        if(list == null || list.size()<=0){
            return null;
        }
        return list.get(0);
    }

    @Override
    public Page<ResponseCamera> getCameraPage(RequestCamera param, String token)  throws Exception{
        SSOUser ssoUser = this.getSSOUserByToken(token);
        return cameraService.getPageByUser(param,ssoUser.getId());
    }

    @Override
    public List<CameraDetailNumEntity> getCameraTypeNum(Integer type, String token) {
        SSOUser ssoUser = this.getSSOUserByToken(token);
        return cameraDetailService.getTypeNumByUser(type,ssoUser.getId());
    }

    @Override
    public ResponseCamera getCameraDetailByChildName(RequestCamera param, String token) {
        SSOUser ssoUser = this.getSSOUserByToken(token);
        return cameraDetailService.getByChildName(ssoUser.getId(),param);
    }

    @Override
    public HashMap<String, Object> getCameraDetailDeadline(RequestCamera param, String token) {
        SSOUser ssoUser = this.getSSOUserByToken(token);
        return cameraDetailService.getCameraDetailDeadline(ssoUser.getId(),param);
    }

    @Override
    public Integer getCameraDetailNumber(String token) {
        SSOUser ssoUser = this.getSSOUserByToken(token);
        return cameraDetailService.getDeadLineNumber(ssoUser.getId());
    }

    @Override
    public List<ResponseCamera> getCameraByUser(RequestCamera param, String token) {
        SSOUser ssoUser = this.getSSOUserByToken(token);
        return cameraService.getByUser(ssoUser.getId(),param.getCameraType());
    }

    @Override
    public String unbindCamera(Long cameraId, String ids)throws Exception {
        if(StringUtils.isEmpty(ids) && cameraId !=null){
            ids = String.valueOf(cameraId);
        }
        String[] cameraIds = ids.split(",");
        for (String id : cameraIds) {
            cameraDetailService.unbind(Long.valueOf(id));
            CameraDetail cameraDetailEntity = cameraDetailService.getByCameraId(Long.valueOf(id));
            //相机解除绑定，一并解除权益绑定
            UserIncrement userIncrementEntity = userIncrementService.getByCameraId(Long.valueOf(id));
            if(userIncrementEntity != null){
                userIncrementService.unbindCamera(cameraDetailEntity.getUserId(), userIncrementEntity.getId(), true,cameraDetailEntity,userIncrementEntity);
            }
            sceneUserSceneClient.updateUserIdByCameraId(null,Long.valueOf(id));
            RequestCamera camera = new RequestCamera();
            camera.setCameraId(Long.valueOf(id));
            deleteCooperationUser(camera,cameraDetailEntity);
        }
        return ServerCode.SUCCESS.message();
    }

    @Override
    public String deleteCooperationUser(RequestCamera camera,CameraDetail cameraDetailEntity )throws Exception{
        if(camera.getCameraId() == null){
            throw new BusinessException(ErrorCode.MISSING_REQUIRED_PARAMETERS);
        }
        if(cameraDetailEntity == null){
            cameraDetailEntity = cameraDetailService.getByCameraId(camera.getCameraId());
            if(cameraDetailEntity == null){
                throw new BusinessException(CameraConstant.FAILURE_6003);
            }
        }
        String snCode = null;
        String cooperationUserName = null;
        if(cameraDetailEntity.getCameraType() == CameraTypeEnum.LASER_TURN.getType()){
            Camera cameraEntity = cameraService.getById(camera.getCameraId());
            snCode = cameraEntity.getSnCode();
            cooperationUserName  =camera.getUserName();
        }
        cameraDetailEntity.setCooperationUser(null);
        cameraDetailService.updateById(cameraDetailEntity);

        //删除相机和场景资源的关联关系
        sceneUserSceneClient.disableCooperation(camera.getCameraId(),snCode,cooperationUserName);

        return ServerCode.SUCCESS.message();
    }

    @Override
    public String saveCooperationUser(RequestCamera camera, String token) throws Exception {
        SSOUser ssoUser = getSSOUserByToken(token);
        if(StringUtils.isEmpty(camera.getUserName()) || (camera.getCameraId() == null &&
                StringUtils.isEmpty(camera.getIds()) ) || StringUtils.isEmpty(camera.getResourceIds())){
            throw new BusinessException(ErrorCode.MISSING_REQUIRED_PARAMETERS);
        }
        User userEntity = this.getUserByUserName(camera.getUserName());
        if(userEntity == null){
            throw new BusinessException(ErrorCode.USER_NOT_EXIST);
        }

        if(ssoUser.getId().longValue() == userEntity.getId().longValue()){
            throw new BusinessException(ErrorCode.CAMERA_NOT_OWN);
        }
        if(StringUtils.isEmpty(camera.getIds()) && camera.getCameraId() !=null){
            camera.setIds( String.valueOf(camera.getCameraId()));
        }
        RequestCamera deleteCamera = new RequestCamera();
        String[] cameraIds = camera.getIds().split(",");
        for (String cameraId : cameraIds) {
            //删除旧的资源后再添加
            deleteCamera.setCameraId(Long.valueOf(cameraId));
            deleteCooperationUser(deleteCamera,null);

            CameraDetail cameraDetailEntity = cameraDetailService.getByCameraId(Long.valueOf(cameraId));
            cameraDetailEntity.setCooperationUser(userEntity.getId());
            cameraDetailService.updateById(cameraDetailEntity);
            //保存相机和场景资源的关联关系
            String snCode = null;
            String cooperationUserName = null;
            if(cameraDetailEntity.getCameraType() == CameraTypeEnum.LASER_TURN.getType()){
                Camera cameraEntity = cameraService.getById(Long.valueOf(cameraId));
                snCode = cameraEntity.getSnCode();
                cooperationUserName = camera.getUserName();
            }
            sceneUserSceneClient.saveCooperation(Long.valueOf(cameraId),camera.getResourceIds(),userEntity.getId(),snCode,cooperationUserName);

        }
        return ServerCode.SUCCESS.message();
    }

    @Override
    public ResultData sceneResourceByCameraId(RequestCamera camera) {
        if(camera.getCameraId() == null){
            throw new BusinessException(ErrorCode.MISSING_REQUIRED_PARAMETERS);
        }
        return sceneUserSceneClient.getSceneResourceByCameraId(camera.getCameraId());
    }

    @Override
    public SSOUser getSSOUserByUserId(Long userId) {
        User user = this.getById(userId);
        if(user == null || 1 == user.getTbStatus()){
            throw new BusinessException(ErrorCode.USER_NOT_EXIST);
        }
        return this.getSsoUserByUserName(user,user.getUserName());
    }

    @Override
    public SSOUser getByNickName(String nickName) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(User ::getTbStatus,TbStatus.VALID.code());
        queryWrapper.lambda().eq(User ::getNickName,nickName);
        List<User> list = this.list(queryWrapper);
        if(list == null || list.size()<=0){
            return null;
        }
        User user = list.get(0);
        return  this.getSsoUserByUserName(user,user.getUserName());
    }

    @Override
    public User getUserByUserId(Long userId) {
        String key = SsoUtil.PREFIX_CACHE_USERINFO + userId;
        String nickName = redisUtil.get(key);
        if(StrUtil.isNotEmpty(nickName)){
            return JSONObject.parseObject(nickName,User.class);
        }
        User user = this.getOne(
                new LambdaQueryWrapper<User>()
                .select(User::getNickName)
                .eq(User::getTbStatus, TbStatus.VALID.code())
                .eq(User::getId, userId));
        if(Objects.isNull(user)){
            return null;
        }
        redisUtil.set(key, JSONObject.toJSONString(user));
        return user;
    }

    @Override
    public Page<ResponseUser> getPageByParam(RequestUser param) {
        Page<ResponseUser> pageVo = new Page<>(param.getPageNum(), param.getPageSize());
        param.setOrderBy("u.register_time desc");
        return userMapper.getListByParam( pageVo,param);
    }

    @Override
    public String updateStatus(Long userId, int status) {
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(User::getStatus,status)
                .eq(User::getId,userId);
        if(!this.update(updateWrapper)){
            throw new BusinessException(ErrorCode.ERROR_MSG);
        }
        return ServerCode.SUCCESS.message();
    }

    @Override
    public List<User> getUserLikeUserName(String searchKey) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getTbStatus,TbStatus.VALID.code())
                .like(User::getUserName,searchKey);
        return this.list(queryWrapper);
    }

    @Override
    public List<ResponseCamera> findNewAll(Long userId, RequestCamera param) throws Exception {

        if(StrUtil.isEmpty(param.getChildName())){
            return null;
        }

        List<Camera> cameraList = cameraService.getCameraLikeSnCode("%" + param.getChildName() + "%");

        List<ResponseCamera> result = new ArrayList<>();
        ResponseCamera responseCamera = null;

        List<CameraDetail> cameraDetailList = cameraDetailService.list(
            new LambdaQueryWrapper<CameraDetail>().eq(CameraDetail::getUserId, userId)
                .ge(CameraDetail::getCameraType, 1));

        if(CollUtil.isEmpty(cameraList) || CollUtil.isEmpty(cameraDetailList)){
            return null;
        }

        for (Camera camera : cameraList) {
            for (CameraDetail detail : cameraDetailList) {
                if(detail.getCameraId().longValue() == camera.getId()){
                    responseCamera = new ResponseCamera();
                    BeanUtils.copyProperties(camera, responseCamera);

                    result.add(responseCamera);
                    break;
                }
            }
        }

        return result;
    }

    @Override
    public ResultData updateDownloadNum(long userId, int downLoadNum) {
        this.update(new LambdaUpdateWrapper<User>()
            .setSql("download_num = download_num + " + downLoadNum)
            .eq(User::getId, userId));
        return ResultData.ok();
    }
}


