package cn.iocoder.yudao.module.contract.service.customercontract;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.enums.GeneralStatusEnum;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.contract.controller.admin.customercontract.vo.*;
import cn.iocoder.yudao.module.contract.dal.dataobject.customercontract.CustomerContractDO;
import cn.iocoder.yudao.module.contract.dal.dataobject.customercontract.CustomerContractHistoryDO;
import cn.iocoder.yudao.module.contract.dal.mysql.customercontract.CustomerContractHistoryMapper;
import cn.iocoder.yudao.module.contract.dal.mysql.customercontract.CustomerContractMapper;
import cn.iocoder.yudao.module.contract.enums.ContractStatusEnum;
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.system.api.dept.DeptApi;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.w3c.dom.ls.LSException;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.ConcurrentModificationException;
import java.util.List;
import java.util.Objects;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.contract.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.employee.enums.ErrorCodeConstants.EMPLOYEE_INFO_NOT_EXISTS;

/**
 * 销售合同信息 Service 实现类
 *
 * @author dp
 */
@Service
@Validated
public class CustomerContractServiceImpl implements CustomerContractService {

    @Resource
    private CustomerContractMapper customerContractMapper;
    @Resource
    private CustomerContractHistoryMapper customerContractHistoryMapper;

    @Resource
    private FileApi fileApi;

    @Resource
    private EmployeeApi employeeApi;

    @Resource
    private DeptApi deptApi;

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

    @Override
    public Long createCustomerContract(CustomerContractSaveReqVO createReqVO) {
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        EmployeeRespDTO loginEmployee = employeeApi.getEmployeeByUserId(loginUserId);
        if (Objects.isNull(loginEmployee)) {
            throw exception(new ErrorCode(EMPLOYEE_INFO_NOT_EXISTS.getCode(), "登录用户员工信息不存在"));
        }
        String customerContractCode = createReqVO.getCustomerContractCode();
        if (StrUtil.isNotBlank(customerContractCode)) {
            validateCustomerContractCode(customerContractCode);
        }
        String customerContractName = createReqVO.getCustomerContractName();
        if (StrUtil.isNotBlank(customerContractName)) {
            validateCustomerContractName(customerContractName, createReqVO.getId());
        }
        // 插入
        CustomerContractDO customerContract = BeanUtils.toBean(createReqVO, CustomerContractDO.class);
        // uuid
        customerContract.setCustomerContractUuid(IdUtil.fastSimpleUUID());
        // 负责人及部门
        Long ownerEmployeeId = createReqVO.getOwnerEmployeeId();
        EmployeeRespDTO ownerEmployee = employeeApi.getEmployeeById(ownerEmployeeId);
        if (Objects.isNull(ownerEmployee)) {
            throw exception(EMPLOYEE_INFO_NOT_EXISTS);
        }
        Long deptId = ownerEmployee.getDeptId();
        if (Objects.nonNull(deptId)) {
            customerContract.setDeptId(deptId);
        }
        // 合同状态：0未归档
        customerContract.setContractStatus(ContractStatusEnum.UNARCHIVED.getStatus());
        // 是否关闭：0否
        customerContract.setClosed(GeneralStatusEnum.NO.getStatus());
        // 是否终止：0否
        customerContract.setTerminate(GeneralStatusEnum.NO.getStatus());
        // 是否变更
        if (Objects.isNull(createReqVO.getIsChange())) {
            customerContract.setIsChange(GeneralStatusEnum.NO.getStatus());
        }

        // 创建人
        customerContract.setCreator(String.valueOf(loginEmployee.getId()));

        customerContractMapper.insert(customerContract);

        // 附件
        fileApi.updateFileBiz(createReqVO.getFileIdList(), customerContract.getCustomerContractUuid());

        // 返回
        return customerContract.getId();
    }

    private void validateCustomerContractName(String customerContractName, Long id) {
        LambdaQueryWrapper<CustomerContractDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(CustomerContractDO::getCustomerContractName, customerContractName);
        if (Objects.nonNull(id)) {
            lambdaQueryWrapper.ne(CustomerContractDO::getId, id);
        }
        if (customerContractMapper.selectCount(lambdaQueryWrapper) > 0) {
            throw exception(CUSTOMER_CONTRACT_NAME_EXISTS);
        }
    }

    private void validateCustomerContractCode(String customerContractCode) {
        Long aLong = customerContractMapper.selectCount(CustomerContractDO::getCustomerContractCode, customerContractCode);
        if (aLong > 0) {
            throw exception(CUSTOMER_CONTRACT_CODE_EXISTS);
        }
    }

    @Override
    public void updateCustomerContract(CustomerContractSaveReqVO updateReqVO) {
        // 校验存在
        CustomerContractDO customerContractDO = validateCustomerContractExists(updateReqVO.getId());
        String customerContractName = updateReqVO.getCustomerContractName();
        if (StrUtil.isNotBlank(customerContractName)) {
            validateCustomerContractName(customerContractName, updateReqVO.getId());
        }
        // 更新
        CustomerContractDO updateObj = BeanUtils.toBean(updateReqVO, CustomerContractDO.class);
        // 负责人及部门
        Long ownerEmployeeId = updateReqVO.getOwnerEmployeeId();
        EmployeeRespDTO ownerEmployee = employeeApi.getEmployeeById(ownerEmployeeId);
        if (Objects.isNull(ownerEmployee)) {
            throw exception(EMPLOYEE_INFO_NOT_EXISTS);
        }
        Long deptId = ownerEmployee.getDeptId();
        if (Objects.nonNull(deptId)) {
            updateObj.setDeptId(deptId);
        }
        customerContractMapper.updateById(updateObj);

        // 附件
        fileApi.updateFileBiz(updateReqVO.getFileIdList(), customerContractDO.getCustomerContractUuid());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteCustomerContract(Long id) {
        // 校验存在
        CustomerContractDO customerContractDO = validateCustomerContractExists(id);
        // 删除
        customerContractMapper.deleteById(id);

        // 删除子表
        // deleteCustomerContractHistoryByCode(customerContractDO.getCustomerContractCode());
    }

    @Override
    public Integer deleteCustomerContractOriginal(Long id) {
        // 校验存在
        CustomerContractDO customerContractDO = validateCustomerContractExists(id);
        return customerContractMapper.deleteCustomerContractOriginal(id);
    }

    private CustomerContractDO validateCustomerContractExists(Long id) {
        CustomerContractDO customerContractDO = customerContractMapper.selectById(id);
        if (customerContractDO == null) {
            throw exception(CUSTOMER_CONTRACT_NOT_EXISTS);
        }
        return customerContractDO;
    }

    @Override
    public CustomerContractDO getCustomerContract(Long id) {
        return customerContractMapper.selectById(id);
    }

    @Override
    public PageResult<CustomerContractRespVO> getCustomerContractPage(CustomerContractPageReqVO pageReqVO) {
        pageReqVO.setPageNo((pageReqVO.getPageNo() - 1) * pageReqVO.getPageSize());

        long pageCount = -1;
        if (!PageParam.PAGE_SIZE_NONE.equals(pageReqVO.getPageSize())) {
            pageCount = customerContractMapper.getPageCount(pageReqVO);
        }

        if (pageCount == 0) {
            return PageResult.empty();
        }

        List<CustomerContractRespVO> pageList = customerContractMapper.getPageList(pageReqVO);

        return new PageResult<>(pageList, pageCount);
    }

    @Override
    public List<CustomerContractDO> getCustomerContractList(CustomerContractListVO listVO) {
        // Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        // EmployeeRespDTO loginEmployee = employeeApi.getEmployeeByUserId(loginUserId);
        // if (loginEmployee == null || loginEmployee.getDeptId() == null) {
        //     // 没有员工信息或部门信息，返回空集合
        //     return Collections.emptyList();
        // }
        if (listVO.getCustomerId() == null) {
            // 没有客户id，返回空集合
            return Collections.emptyList();
        }
        LambdaQueryWrapper<CustomerContractDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(CustomerContractDO::getCustomerId, listVO.getCustomerId())
                .eq(listVO.getClosed() != null, CustomerContractDO::getClosed, listVO.getClosed());
        return customerContractMapper.selectList(lambdaQueryWrapper);

    }

    @Override
    public Integer openCustomerContract(Long id) {
        CustomerContractDO customerContractDO = validateCustomerContractExists(id);
        if (GeneralStatusEnum.NO.getStatus().equals(customerContractDO.getClosed())) {
            throw exception(CUSTOMER_CONTRACT_NOT_CLOSED);
        }
        CustomerContractDO build = CustomerContractDO.builder()
                .id(id)
                .closed(GeneralStatusEnum.NO.getStatus())
                .build();
        return customerContractMapper.updateById(build);
    }

    @Override
    public Integer closeCustomerContract(CustomerContractCloseReqVO closeReqVO) {
        CustomerContractDO customerContractDO = validateCustomerContractExists(closeReqVO.getId());

        if (GeneralStatusEnum.YES.getStatus().equals(customerContractDO.getClosed())) {
            throw exception(new ErrorCode(CUSTOMER_CONTRACT_NOT_CLOSED.getCode(), "合同已经是关闭状态"));
        }

        CustomerContractDO build = CustomerContractDO.builder()
                .id(closeReqVO.getId())
                .closed(GeneralStatusEnum.YES.getStatus())
                .closeReason(closeReqVO.getCloseReason())
                .build();

        return customerContractMapper.updateById(build);
    }

    @Override
    public Integer terminateCustomerContract(CustomerContractTerminatedReqVO terminatedReqVO) {
        CustomerContractDO customerContractDO = validateCustomerContractExists(terminatedReqVO.getId());
        if (GeneralStatusEnum.YES.getStatus().equals(customerContractDO.getTerminate())) {
            throw exception(new ErrorCode(CUSTOMER_CONTRACT_NOT_CLOSED.getCode(), "合同已经是终止状态"));
        }
        CustomerContractDO build = CustomerContractDO.builder()
                .id(terminatedReqVO.getId())
                .terminate(GeneralStatusEnum.YES.getStatus())
                .terminateDate(terminatedReqVO.getTerminateDate())
                .terminateReason(terminatedReqVO.getTerminateReason())
                .build();
        return customerContractMapper.updateById(build);
    }

    @Override
    public Integer editCustomerStatus(CustomerContractStatusReqVO statusReqVO) {
        CustomerContractDO customerContractDO = validateCustomerContractExists(statusReqVO.getId());

        CustomerContractDO build = CustomerContractDO.builder()
                .id(statusReqVO.getId())
                .contractStatus(statusReqVO.getContractStatus())
                .build();
        return customerContractMapper.updateById(build);
    }

    @Override
    public CustomerContractDO getCustomerContractByCode(String customerContractCode) {
        return customerContractMapper.selectOne(CustomerContractDO::getCustomerContractCode, customerContractCode);
    }

    // ==================== 子表（销售合同历史信息） ====================

    @Override
    public PageResult<CustomerContractHistoryDO> getCustomerContractHistoryPage(PageParam pageReqVO, String code) {
        pageReqVO.setPageNo((pageReqVO.getPageNo() - 1) * pageReqVO.getPageSize());

        long pageCount = -1;
        if (!PageParam.PAGE_SIZE_NONE.equals(pageReqVO.getPageSize())) {
            pageCount = customerContractHistoryMapper.getPageCount(pageReqVO, code);
        }

        if (pageCount == 0) {
            return PageResult.empty();
        }

        List<CustomerContractHistoryDO> pageList = customerContractHistoryMapper.getPageList(pageReqVO, code);

        return new PageResult<>(pageList, pageCount);
    }

    @Override
    public Long createCustomerContractHistory(CustomerContractHistoryDO customerContractHistory) {
        customerContractHistoryMapper.insert(customerContractHistory);
        return customerContractHistory.getId();
    }

    // @Override
    // public void updateCustomerContractHistory(CustomerContractHistoryDO customerContractHistory) {
    //     // 校验存在
    //     validateCustomerContractHistoryExists(customerContractHistory.getId());
    //     // 更新
    //     customerContractHistoryMapper.updateById(customerContractHistory);
    // }
    //
    // @Override
    // public void deleteCustomerContractHistory(Long id) {
    //     // 校验存在
    //     validateCustomerContractHistoryExists(id);
    //     // 删除
    //     customerContractHistoryMapper.deleteById(id);
    // }

    @Override
    public CustomerContractHistoryDO getCustomerContractHistory(Long id) {
        // validateCustomerContractHistoryExists(id);
        return customerContractHistoryMapper.selectById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void alterCustomerContract(CustomerContractSaveReqVO updateReqVO) {
        String customerContractCode = updateReqVO.getCustomerContractCode();
        CustomerContractDO customerContract = this.getCustomerContractByCode(customerContractCode);
        if (Objects.isNull(customerContract)) {
            throw exception(CUSTOMER_CONTRACT_NOT_EXISTS);
        }
        // 物理删除原合同信息
        this.deleteCustomerContractOriginal(customerContract.getId());
        // 添加到历史合同信息表中
        CustomerContractHistoryDO customerContractHistoryDO = BeanUtils.toBean(customerContract, CustomerContractHistoryDO.class);
        customerContractHistoryDO.setId(null);
        this.createCustomerContractHistory(customerContractHistoryDO);
        // 新增新合同
        updateReqVO.setId(null);
        updateReqVO.setIsChange(GeneralStatusEnum.YES.getStatus());
        this.createCustomerContract(updateReqVO);
    }

    private CustomerContractHistoryDO validateCustomerContractHistoryExists(Long id) {
        CustomerContractHistoryDO customerContractHistoryDO = customerContractHistoryMapper.selectById(id);
        if (customerContractHistoryDO == null) {
            throw exception(CUSTOMER_CONTRACT_HISTORY_NOT_EXISTS);
        }
        return customerContractHistoryDO;
    }

    private void deleteCustomerContractHistoryByCode(String code) {
        customerContractHistoryMapper.deleteByCode(code);
    }


}