package cn.iocoder.yudao.module.customer.service.info;

import cn.hutool.core.util.IdUtil;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.employee.api.EmployeeApi;
import cn.iocoder.yudao.module.employee.api.dto.EmployeeRespDTO;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
import cn.iocoder.yudao.module.infra.api.file.dto.FileDTO;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import cn.iocoder.yudao.module.customer.controller.admin.info.vo.*;
import cn.iocoder.yudao.module.customer.dal.dataobject.info.CustomerInfoDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.customer.dal.mysql.info.CustomerInfoMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.customer.enums.ErrorCodeConstants.CUSTOMER_CODE_EXISTS;
import static cn.iocoder.yudao.module.customer.enums.ErrorCodeConstants.CUSTOMER_INFO_NOT_EXISTS;

/**
 * 客户信息 Service 实现类
 *
 * @author zhaopq
 */
@Service
@Validated
public class CustomerInfoServiceImpl implements CustomerInfoService {

    @Resource
    private CustomerInfoMapper infoMapper;
    @Resource
    private FileApi fileApi;
    @Resource
    private DeptApi deptApi;
    @Resource
    private EmployeeApi employeeApi;

    @Override
    public Long createInfo(CustomerInfoSaveReqVO createReqVO) {
        // 客户编号判重
        if (StringUtils.isNotBlank(createReqVO.getCustomerCode())
                && infoMapper.selectOne(
                        new LambdaQueryWrapper<CustomerInfoDO>()
                                .eq(CustomerInfoDO::getCustomerCode,
                                        createReqVO.getCustomerCode())) != null) {
            throw exception(CUSTOMER_CODE_EXISTS);
        }
        // 获取用户信息和租户ID
        LoginUser user = SecurityFrameworkUtils.getLoginUser();
//        Long tenantId = user != null && user.getTenantId() != null ? user.getTenantId() : 0L;
        Long userId = user != null && user.getId() != null ? user.getId() : 0L;
//        createReqVO.setTenantId(tenantId);
        // 通过用户ID获取登录员工信息
        EmployeeRespDTO loginEmployee = employeeApi.getEmployeeByUserId(userId);
        // 创建人信息
        if (loginEmployee != null) {
            createReqVO.setCreatorEmployeeId(loginEmployee.getId());
            createReqVO.setCreatorEmployeeName(loginEmployee.getName());
            createReqVO.setDeptId(loginEmployee.getDeptId());
        }
        // 插入
        String infoId = IdUtil.fastSimpleUUID();
        createReqVO.setCustomerId(infoId);
        CustomerInfoDO info = BeanUtils.toBean(createReqVO, CustomerInfoDO.class);
        infoMapper.insert(info);
        // 保存业务uuid到附件中
        fileApi.updateFileBiz(createReqVO.getFileIdList(), infoId);
        // 返回
        return info.getId();
    }

    @Override
    public void updateInfo(CustomerInfoSaveReqVO updateReqVO) {
        // 校验存在
//        validateInfoExists(updateReqVO.getId());
        CustomerInfoDO info = infoMapper.selectById(updateReqVO.getId());
        if (info == null) {
            throw exception(CUSTOMER_INFO_NOT_EXISTS);
        }
        if (StringUtils.isNotBlank(updateReqVO.getCustomerCode())
                && !info.getCustomerCode().equals(updateReqVO.getCustomerCode())) {// 编码改变，需要判重
            // 客户编号判重
            if (infoMapper.selectOne(
                    new LambdaQueryWrapper<CustomerInfoDO>()
                            .eq(CustomerInfoDO::getCustomerCode,
                                    updateReqVO.getCustomerCode())) != null) {
                throw exception(CUSTOMER_CODE_EXISTS);
            }
        }
        // 保存业务uuid到附件中
        fileApi.updateFileBiz(updateReqVO.getFileIdList(), updateReqVO.getCustomerId());
        // 获取用户信息和租户ID
        LoginUser user = SecurityFrameworkUtils.getLoginUser();
        Long tenantId = user != null && user.getTenantId() != null ? user.getTenantId() : 0L;
        Long userId = user != null && user.getId() != null ? user.getId() : 0L;
        // 通过用户ID获取登录员工信息
        EmployeeRespDTO loginEmployee = employeeApi.getEmployeeByUserId(userId);
        // 创建人信息
        if (loginEmployee != null) {
            updateReqVO.setCreatorEmployeeId(loginEmployee.getId());
            updateReqVO.setCreatorEmployeeName(loginEmployee.getName());
            updateReqVO.setDeptId(loginEmployee.getDeptId());
        }
        // 更新
        CustomerInfoDO updateObj = BeanUtils.toBean(updateReqVO, CustomerInfoDO.class);
        infoMapper.updateById(updateObj);
    }

    @Override
    public void deleteInfo(Long id) {
        // 校验存在
        validateInfoExists(id);
        // 删除
        infoMapper.deleteById(id);
    }

    private void validateInfoExists(Long id) {
        if (infoMapper.selectById(id) == null) {
            throw exception(CUSTOMER_INFO_NOT_EXISTS);
        }
    }

    @Override
    public CustomerInfoDO getInfo(Long id) {
        return infoMapper.selectById(id);
    }

    @Override
    public CustomerInfoRespVO getById(Long id) {
        // 第一步：检查ID是否为空
        if (id == null) {
            throw new IllegalArgumentException("ID cannot be null");
        }
        // 第二步：从数据库获取数据
        CustomerInfoDO infoDO = infoMapper.selectById(id);
        if (infoDO == null) {
            throw exception(CUSTOMER_INFO_NOT_EXISTS);
        }
        // 第三步：将DO对象转换为VO对象
        CustomerInfoRespVO respVO = BeanUtils.toBean(infoDO, CustomerInfoRespVO.class);
        if (respVO == null) {
            // 理论上BeanUtils.toBean不应该返回null，但为了安全起见，还是检查一下
            throw new RuntimeException("Failed to convert DO to VO");
        }
        // 第四步：获取附件列表
        List<FileDTO> fileList = fileApi.getFileDTOListByBiz(infoDO.getCustomerId());
        if (fileList != null) {
            // 如果fileList不为null，则设置到VO对象中
            respVO.setFileList(fileList);
            List<Long> fileIdList = fileList.stream().map(FileDTO::getId).collect(Collectors.toList());
            respVO.setFileIdList(fileIdList);
        }
        // 部门
        if (infoDO.getDeptId() != null) {
            DeptRespDTO dept = deptApi.getDept(infoDO.getDeptId());
            respVO.setDeptName(dept.getName());
            if (dept != null && StringUtils.isNotBlank(dept.getName())) {
                respVO.setDeptName(dept.getName());
            }
        }
        // 第五步：返回VO对象
        return respVO;
    }

    @Override
    public PageResult<CustomerInfoDO> getInfoPage(CustomerInfoPageReqVO pageReqVO) {
        return infoMapper.selectPage(pageReqVO);
    }

    @Override
    public String getCustomerCode() {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        String format = formatter.format(LocalDateTime.now());
        return format + IdUtil.fastSimpleUUID();
    }

    @Override
    @TenantIgnore
    public void updateOpenStatus(Long id, Integer status) {
        // 校验存在
        validateInfoExists(id);
        // 更新状态
        // 更新状态
        CustomerInfoDO updateObj = new CustomerInfoDO();
        updateObj.setId(id);
        updateObj.setIsOpen(status);
        infoMapper.updateById(updateObj);
    }

    @Override
    public List<CustomerInfoDO> getCustomerInfoList(Collection<Long> ids) {
        return infoMapper.selectBatchIds(ids);
    }

    @Override
    public List<CustomerInfoDO> getCustomerInfoListForSelect(Integer isOpen) {
        LambdaQueryWrapper<CustomerInfoDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(isOpen != null, CustomerInfoDO::getIsOpen, isOpen);
        return infoMapper.selectList(lambdaQueryWrapper);
    }

}