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

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.suppliercontract.vo.SupplierContractCloseReqVO;
import cn.iocoder.yudao.module.contract.controller.admin.suppliercontract.vo.SupplierContractPageReqVO;
import cn.iocoder.yudao.module.contract.controller.admin.suppliercontract.vo.SupplierContractRespVO;
import cn.iocoder.yudao.module.contract.controller.admin.suppliercontract.vo.SupplierContractSaveReqVO;
import cn.iocoder.yudao.module.contract.controller.admin.suppliercontract.vo.SupplierContractStatusReqVO;
import cn.iocoder.yudao.module.contract.controller.admin.suppliercontract.vo.SupplierContractTerminatedReqVO;
import cn.iocoder.yudao.module.contract.dal.dataobject.suppliercontract.SupplierContractDO;
import cn.iocoder.yudao.module.contract.dal.dataobject.suppliercontract.SupplierContractHistoryDO;
import cn.iocoder.yudao.module.contract.dal.mysql.suppliercontract.SupplierContractHistoryMapper;
import cn.iocoder.yudao.module.contract.dal.mysql.suppliercontract.SupplierContractMapper;
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 cn.iocoder.yudao.module.system.api.permission.PermissionApi;
import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
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.CONTRACT_NOT_ALLOW_OPERATE_BY_OTHER;
import static cn.iocoder.yudao.module.contract.enums.ErrorCodeConstants.SUPPLIER_CONTRACT_CODE_EXISTS;
import static cn.iocoder.yudao.module.contract.enums.ErrorCodeConstants.SUPPLIER_CONTRACT_HISTORY_NOT_EXISTS;
import static cn.iocoder.yudao.module.contract.enums.ErrorCodeConstants.SUPPLIER_CONTRACT_NAME_EXISTS;
import static cn.iocoder.yudao.module.contract.enums.ErrorCodeConstants.SUPPLIER_CONTRACT_NOT_CLOSED;
import static cn.iocoder.yudao.module.contract.enums.ErrorCodeConstants.SUPPLIER_CONTRACT_NOT_EXISTS;
import static cn.iocoder.yudao.module.contract.enums.ErrorCodeConstants.SUPPLIER_CONTRACT_START_DATE_GREATER_THAN_END_DATE;
import static cn.iocoder.yudao.module.employee.enums.ErrorCodeConstants.EMPLOYEE_INFO_NOT_EXISTS;

/**
 * 采购合同信息 Service 实现类
 *
 * @author dp
 */
@Service
@Validated
public class SupplierContractServiceImpl implements SupplierContractService {

    @Resource
    private SupplierContractMapper supplierContractMapper;
    @Resource
    private SupplierContractHistoryMapper supplierContractHistoryMapper;

    @Resource
    private FileApi fileApi;

    @Resource
    private EmployeeApi employeeApi;

    @Resource
    private DeptApi deptApi;

    @Resource
    private PermissionApi permissionApi;

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

    @Override
    public Long createSupplierContract(SupplierContractSaveReqVO createReqVO) {
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        EmployeeRespDTO loginEmployee = employeeApi.getEmployeeByUserId(loginUserId);
        if (Objects.isNull(loginEmployee)) {
            throw exception(new ErrorCode(EMPLOYEE_INFO_NOT_EXISTS.getCode(), "登录用户员工信息不存在"));
        }
        String supplierContractCode = createReqVO.getSupplierContractCode();
        if (StrUtil.isNotBlank(supplierContractCode)) {
            validateSupplierContractCode(supplierContractCode, createReqVO.getId());
        }
        String supplierContractName = createReqVO.getSupplierContractName();
        if (StrUtil.isNotBlank(supplierContractName)) {
            validateSupplierContractName(supplierContractName, createReqVO.getId());
        }
        String startDate = createReqVO.getStartDate();
        String endDate = createReqVO.getEndDate();
        if (StrUtil.isNotBlank(startDate) && StrUtil.isNotBlank(endDate)) {
            if (startDate.compareTo(endDate) > 0) {
                throw exception(SUPPLIER_CONTRACT_START_DATE_GREATER_THAN_END_DATE);
            }
        }
        // 插入
        SupplierContractDO supplierContract = BeanUtils.toBean(createReqVO, SupplierContractDO.class);
        // uuid
        supplierContract.setSupplierContractUuid(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)) {
            supplierContract.setDeptId(deptId);
        }
        // 合同状态：0未归档
        supplierContract.setContractStatus(ContractStatusEnum.UNARCHIVED.getStatus());
        // 是否关闭：0否
        supplierContract.setClosed(GeneralStatusEnum.NO.getStatus());
        // 是否终止：0否
        supplierContract.setTerminate(GeneralStatusEnum.NO.getStatus());
        // 是否变更
        if (Objects.isNull(createReqVO.getIsChange())) {
            supplierContract.setIsChange(GeneralStatusEnum.NO.getStatus());
        }

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

        supplierContractMapper.insert(supplierContract);

        // 附件
        fileApi.updateFileBiz(createReqVO.getFileIdList(), supplierContract.getSupplierContractUuid());

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

    private void validateSupplierContractName(String supplierContractName, Long id) {
        LambdaQueryWrapper<SupplierContractDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SupplierContractDO::getSupplierContractName, supplierContractName);
        if (Objects.nonNull(id)) {
            lambdaQueryWrapper.ne(SupplierContractDO::getId, id);
        }
        if (supplierContractMapper.selectCount(lambdaQueryWrapper) > 0) {
            throw exception(SUPPLIER_CONTRACT_NAME_EXISTS);
        }
    }

    private void validateSupplierContractCode(String supplierContractCode, Long id) {
        LambdaQueryWrapper<SupplierContractDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SupplierContractDO::getSupplierContractCode, supplierContractCode);
        if (Objects.nonNull(id)) {
            lambdaQueryWrapper.ne(SupplierContractDO::getId, id);
        }
        if (supplierContractMapper.selectCount(lambdaQueryWrapper) > 0) {
            throw exception(SUPPLIER_CONTRACT_CODE_EXISTS);
        }
    }

    @Override
    public void updateSupplierContract(SupplierContractSaveReqVO updateReqVO) {
        // 校验存在
        SupplierContractDO supplierContractDO = validateSupplierContractExists(updateReqVO.getId());
        validateOperator(SecurityFrameworkUtils.getLoginUserId(), Long.valueOf(supplierContractDO.getCreator()));
        String supplierContractName = updateReqVO.getSupplierContractName();
        if (StrUtil.isNotBlank(supplierContractName)) {
            validateSupplierContractName(supplierContractName, updateReqVO.getId());
        }
        String supplierContractCode = updateReqVO.getSupplierContractCode();
        if (StrUtil.isNotBlank(supplierContractCode)) {
            validateSupplierContractCode(supplierContractCode, updateReqVO.getId());
        }
        String startDate = updateReqVO.getStartDate();
        String endDate = updateReqVO.getEndDate();
        if (StrUtil.isNotBlank(startDate) && StrUtil.isNotBlank(endDate)) {
            if (startDate.compareTo(endDate) > 0) {
                throw exception(SUPPLIER_CONTRACT_START_DATE_GREATER_THAN_END_DATE);
            }
        }
        // 更新
        SupplierContractDO updateObj = BeanUtils.toBean(updateReqVO, SupplierContractDO.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);
        }
        supplierContractMapper.updateById(updateObj);

        // 附件
        fileApi.updateFileBiz(updateReqVO.getFileIdList(), supplierContractDO.getSupplierContractUuid());
    }

    private void validateOperator(Long loginUserId, Long creator) {
        if (!Objects.equals(loginUserId, creator)) {
            throw exception(CONTRACT_NOT_ALLOW_OPERATE_BY_OTHER);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteSupplierContract(Long id) {
        // 校验存在
        SupplierContractDO supplierContractDO = validateSupplierContractExists(id);
        validateOperator(SecurityFrameworkUtils.getLoginUserId(), Long.valueOf(supplierContractDO.getCreator()));
        // 删除
        supplierContractMapper.deleteById(id);

        // 删除子表
        // deleteSupplierContractHistoryByCode(supplierContractDO.getSupplierContractCode());
    }

    @Override
    public Integer deleteSupplierContractOriginal(Long id) {
        // 校验存在
        SupplierContractDO supplierContractDO = validateSupplierContractExists(id);
        return supplierContractMapper.deleteSupplierContractOriginal(id);
    }

    private SupplierContractDO validateSupplierContractExists(Long id) {
        SupplierContractDO supplierContractDO = supplierContractMapper.selectById(id);
        if (supplierContractDO == null) {
            throw exception(SUPPLIER_CONTRACT_NOT_EXISTS);
        }
        return supplierContractDO;
    }

    @Override
    public SupplierContractDO getSupplierContract(Long id) {
        return supplierContractMapper.selectById(id);
    }

    @Override
    public PageResult<SupplierContractRespVO> getSupplierContractPage(SupplierContractPageReqVO pageReqVO) {
        // 数据权限
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        DeptDataPermissionRespDTO deptDataPermission = permissionApi.getDeptDataPermission(loginUserId);
        pageReqVO.setDeptDataPermission(deptDataPermission);
        pageReqVO.setUserId(loginUserId);
        pageReqVO.setPageNo((pageReqVO.getPageNo() - 1) * pageReqVO.getPageSize());

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

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

        List<SupplierContractRespVO> pageList = supplierContractMapper.getPageList(pageReqVO);

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

    @Override
    public Integer openSupplierContract(Long id) {
        SupplierContractDO supplierContractDO = validateSupplierContractExists(id);
        if (GeneralStatusEnum.NO.getStatus().equals(supplierContractDO.getClosed())) {
            throw exception(SUPPLIER_CONTRACT_NOT_CLOSED);
        }
        LambdaUpdateWrapper<SupplierContractDO> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.set(SupplierContractDO::getClosed, GeneralStatusEnum.NO.getStatus())
                .set(SupplierContractDO::getCloseReason, null)
                .eq(SupplierContractDO::getId, id);
        return supplierContractMapper.update(lambdaUpdateWrapper);
    }

    @Override
    public Integer closeSupplierContract(SupplierContractCloseReqVO closeReqVO) {
        SupplierContractDO supplierContractDO = validateSupplierContractExists(closeReqVO.getId());

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

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

        return supplierContractMapper.updateById(build);
    }

    @Override
    public Integer terminateSupplierContract(SupplierContractTerminatedReqVO terminatedReqVO) {
        SupplierContractDO supplierContractDO = validateSupplierContractExists(terminatedReqVO.getId());
        if (GeneralStatusEnum.YES.getStatus().equals(supplierContractDO.getTerminate())) {
            throw exception(new ErrorCode(SUPPLIER_CONTRACT_NOT_CLOSED.getCode(), "合同已经是终止状态"));
        }
        SupplierContractDO build = SupplierContractDO.builder()
                .id(terminatedReqVO.getId())
                .terminate(GeneralStatusEnum.YES.getStatus())
                .terminateDate(terminatedReqVO.getTerminateDate())
                .terminateReason(terminatedReqVO.getTerminateReason())
                .build();
        return supplierContractMapper.updateById(build);
    }

    @Override
    public Integer editSupplierStatus(SupplierContractStatusReqVO statusReqVO) {
        SupplierContractDO supplierContractDO = validateSupplierContractExists(statusReqVO.getId());

        SupplierContractDO build = SupplierContractDO.builder()
                .id(statusReqVO.getId())
                .contractStatus(statusReqVO.getContractStatus())
                .build();
        return supplierContractMapper.updateById(build);
    }

    @Override
    public SupplierContractDO getSupplierContractByCode(String supplierContractCode) {
        return supplierContractMapper.selectOne(SupplierContractDO::getSupplierContractCode, supplierContractCode);
    }

    // ==================== 子表（采购合同历史信息） ====================

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

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

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

        List<SupplierContractHistoryDO> pageList = supplierContractHistoryMapper.getPageList(pageReqVO, code);

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

    @Override
    public Long createSupplierContractHistory(SupplierContractHistoryDO supplierContractHistory) {
        supplierContractHistoryMapper.insert(supplierContractHistory);
        return supplierContractHistory.getId();
    }

    // @Override
    // public void updateSupplierContractHistory(SupplierContractHistoryDO supplierContractHistory) {
    //     // 校验存在
    //     validateSupplierContractHistoryExists(supplierContractHistory.getId());
    //     // 更新
    //     supplierContractHistoryMapper.updateById(supplierContractHistory);
    // }
    //
    // @Override
    // public void deleteSupplierContractHistory(Long id) {
    //     // 校验存在
    //     validateSupplierContractHistoryExists(id);
    //     // 删除
    //     supplierContractHistoryMapper.deleteById(id);
    // }

    @Override
    public SupplierContractHistoryDO getSupplierContractHistory(Long id) {
        return supplierContractHistoryMapper.selectById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void alterSupplierContract(SupplierContractSaveReqVO updateReqVO) {
        String supplierContractCode = updateReqVO.getSupplierContractCode();
        SupplierContractDO supplierContract = this.getSupplierContractByCode(supplierContractCode);
        if (Objects.isNull(supplierContract)) {
            throw exception(SUPPLIER_CONTRACT_NOT_EXISTS);
        }
        // 物理删除原合同信息
        this.deleteSupplierContractOriginal(supplierContract.getId());
        // 添加到历史合同信息表中
        SupplierContractHistoryDO supplierContractHistoryDO = BeanUtils.toBean(supplierContract, SupplierContractHistoryDO.class);
        supplierContractHistoryDO.setId(null);
        this.createSupplierContractHistory(supplierContractHistoryDO);
        // 新增新合同
        updateReqVO.setId(null);
        updateReqVO.setIsChange(GeneralStatusEnum.YES.getStatus());
        this.createSupplierContract(updateReqVO);
    }

    private void validateSupplierContractHistoryExists(Long id) {
        if (supplierContractHistoryMapper.selectById(id) == null) {
            throw exception(SUPPLIER_CONTRACT_HISTORY_NOT_EXISTS);
        }
    }

    private void deleteSupplierContractHistoryByCode(String code) {
        supplierContractHistoryMapper.deleteByCode(code);
    }

}