/**
 * @filename:CustomerAssignServiceImpl 2024-06-03
 * @project trade-admin V1.0 Copyright(c) 2024 wanglang Co. Ltd. All right reserved.
 */
package com.trade.admin.enterprise.customer.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.trade.admin.enterprise.customer.constant.AssignStatusEnum;
import com.trade.admin.enterprise.customer.constant.AssignWayEnum;
import com.trade.admin.enterprise.customer.constant.Constants;
import com.trade.admin.enterprise.customer.domain.CustomerAssign;
import com.trade.admin.enterprise.customer.domain.CustomerAssignRecord;
import com.trade.admin.enterprise.customer.domain.CustomerReferralCode;
import com.trade.admin.enterprise.customer.domain.SearchCustomerAssign;
import com.trade.admin.enterprise.customer.dto.ClaimDto;
import com.trade.admin.enterprise.customer.dto.CustomerTransferVo;
import com.trade.admin.enterprise.customer.mapper.CustomerAssignMapper;
import com.trade.admin.enterprise.customer.service.CustomerAssignRecordService;
import com.trade.admin.enterprise.customer.service.CustomerAssignService;
import com.trade.admin.enterprise.customer.service.CustomerReferralCodeService;
import com.trade.admin.system.domain.SysUserRole;
import com.trade.admin.system.domain.entity.SysRole;
import com.trade.admin.system.domain.entity.SysUser;
import com.trade.admin.system.domain.model.LoginUser;
import com.trade.admin.system.security.utils.SecurityUtils;
import com.trade.admin.system.service.ISysRoleService;
import com.trade.admin.system.service.ISysUserService;
import com.trade.common.constant.HttpStatus;
import com.trade.common.core.page.GridPage;
import com.trade.common.exception.ServiceException;
import com.trade.common.utils.StringUtils;
import com.trade.common.validate.ValidatorGroup;
import com.trade.common.validate.ValidatorUtil;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description:客户分配移交业务实现类
 * @version: V1.0
 * @author: wanglang
 */
@Service
public class CustomerAssignServiceImpl extends ServiceImpl<CustomerAssignMapper, CustomerAssign> implements CustomerAssignService {

    @Resource
    @Lazy
    private CustomerReferralCodeService customerReferralCodeService;
    @Resource
    private CustomerAssignMapper customerAssignMapper;
    @Resource
    private ISysRoleService roleService;
    @Resource
    private ISysUserService sysUserService;
    @Resource
    private CustomerAssignRecordService customerAssignRecordService;

    @Override
    public GridPage<CustomerAssign> findBySearch(SearchCustomerAssign search) {
        Page<CustomerReferralCode> page = PageHelper.startPage(search.getPage(), search.getRows());
        List<CustomerAssign> rows = customerAssignMapper.findBySearch(search);
        return new GridPage<>(search.getPage(), search.getRows(), page.getTotal(), rows);
    }

    @Override
    public CustomerAssign findByCustomerUserId(Long customerUserId) {
        return this.lambdaQuery().eq(CustomerAssign::getCustomerUserId, customerUserId).one();
    }

    @Override
    public List<CustomerAssignRecord> findRecordByCustomerAssignId(Long customerAssignId) {
        CustomerAssignRecord record = new CustomerAssignRecord();
        record.setCustomerAssignId(customerAssignId);
        Wrapper<CustomerAssignRecord> queryWrapper = new QueryWrapper<>(record);
        return customerAssignRecordService.list(queryWrapper);
    }

    @Override
    public Boolean addCustomerAssign(Long customerUserId, String referralCode, String identifierNo) {
        CustomerAssign assign = new CustomerAssign();
        assign.setBdAssignStatus(AssignStatusEnum.WAIT_CLAIM.getCode());
        assign.setRcAssignStatus(AssignStatusEnum.WAIT_CLAIM.getCode());
        if (StringUtils.isNotBlank(referralCode)) {
            // 查询推荐码属于那个用户
            CustomerReferralCode exits = customerReferralCodeService.getByReferralCode(referralCode.trim());
            if (null == exits || !exits.isStatus()) {
                assign.setRemark("推荐码不存在或被禁用");
            } else {
                SysRole role = roleService.selectRoleById(exits.getRoleId());
                if (role != null) {
                    if (Constants.BD.equals(role.getRoleName())) {
                        assign.setBdUserId(exits.getUserId());
                        assign.setBdUserName(exits.getUserName());
                        assign.setBdAssignStatus(AssignStatusEnum.CLAIMED.getCode());
                        assign.setBdTime(LocalDateTime.now());
                        assign.setBdAssignWay(AssignWayEnum.AUTO_ASSIGN.getCode());
                    } else if (Constants.RC.equals(role.getRoleName())) {
                        assign.setRcUserId(exits.getUserId());
                        assign.setRcUserName(exits.getUserName());
                        assign.setRcAssignStatus(AssignStatusEnum.CLAIMED.getCode());
                        assign.setRiskTime(LocalDateTime.now());
                        assign.setRcAssignWay(AssignWayEnum.AUTO_ASSIGN.getCode());
                    }
                }
            }
        }
        assign.setIdentifierNo(identifierNo);
        assign.setCustomerUserId(customerUserId);
        ValidatorUtil.validator(ValidatorGroup.ValidatorType.ADD, assign);
        return customerAssignMapper.insert(assign) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean claim(ClaimDto claimDto) {
        for (Long customerAssignId : claimDto.getCustomerAssignIds()) {
            if (null == customerAssignId) {
                throw new ServiceException("需要被认领的官网客户分配主键ID不能为空！", HttpStatus.BAD_REQUEST);
            }
            CustomerAssign exits = customerAssignMapper.selectById(customerAssignId);
            if (null == exits) {
                throw new ServiceException("需要被认领的客户不存在！", HttpStatus.BAD_REQUEST);
            }
            if (!AssignStatusEnum.WAIT_CLAIM.getCode().equals(exits.getBdAssignStatus())
                    && !AssignStatusEnum.WAIT_CLAIM.getCode().equals(exits.getRcAssignStatus())) {
                throw new ServiceException("该客户已被认领，不能再认领了！", HttpStatus.BAD_REQUEST);
            }
            LoginUser loginUser = SecurityUtils.getLoginUser();
            // 只有BD/RC角色才可以操作认领
            boolean bd = isBd(loginUser.getUserId());
            boolean rc = isRc(loginUser.getUserId());
            if (!bd && !rc) {
                throw new ServiceException("您不是业务经理或风控经理，无法进行认领操作！！", HttpStatus.BAD_REQUEST);
            }
            CustomerAssignRecord record = new CustomerAssignRecord(exits);
            if (bd) {
                if (!AssignStatusEnum.WAIT_CLAIM.getCode().equals(exits.getBdAssignStatus())) {
                    throw new ServiceException("该客户已有业务经理认领，不能再认领了！", HttpStatus.BAD_REQUEST);
                }
                exits.setBdUserName(loginUser.getUsername());
                exits.setBdUserId(loginUser.getUserId());
                exits.setBdTime(LocalDateTime.now());
                exits.setBdAssignWay(AssignWayEnum.MANUAL_CLAIM.getCode());
                exits.setBdAssignStatus(AssignStatusEnum.CLAIMED.getCode());
                record.setBdUserIdNew(loginUser.getUserId());
                record.setBdUserNameNew(loginUser.getUsername());
            } else {
                if (!AssignStatusEnum.WAIT_CLAIM.getCode().equals(exits.getRcAssignStatus())) {
                    throw new ServiceException("该客户已有风控经理认领，不能再认领了！", HttpStatus.BAD_REQUEST);
                }
                exits.setRcUserName(loginUser.getUsername());
                exits.setRcUserId(loginUser.getUserId());
                exits.setRiskTime(LocalDateTime.now());
                exits.setRcAssignWay(AssignWayEnum.MANUAL_CLAIM.getCode());
                exits.setRcAssignStatus(AssignStatusEnum.CLAIMED.getCode());
                record.setRcUserIdNew(loginUser.getUserId());
                record.setRcUserNameNew(loginUser.getUsername());
            }
            exits.setRemark(claimDto.getRemark());
            customerAssignMapper.updateById(exits);
            // 添加操作记录
            record.setOperatorId(loginUser.getUserId());
            record.setOperatorName(loginUser.getUsername());
            record.setOperatorTime(LocalDateTime.now());
            record.setOperatorType(AssignStatusEnum.CLAIMED.getCode());
            record.setRemark(claimDto.getRemark());
            customerAssignRecordService.save(record);
        }
        return true;
    }

    @Override
    public Map<String, Object> getDetailById(List<Long> ids) {
        Map<String, Object> map = new HashMap<String, Object>();
        List<CustomerAssign> assigns = customerAssignMapper.selectBatchIds(ids);
        map.put("customerAssigns", assigns);
        map.put("bd", getBdUsers());
        map.put("rc", getRcUsers());
        return map;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean assignAdjustment(List<CustomerAssign> assigns) {
        for (CustomerAssign assign : assigns) {
            if (null == assign || null == assign.getId()) {
                throw new ServiceException("需要调整的客户分配主键ID不能为空！", HttpStatus.BAD_REQUEST);
            }
            if ((assign.getBdUserId() == null || StringUtils.isEmpty(assign.getBdUserName()))
                    && (assign.getRcUserId() == null || StringUtils.isEmpty(assign.getRcUserName()))) {
                throw new ServiceException("业务经理或风控经理不能为空！", HttpStatus.BAD_REQUEST);
            }
            CustomerAssign exits = customerAssignMapper.selectById(assign.getId());
            if (exits.getBdUserId() == assign.getBdUserId() && exits.getRcUserId() == assign.getRcUserId()) {
                throw new ServiceException("您未修改任何信息，无法提交表单！", HttpStatus.BAD_REQUEST);
            }
            if (assign.getBdUserId() != null) {
                exits.setBdAssignWay(AssignWayEnum.MANUAL_ASSIGN.getCode());
                exits.setBdTime(LocalDateTime.now());
                exits.setBdUserId(assign.getBdUserId());
                exits.setBdUserName(assign.getBdUserName());
                exits.setBdAssignStatus(AssignStatusEnum.ALLOCATED.getCode());
                assign.setBdAssignStatus(AssignStatusEnum.ALLOCATED.getCode());
            }
            if (assign.getRcUserId() != null) {
                exits.setRiskTime(LocalDateTime.now());
                exits.setRcUserId(assign.getRcUserId());
                exits.setRcUserName(assign.getRcUserName());
                exits.setRcAssignWay(AssignWayEnum.MANUAL_ASSIGN.getCode());
                exits.setRcAssignStatus(AssignStatusEnum.ALLOCATED.getCode());
                assign.setRcAssignStatus(AssignStatusEnum.ALLOCATED.getCode());
            }
            exits.setRemark(assign.getRemark());
            customerAssignMapper.updateById(exits);
            // 新增分配操作记录
            LoginUser loginUser = SecurityUtils.getLoginUser();
            CustomerAssignRecord record = new CustomerAssignRecord(exits);
            record.setBdUserIdNew(assign.getBdUserId());
            record.setBdUserNameNew(assign.getBdUserName());
            record.setRcUserIdNew(assign.getBdUserId());
            record.setRcUserNameNew(assign.getRcUserName());
            record.setRemark(assign.getRemark());
            record.setOperatorId(loginUser.getUserId());
            record.setOperatorName(loginUser.getUsername());
            record.setOperatorTime(LocalDateTime.now());
            record.setOperatorType(AssignStatusEnum.ALLOCATED.getCode());
            customerAssignRecordService.save(record);
        }
        return true;
    }

    @Override
    public List<CustomerTransferVo> getCustomerTransferInfo(List<Long> customerAssignIds) {
        List<CustomerTransferVo> transferVos = new ArrayList<>();
        for (Long customerAssignId : customerAssignIds) {
            if (null == customerAssignId) {
                throw new ServiceException("需要移交的客户分配主键ID不能为空！", HttpStatus.BAD_REQUEST);
            }
            CustomerAssign exits = customerAssignMapper.selectById(customerAssignId);
            if (null == exits) {
                throw new ServiceException("未查询到客户分配主键ID的数据！", HttpStatus.BAD_REQUEST);
            }
            CustomerTransferVo transferVo = new CustomerTransferVo();
            transferVo.setBdUserIdSource(exits.getBdUserId());
            transferVo.setRcUserIdSource(exits.getRcUserId());
            transferVo.setBdUserNameSource(exits.getBdUserName());
            transferVo.setRcUserNameSource(exits.getRcUserName());
            transferVo.setCustomerAssignId(customerAssignId);
            transferVo.setBdList(getBdUsers().stream().filter(bdUser -> !bdUser.getUserId().equals(exits.getBdUserId()))
                    .collect(Collectors.toList()));
            transferVo.setRcList(getRcUsers().stream().filter(rcUser -> !rcUser.getUserId().equals(exits.getRcUserId()))
                    .collect(Collectors.toList()));
            transferVos.add(transferVo);
        }
        return transferVos;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean transfer(List<CustomerTransferVo> assigns) {
        for (CustomerTransferVo assign : assigns) {
            if (null == assign || null == assign.getCustomerAssignId()) {
                throw new ServiceException("需要移交的客户分配主键ID不能为空！", HttpStatus.BAD_REQUEST);
            }
            if ((assign.getBdUserIdNew() == null || StringUtils.isEmpty(assign.getBdUserNameNew()))
                    && (assign.getRcUserIdNew() == null || StringUtils.isEmpty(assign.getRcUserNameNew()))) {
                throw new ServiceException("业务经理或风控经理不能为空！", HttpStatus.BAD_REQUEST);
            }
            CustomerAssign exits = customerAssignMapper.selectById(assign.getCustomerAssignId());
            if (null == exits) {
                throw new ServiceException("未查询到客户分配主键ID的数据！", HttpStatus.BAD_REQUEST);
            }
            // 新增分移交操作记录
            LoginUser loginUser = SecurityUtils.getLoginUser();
            CustomerAssignRecord record = new CustomerAssignRecord(exits);
            record.setBdUserIdNew(assign.getBdUserIdNew());
            record.setBdUserNameNew(assign.getBdUserNameNew());
            record.setRcUserIdNew(assign.getRcUserIdNew());
            record.setRcUserNameNew(assign.getRcUserNameNew());
            record.setRemark(assign.getRemark());
            record.setOperatorId(loginUser.getUserId());
            record.setOperatorName(loginUser.getUsername());
            record.setOperatorTime(LocalDateTime.now());
            record.setOperatorType(AssignStatusEnum.TRANSFERED.getCode());
            customerAssignRecordService.save(record);
            exits.setBdUserName(assign.getBdUserNameNew());
            exits.setBdUserId(assign.getBdUserIdNew());
            exits.setRcUserName(assign.getRcUserNameNew());
            exits.setRcUserId(assign.getRcUserIdNew());
            if (assign.getBdUserIdNew() != null) {
                exits.setBdAssignWay(AssignWayEnum.MANUAL_TRANSFER.getCode());
                exits.setBdTime(LocalDateTime.now());
                exits.setBdAssignStatus(AssignStatusEnum.TRANSFERED.getCode());
                exits.setBdUserId(assign.getBdUserIdNew());
                exits.setBdUserName(assign.getBdUserNameNew());
            }
            if (assign.getRcUserIdNew() != null) {
                exits.setRcAssignWay(AssignWayEnum.MANUAL_TRANSFER.getCode());
                exits.setRiskTime(LocalDateTime.now());
                exits.setRcAssignStatus(AssignStatusEnum.TRANSFERED.getCode());
                exits.setRcUserId(assign.getRcUserIdNew());
                exits.setRcUserName(assign.getRcUserNameNew());
            }
            exits.setRemark(assign.getRemark());
            customerAssignMapper.updateById(exits);
        }
        return true;
    }

    @Override
    public boolean update(CustomerAssign assign) {
        return customerAssignMapper.updateById(assign) > 0;
    }

    @Override
    public boolean isOccupiedByUserId(Long userId) {
        if (null == userId) {
            throw new ServiceException("参数错误,用户ID为空！", HttpStatus.BAD_REQUEST);
        }
        return customerAssignMapper.countByUserId(userId) > 1L;
    }

    /**
     * 该用户是否是BD或RC
     * 
     * @param userId 用户id
     * @return true 是 false 否
     */
    private boolean isBdOrRc(Long userId) {
        List<SysRole> sysRoles = roleService.selectByRoleKeys(Arrays.asList(Constants.BD, Constants.RC));
        boolean falg = false;
        if (!CollectionUtils.isEmpty(sysRoles)) {
            for (SysRole sysRole : sysRoles) {
                SysUserRole roleRel = sysUserService.selectByUserRole(userId, sysRole.getRoleId());
                if (null != roleRel) {
                    falg = true;
                    break;
                }
            }
        } else {
            falg = false;
        }
        return falg;
    }

    /**
     * 该用户是否是BD
     *
     * @param userId 用户id
     * @return true 是 false 否
     */
    private boolean isBd(Long userId) {
        SysRole sysRole = roleService.selectByRoleKey(Constants.BD);
        boolean falg = false;
        if (sysRole != null) {
            SysUserRole roleRel = sysUserService.selectByUserRole(userId, sysRole.getRoleId());
            if (null != roleRel) {
                falg = true;
            }
        } else {
            falg = false;
        }
        return falg;
    }

    /**
     * 该用户是否是BD或RC
     *
     * @param userId 用户id
     * @return true 是 false 否
     */
    private boolean isRc(Long userId) {
        SysRole sysRole = roleService.selectByRoleKey(Constants.RC);
        boolean falg = false;
        if (sysRole != null) {
            SysUserRole roleRel = sysUserService.selectByUserRole(userId, sysRole.getRoleId());
            if (null != roleRel) {
                falg = true;
            }
        } else {
            falg = false;
        }
        return falg;
    }

    private List<SysUser> getBdUsers() {
        List<SysUser> bdList = new ArrayList<>();
        // 业务经理角色下的用户
        SysRole bdRole = roleService.selectByRoleKey(Constants.BD);
        List<Long> bd = sysUserService.selectUserIdByRoleId(bdRole.getRoleId());
        if (!CollectionUtils.isEmpty(bd)) {
            for (Long userId : bd) {
                SysUser user = sysUserService.selectUserById(userId);
                if (null != user) {
                    bdList.add(user);
                }
            }
        }
        return bdList;
    }

    private List<SysUser> getRcUsers() {
        List<SysUser> rcList = new ArrayList<>();
        // 风控经理角色下的用户
        SysRole rcRole = roleService.selectByRoleKey(Constants.RC);
        List<Long> rc = sysUserService.selectUserIdByRoleId(rcRole.getRoleId());
        if (!CollectionUtils.isEmpty(rc)) {
            for (Long userId : rc) {
                SysUser user = sysUserService.selectUserById(userId);
                if (null != user) {
                    rcList.add(user);
                }
            }
        }
        return rcList;
    }
}
