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.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
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.CustomerCouponService;
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.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

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;
    @Resource
    private CustomerCouponService customerCouponService;

    /**
     * 客户管理分页列表查询
     *
     * @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)
     * @author PQZ
     * @date 15:46 2024/8/1
     **/
    @Override
    @DSTransactional
    public UserDTO saveCustomer(CustomerMainSaveReqVO saveReqVO, String sign) {
        Long userId;
        UserDTO user = null;
        try {
            /*1、入参及基础参数值设置*/
            CustomerMain main = JSONUtil.toBean(JSONUtil.parseObj(saveReqVO).toJSONString(0), CustomerMain.class);

            /*2、新增客户时绑定绑定客户信息*/
            if (SIGN_CREATE.equals(sign)){
                //查询数据字典，根据客户类型匹配出预设角色code；
                DictDataRespDTO dict = dictDataApi.getDictData(DICT_CUS_TYPE, main.getTypeCode());
                //查客户，调用租户为null的查询---未来启用多租户的时候放开 TODO
//                AdminUserRespDTO userDTO = adminUserApi.getUserByUsernameNoTenantId(saveReqVO.getPhoneNumber());
                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);
                    }else{
                        //私人客户和代办客户归属到默认的部门中
                        String deptName = "";
                        if(CUS_TYPE_PRIVATE.equals(main.getTypeCode())){
                            deptName =DEPT_NAME_PRIVATE_NAME;
                        }else if(CUS_TYPE_AGENT.equals(main.getTypeCode())){
                            deptName = DEPT_NAME_AGENT_NAME;
                        }
                        DeptRespDTO parentDept = deptApi.getDeptByName(deptName);
                        user.setDeptId(parentDept.getId());
                        main.setDeptCode(parentDept.getId());
                    }
                    //创建客户
                    userId = adminUserApi.createUser(user);
                    user.setId(userId);
                } else {
                    userId = user.getId();
                }
                //客户表绑定用户id
                main.setUserId(userId);
                //绑定角色
                Set<String> roleCodes = new HashSet<>();
                roleCodes.add(dict.getRemark());
                permissionApi.assignUserRole(userId, roleCodes);
            }
            /*3、保存客户主表信息*/
            //暂时写死会员id  TODO
            main.setMemberLevelId("9d4567b7e68803933f4917a4aab6b745");

            //解决重复用户校验
            if (StringUtils.isEmpty(main.getId())){
                //通过手机号匹配是否存在当前用户
                LambdaQueryWrapper<CustomerMain> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                lambdaQueryWrapper.eq(CustomerMain::getPhoneNumber,main.getPhoneNumber());
                List<CustomerMain> list = list(lambdaQueryWrapper);
                if (list.isEmpty()){
                    //如不存在插入
                    this.save(main);
                } else {
                    if (StringUtils.isNotEmpty(main.getCusName())) {
                        //如存在，更新用户名称
                        CustomerMain updateCust = list.get(0);
                        updateCust.setCusName(main.getCusName());
                        this.updateById(updateCust);
                    }
                }
            } else {
                //存在id直接更行
                this.updateById(main);
            }


            /*4、保存扩展表信息*/
            if ( null!=saveReqVO.getItemList() && !saveReqVO.getItemList().isEmpty()) {
                customerItemService.saveCutomItem(main.getId(), saveReqVO.getItemList());
            }
        } catch (ServiceException e) {
            log.error(e.getMessage());
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR);
        }
        return user;
    }

    /**
     * 根据客户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、主表信息*/
        CustomerMainRespVO result = customerMainMapper.queryById(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);
        result.setItemList(itemList);
        result.setCarList(carList);
        /*4、标签信息*/
        List<BusiLabel> labelList = busiLabelService.listByMainId(id);
        result.setLabelList(labelList);
        /*5、卡券信息*/
        List<CustomerCouponRespVO> couponList = customerCouponService.listByCusId(id);
        result.setCouponList(couponList);
        return result;
    }

    /**
     * 根据userID客户表信息
     *
     * @param userId 用户id
     * @return cn.iocoder.yudao.module.custom.vo.CustomerMainRespVO
     * @author vinjor-M
     * @date 15:25 2024/9/27
     **/
    @Override
    public CustomerMain getCustomerByUserId(Long userId) {
        LambdaQueryWrapper<CustomerMain> queryWrapper = new LambdaQueryWrapper<CustomerMain>()
                .eq(CustomerMain::getUserId,userId);
        List<CustomerMain> customerList = this.list(queryWrapper);
        if(customerList.isEmpty()){
            return null;
        }else{
            return customerList.get(0);
        }
    }

    /**
     * 获取当前登录用户的客户信息
     *
     * @return cn.iocoder.yudao.module.custom.vo.CustomerMainRespVO
     * @author PQZ
     * @date 17:27 2024/9/24
     **/
    @Override
    public CustomerMainRespVO getUserCustomer() {
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        LambdaQueryWrapper<CustomerMain> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(CustomerMain::getUserId,loginUser.getId()).eq(BaseDO::getDeleted,'0');
        CustomerMain customerMain = getOne(lambdaQueryWrapper);
        if (ObjectUtils.isEmpty(customerMain)){
            return null;
        }
        return getCustomerById(customerMain.getId());
    }

    /**
     * 根据经办人所属企业查询经办人信息
     *
     * @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);
    }

    /**
     * 根据车辆ID反查用户信息
     *
     * @author 小李
     * @date 21:41 2024/9/24
     * @param carId 车辆ID
     **/
    @Override
    public CustomerMain getCustomerByCarId(String carId){
        return baseMapper.getCustomerByCarId(carId);
    }
}
