package com.zcloud.basic.info.command;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.cola.dto.SingleResponse;
import com.alibaba.cola.exception.BizException;
import com.jjb.saas.config.client.dicttree.facade.ConfDictTreeFacade;
import com.jjb.saas.framework.auth.model.SSOUser;
import com.jjb.saas.framework.auth.utils.AuthContext;
import com.jjb.saas.message.client.message.facede.MessageFacade;
import com.jjb.saas.message.client.message.request.MessageSendCmd;
import com.jjb.saas.message.client.message.request.MessageTargetCmd;
import com.zcloud.basic.info.command.convertor.UserCoConvertor;
import com.zcloud.basic.info.command.query.CorpInfoQueryExe;
import com.zcloud.basic.info.constant.RedisConstant;
import com.zcloud.basic.info.domain.enums.UserEmploymentFlagEnum;
import com.zcloud.basic.info.domain.enums.UserFlowFlagEnum;
import com.zcloud.basic.info.domain.gateway.*;
import com.zcloud.basic.info.domain.model.*;
import com.zcloud.basic.info.dto.*;
import com.zcloud.basic.info.persistence.dataobject.*;
import com.zcloud.basic.info.persistence.repository.*;
import com.zcloud.gbscommon.utils.DateUtil;
import com.zcloud.gbscommon.utils.UuidUtil;
import com.zcloud.gbscommon.utils.ZcloudRedisUtil;
import lombok.AllArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
* web-app
* @Author zhangyue
* @Date 2025-11-04 14:07:21
*/
@Component
@AllArgsConstructor
public class UserAddExe {
    private final UserGateway userGateway;
    private UserCoConvertor userCoConvertor;
    private final UserEmploymentLogGateway userEmploymentLogGateway;
    private final CorpInfoRepository corpInfoRepository;
    private final DepartmentRepository departmentRepository;
    private final PostRepository postRepository;
    private final UserRepository userRepository;
    @DubboReference
    private ConfDictTreeFacade confDictTreeFacade;
    @DubboReference
    private final MessageFacade messageFacade;
    private final CorpInfoQueryExe corpInfoQueryExe;
    private final UserCorpGateway userCorpGateway;
    private final UserCorpRepository userCorpRepository;
    private final UserChangeRecordGateway userChangeRecordGateway;
    private final UserCorpRecordGateway userCorpRecordGateway;
    private ZcloudRedisUtil zcloudRedisUtil;


    @Transactional(rollbackFor = Exception.class)
    public boolean execute(UserAddCmd cmd) {
        Boolean b = corpInfoQueryExe.verifyCorpInfo();
        if (!b) {
            throw new BizException("请先完善企业信息");
        }
        SSOUser ssoUser = AuthContext.getCurrentUser();
        Long tenantId = ssoUser.getTenantId();
        UserE userE = new UserE();
        BeanUtils.copyProperties(cmd, userE);
        userE.initAdd(tenantId, userE);
        CorpInfoDO corpInfoDO = corpInfoRepository.getById(userE.getCorpinfoId());
        String corpName = null;
        UserEmploymentLogE userEmploymentLogE = new UserEmploymentLogE();
        BeanUtils.copyProperties(userE, userEmploymentLogE);
        boolean res = false;
        if(ObjectUtils.isEmpty(userE.getRoleId())){
            Long roleId = userRepository.getDefaultRoleId();
            if (roleId == null){
                throw new BizException("未创建默认通用角色，请联系管理员");
            }
            userE.setRoleId(roleId);
        }
        try {

            res = userGateway.add(userE);
            if(corpInfoDO != null && !ObjectUtils.isEmpty(corpInfoDO.getCorpName())){
                corpName = corpInfoDO.getCorpName();
            }
            userEmploymentLogE.initAdd(userEmploymentLogE, corpName, userE.getId());
            userEmploymentLogGateway.add(userEmploymentLogE);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if (!res) {
            throw new BizException("保存失败");
        }
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean executeRegister(AppUserRegisterCmd cmd) {

        UserE userE = new UserE();
        userE.checkPassword(cmd.getNewPassword(), cmd.getConfirmPassword());

        // 获取redis验证码
        Object phoneCodeObj = zcloudRedisUtil.get(RedisConstant.PHONE_CODE_KEY + cmd.getPhone());
        if(phoneCodeObj == null || !phoneCodeObj.toString().equals(cmd.getPhoneCode())){
            throw new BizException("验证码已过期或错误");
        }
        zcloudRedisUtil.del(RedisConstant.PHONE_CODE_KEY + cmd.getPhone());

        CorpInfoDO corpInfoDO = corpInfoRepository.getCorpInfoByCorpName("相关方通用租户");
        if(corpInfoDO == null){
            throw new BizException("未创建相关方通用租户");
        }
        BeanUtils.copyProperties(cmd, userE);
        userE.setPassword(cmd.getNewPassword());
        userE.setCorpinfoId(corpInfoDO.getId());
        userE.setDepartmentId(corpInfoDO.getId());
        userGateway.register(userE);

        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean executePerfectUserInfo(AppUserInfoCmd cmd) {

        UserE userE = new UserE();
        BeanUtils.copyProperties(cmd, userE);
        // 3-相关方
        userE.setUserType(3);
        if(UserFlowFlagEnum.FIXED.getCode().equals(cmd.getFlowFlag())){
            userE.setEmploymentFlag(UserEmploymentFlagEnum.NOT_ON.getCode());
        }
        userGateway.update(userE);

        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean executeOnboarding(AppUserOnboardingCmd cmd) {

        // todo 底座将人转移到另一个租户

        //// 如果是流动人员, 判断user_corp表是否有未离职的数据, 如果有则不能入职(1-离职)
        List<Integer> statusList = Arrays.asList(UserEmploymentFlagEnum.RESIGNATION.getCode(), UserEmploymentFlagEnum.NOT_ON.getCode());
        List<UserCorpDO> userCorpDOS = userCorpRepository.listByUserIdAndCorpIdAndNoStatus(cmd.getId(), cmd.getCorpinfoId(), statusList);
        if(CollUtil.isNotEmpty(userCorpDOS)){
            throw new BizException("该用户在当前企业存在未离职信息，无法入职");
        }
        /**
         * 如果是离职的话, 则将离职改为入职
         */


        // 把user表和user_corp表相关企业,部门,岗位数据补充完整
        UserE userE = new UserE();
        BeanUtils.copyProperties(cmd, userE);


        // 查询用户信息, 获取是否流动人员
        UserDO userDO = userRepository.getById(cmd.getId());
        if(userDO == null){
            throw new BizException("用户不存在");
        }
        if(UserFlowFlagEnum.FLOW.getCode().equals(userDO.getFlowFlag())){
            List<UserCorpDO> userCorpList = userCorpRepository.listByUserIdAndCorpIdAndStatus(cmd.getId(), cmd.getCorpinfoId(), statusList);
            if(CollUtil.isNotEmpty(userCorpList)){
                if(userCorpList.size() > 1){
                    throw new BizException("用户在当前企业存在多条离职数据，请联系管理员。");
                }
                UserCorpDO userCorpDO = userCorpList.get(0);
                userCorpDO.setEmploymentFlag(UserEmploymentFlagEnum.ENTRY_AUDIT.getCode());
                UserCorpE userCorpE = new UserCorpE();
                BeanUtils.copyProperties(userCorpDO, userCorpE);
                userCorpGateway.update(userCorpE);
            }else {
                // 插入user_corp表
                UserCorpE userCorpE = new UserCorpE();
                userCorpE.setUserId(userE.getId());
                userCorpE.setCorpinfoId(userE.getCorpinfoId());
                userCorpE.setDepartmentId(userE.getDepartmentId());
                userCorpE.setPostName(userE.getPostName());
                userCorpE.setRoleId(userE.getRoleId());
                userCorpE.setDepartmentLeaderFlag(0);
                userCorpE.setSort(9999);
                userCorpE.setEmploymentFlag(UserEmploymentFlagEnum.ENTRY_AUDIT.getCode());
                userCorpGateway.add(userCorpE);
            }
        }else{
            userE.setEmploymentFlag(UserEmploymentFlagEnum.ENTRY_AUDIT.getCode());
            // 扫码入职时, 固定人员user表企业id变为入职的企业
            userE.setCorpinfoId(cmd.getCorpinfoId());
        }

        userGateway.update(userE);
        // 插入user_corp_record表
        UserCorpRecordE userCorpRecordE = new UserCorpRecordE();
        userCorpRecordE.initAddFromApp(userE, cmd.getCorpinfoName(), cmd.getDepartmentName());
        userCorpRecordGateway.add(userCorpRecordE);

        // 插入user_change_record表
        UserChangeRecordE userChangeRecordE = new UserChangeRecordE();
        userChangeRecordE.initUserAddFromApp(userE, cmd.getCorpinfoName(), cmd.getDepartmentName());
        userChangeRecordGateway.add(userChangeRecordE);

        return true;
    }


    @Transactional(rollbackFor = Exception.class)
    public boolean executeSendPhoneCode(UserVerifyPhoneCmd cmd) {
        // 生成6位验证码
        String phoneCode = RandomUtil.randomNumbers(6);
        Object phoneCodeCountObj = zcloudRedisUtil.get(RedisConstant.PHONE_CODE_COUNT + DateUtil.getDays() + ":" + cmd.getPhone());
        if(phoneCodeCountObj != null){
            Integer phoneCodeCount = (Integer) phoneCodeCountObj;
            if(phoneCodeCount >= 20){
                throw new BizException("今天验证码已发送次数已超过20次");
            }
        }

        boolean sendFlag = sendMessage(cmd.getPhone(), phoneCode);
        if(sendFlag){
            // 发送成功
            // 放入到redis里
            zcloudRedisUtil.set(RedisConstant.PHONE_CODE_KEY + cmd.getPhone(), phoneCode, 60 * 15);
            // 设置新的验证码发送次数
            zcloudRedisUtil.set(RedisConstant.PHONE_CODE_COUNT + DateUtil.getDays() + ":" + cmd.getPhone(),
                    phoneCodeCountObj == null ? 1 : (Integer)phoneCodeCountObj + 1,
                    60 * 60 * 24);
            return true;
        }

        return false;
    }

    // 组装发送短信
    public boolean sendMessage(String phone, String phoneCode){
        MessageSendCmd messageSendCmd = new MessageSendCmd();
        messageSendCmd.setBusinessId(UuidUtil.get32UUID());
        MessageTargetCmd messageTargetCmd = new MessageTargetCmd();
        messageTargetCmd.setMobile(phone);
        messageSendCmd.setTargetCmd(messageTargetCmd);
        messageSendCmd.setSourceCode("MS000070");
        Map<String, Object> sendParams = new HashMap<String, Object>();
        sendParams.put("code", phoneCode);
        messageSendCmd.setParams(sendParams);
        SingleResponse<Boolean> d = messageFacade.send(messageSendCmd);
        return d == null ? false : d.getData();
    }



    @Transactional(rollbackFor = Exception.class)
    public boolean executeXgf(UserXgfAddCmd cmd) {
        SSOUser ssoUser = AuthContext.getCurrentUser();
        Long tenantId = ssoUser.getTenantId();
        UserE userE = new UserE();
        BeanUtils.copyProperties(cmd, userE);
        userE.initAdd(tenantId, userE);
        CorpInfoDO corpInfoDO = corpInfoRepository.getById(userE.getCorpinfoId());
        boolean res = false;
        try {
            res = userGateway.addXgf(userE);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if (!res) {
            throw new BizException("保存失败");
        }

        if(UserFlowFlagEnum.FLOW.getCode().equals(cmd.getFlowFlag())){
            //流动人员
            UserCorpE userCorpE = new UserCorpE();
//            BeanUtils.copyProperties(userE, userCorpE);
//            userCorpE.setCorpinfoId(tenantId);
            userCorpE.initAdd(tenantId, userE);
            userCorpGateway.add(userCorpE);
        }
        //页面相关保存user_corp
        /**
         * 非流动人员用户只能在一个企业，
         * 同步gbs，流动人员企业固定
         */
        DepartmentDO departmentDO = departmentRepository.getById(userE.getDepartmentId());

        //增加用户入职企业
        UserCorpRecordE userCorpRecordE = new UserCorpRecordE();
        BeanUtils.copyProperties(cmd, userCorpRecordE);
        userCorpRecordE.initAdd(userE,corpInfoDO.getCorpName(),departmentDO.getName());
        userCorpRecordGateway.add(userCorpRecordE);

        // 增加用户变更记录
        UserChangeRecordE userChangeRecordE = new UserChangeRecordE();
        BeanUtils.copyProperties(cmd, userChangeRecordE);
        userChangeRecordE.initUserAdd( userE,corpInfoDO.getCorpName(),departmentDO.getName());
        userChangeRecordGateway.add(userChangeRecordE);


        return true;
    }


    public void addCorpInfo(CorpInfoAddCmd cmd) {
    }
}

