package cn.iocoder.yudao.module.custom.service.impl;

import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.module.custom.entity.CustomerCar;
import cn.iocoder.yudao.module.custom.entity.CustomerItem;
import cn.iocoder.yudao.module.custom.entity.CustomerMain;
import cn.iocoder.yudao.module.custom.mapper.CustomerCarMapper;
import cn.iocoder.yudao.module.custom.mapper.CustomerMainMapper;
import cn.iocoder.yudao.module.custom.service.CustomerCarService;
import cn.iocoder.yudao.module.custom.service.CustomerItemService;
import cn.iocoder.yudao.module.custom.service.CustomerMainService;
import cn.iocoder.yudao.module.custom.vo.*;
import cn.iocoder.yudao.module.label.entity.BusiLabel;
import cn.iocoder.yudao.module.label.service.BusiLabelService;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO;
import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import cn.iocoder.yudao.module.system.api.user.dto.UserDTO;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.*;

import static cn.iocoder.yudao.common.BaseConstants.*;
import static cn.iocoder.yudao.common.DictBaseConstants.DICT_CUS_TYPE;
import static cn.iocoder.yudao.framework.common.config.CommonStr.USER_TYPE_CUS;

/**
 * 客户管理 Service 实现类
 *
 * @author pqz
 */
@Service
@Validated
public class CustomerMainServiceImpl extends ServiceImpl<CustomerMainMapper, CustomerMain> implements CustomerMainService {

    @Resource
    private CustomerMainMapper customerMainMapper;
    @Resource
    private CustomerItemService customerItemService;
    @Resource
    private CustomerCarService customerCarService;
    @Resource
    private CustomerCarMapper customerCarMapper;
    @Resource
    private BusiLabelService busiLabelService;
    @Resource
    private DictDataApi dictDataApi;
    @Resource
    @Lazy
    private AdminUserApi adminUserApi;
    @Resource
    private PermissionApi permissionApi;
    @Resource
    private DeptApi deptApi;

    /**
     * 客户管理分页列表查询
     *
     * @param pageReqVO 客户管理查询条件封装实体
     * @param page      分页参数
     * @return com.baomidou.mybatisplus.core.metadata.IPage<cn.iocoder.yudao.module.custom.vo.CustomerMainRespVO>
     * @author PQZ
     * @date 14:57 2024/8/1
     **/
    @Override
    public IPage<CustomerMainRespVO> queryListPage(CustomerMainPageReqVO pageReqVO, Page<CustomerMainRespVO> page) {
        return customerMainMapper.selectListPage(pageReqVO, page);
    }

    /**
     * 保存客户信息
     *
     * @param saveReqVO 保存客户信息扩展实体
     * @param sign      标识(新增客户created/编辑客户update)
     * @return void
     * @author PQZ
     * @date 15:46 2024/8/1
     **/
    @Override
    @DSTransactional
    public void saveCustomer(CustomerMainSaveReqVO saveReqVO, String sign) {
        try {
            /*1、入参及基础参数值设置*/
            CustomerMain main = JSONUtil.toBean(JSONUtil.parseObj(saveReqVO).toJSONString(0), CustomerMain.class);
            Long userId;
            UserDTO user;
            /*2、新增客户时绑定绑定客户信息*/
            if (SIGN_CREATE.equals(sign)){
                //查询数据字典，根据客户类型匹配出预设角色code；
                DictDataRespDTO dict = dictDataApi.getDictData(DICT_CUS_TYPE, main.getTypeCode());
                AdminUserRespDTO userDTO = adminUserApi.getUserByUsername(saveReqVO.getPhoneNumber());
                user = BeanUtils.toBean(userDTO, UserDTO.class);
                //存在两种情况，一是该用户已经注册，二是该用户未注册
                if (null == user){
                    user = new UserDTO();
                    //如果不存在创建用户；
                    user.setUsername(saveReqVO.getPhoneNumber());
                    user.setNickname(saveReqVO.getCusName());
                    //默认密码
                    user.setPassword(PASSWORD_DEFAULT);
                    user.setMobile(saveReqVO.getPhoneNumber());
                    user.setUserType(USER_TYPE_CUS);
                    //该用户未注册情况下，如果是政企客户，需要在部门表中创建部门，并给用户绑定
                    if (CUS_TYPE_CORP.equals(main.getTypeCode())) {
                        //查询当前登录用户所属租户的政企客户部门id（父级部门）
                        DeptRespDTO parentDept = deptApi.getDeptByName(DEPT_NAME_CORP_NAME);
                        //在部门表下新增一个部门
                        DeptRespDTO deptRespDTO = new DeptRespDTO();
                        deptRespDTO.setName(saveReqVO.getCusName());
                        deptRespDTO.setStatus(CommonStatusEnum.ENABLE.getStatus());
                        //上级部门为本租户顶级部门
                        deptRespDTO.setParentId(parentDept.getId());
                        Long deptId = deptApi.saveDept(deptRespDTO);
                        //为用户绑定deptId
                        user.setDeptId(deptId);
                        //客户信息表绑定deptCode
                        main.setDeptCode(deptId);
                    }
                    //创建客户
                    userId = adminUserApi.createUser(user);
                } else {
                    userId = user.getId();
                }
                //客户表绑定用户id
                main.setUserId(userId);
                //绑定角色
                Set<String> roleCodes = new HashSet<>();
                roleCodes.add(dict.getRemark());
                permissionApi.assignUserRole(userId, roleCodes);
            }
            /*3、保存客户主表信息*/
            this.saveOrUpdate(main);
            /*4、保存扩展表信息*/
            if (!saveReqVO.getItemList().isEmpty()) {
                customerItemService.saveCutomItem(main.getId(), saveReqVO.getItemList());
            }
        } catch (ServiceException e) {
            log.error(e.getMessage());
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR);
        }

    }

    /**
     * 根据客户id查询客户信息
     *
     * @param id 客户id
     * @return cn.iocoder.yudao.module.custom.vo.CustomerMainRespVO
     * @author PQZ
     * @date 15:12 2024/8/2
     **/
    @Override
    public CustomerMainRespVO getCustomerById(String id) {
        /*1、主表信息*/
        CustomerMain main = this.getById(id);
        /*2、扩展表信息*/
        LambdaQueryWrapper<CustomerItem> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(BaseDO::getDeleted, 0).eq(CustomerItem::getCusId, id);
        List<CustomerItem> itemList = customerItemService.list(lambdaQueryWrapper);
        /*3、车辆信息*/
        List<CarMainRespVO> carList = customerCarMapper.selectCarListByCusId(id);
        CustomerMainRespVO result = JSONUtil.toBean(JSONUtil.parseObj(main).toJSONString(0), CustomerMainRespVO.class);
        result.setItemList(itemList);
        result.setCarList(carList);
        /*4、标签信息*/
        List<BusiLabel> labelList = busiLabelService.listByMainId(id);
        result.setLabelList(labelList);
        return result;
    }

    /**
     * 根据经办人所属企业查询经办人信息
     *
     * @param deptCode 经办人所属企业code
     * @return java.util.List<cn.iocoder.yudao.module.custom.vo.CustomerMainRespVO>
     * @author PQZ
     * @date 16:15 2024/8/2
     **/
    @Override
    public List<CustomerMain> getCustomerByDeptCode(String deptCode) {
        LambdaQueryWrapper<CustomerMain> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(BaseDO::getDeleted, 0).eq(CustomerMain::getDeptCode, deptCode).eq(CustomerMain::getTypeCode, CUS_TYPE_CORP_ATTN);
        return list(lambdaQueryWrapper);
    }

    /**
     * 绑定车辆信息
     *
     * @param saveReqVO CustomerMainSaveReqVO实体
     * @return void
     * @author PQZ
     * @date 18:42 2024/8/3
     **/
    @Override
    @DSTransactional
    public void bindCustomAndCar(CustomerMainSaveReqVO saveReqVO) {
        List<CustomerCar> customerCars = new ArrayList<>();
        List<CarMainRespVO> carList = saveReqVO.getCarList();
        if (null != carList) {
            //组装数据
            carList.forEach(item -> {
                CustomerCar customerCar = new CustomerCar();
                customerCar.setCarId(item.getId());
                customerCar.setCusId(saveReqVO.getId());
                customerCar.setIsOwner(item.getIsOwner());
                customerCars.add(customerCar);
            });
        }
        customerCarService.bindCustomerCar(saveReqVO.getId(), CUS_SIGN_CUSTOMER, customerCars);
    }
}