package com.zt.plat.module.contractorder.service.originalmaterialprocessing;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zt.plat.framework.common.pojo.PageResult;
import com.zt.plat.framework.common.util.object.BeanUtils;
import com.zt.plat.module.contractorder.api.vo.contract.ContractRespVO;
import com.zt.plat.module.contractorder.controller.admin.originalmaterialprocessing.vo.OriginalMaterialProcessingDetailRespVO;
import com.zt.plat.module.contractorder.controller.admin.originalmaterialprocessing.vo.OriginalMaterialProcessingPageReqVO;
import com.zt.plat.module.contractorder.controller.admin.originalmaterialprocessing.vo.OriginalMaterialProcessingRespVO;
import com.zt.plat.module.contractorder.controller.admin.originalmaterialprocessing.vo.OriginalMaterialProcessingSaveReqVO;
import com.zt.plat.module.contractorder.controller.admin.purchaseorder.vo.DownOrUpOrderReqVO;
import com.zt.plat.module.contractorder.controller.admin.purchaseorder.vo.DownOrUpOrderRespVO;
import com.zt.plat.module.contractorder.controller.admin.purchaseorder.vo.LinkOrderReqVO;
import com.zt.plat.module.contractorder.controller.admin.purchaseorder.vo.PurchaseOrderRespVO;
import com.zt.plat.module.contractorder.dal.dataobject.contract.SystemRelativityDO;
import com.zt.plat.module.contractorder.dal.dataobject.entrustorder.EntrustOrderOrderDO;
import com.zt.plat.module.contractorder.dal.dataobject.originalmaterialprocessing.OriginalMaterialProcessingDO;
import com.zt.plat.module.contractorder.dal.mysql.contract.SystemRelativityMapper;
import com.zt.plat.module.contractorder.dal.mysql.originalmaterialprocessing.OriginalMaterialProcessingMapper;
import com.zt.plat.module.contractorder.enums.contract.DictEnum;
import com.zt.plat.module.contractorder.enums.purchaseorder.OrderStatusEnum;
import com.zt.plat.module.contractorder.service.contract.ContractService;
import com.zt.plat.module.system.api.sequence.SequenceApi;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.util.*;

import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.zt.plat.module.contractorder.enums.ErrorCodeConstants.CONTRACT_ORDER_EXISTS;
import static com.zt.plat.module.contractorder.enums.entrustorder.ErrorCodeConstants.ENTRUST_ORDER_NOT_EXISTS;
import static com.zt.plat.module.contractorder.enums.originalmaterialprocessing.ErrorCodeConstants.ORIGINAL_MATERIAL_PROCESSING_DO_NOT_EXISTS;


/**
 * 采购订单 Service 实现类
 *
 * @author 后台管理-1
 */
@Service
@Validated
@Slf4j
public class OriginalMaterialProcessingServiceImplImpl implements OriginalMaterialProcessingService {

    @Resource
    private OriginalMaterialProcessingMapper originalMaterialProcessingMapper;

    @Resource
    private OriginalMaterialProcessingDetailService originalMaterialProcessingDetailService;
    @Resource
    private SystemRelativityMapper systemRelativityMapper;

    @Resource
    private SequenceApi sequenceApi;

    @Resource
    private ContractService contractService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OriginalMaterialProcessingRespVO createOriginalMaterialProcessing(OriginalMaterialProcessingSaveReqVO createReqVO) {
        // 插入
        OriginalMaterialProcessingDO originalMaterialProcessingDO = BeanUtils.toBean(createReqVO, OriginalMaterialProcessingDO.class);
        originalMaterialProcessingDO.setIsPush(0);
        originalMaterialProcessingDO.setStatus(OrderStatusEnum.IN_PROGRESS.getCode());
        originalMaterialProcessingDO.setSystemOrderNumber(this.generateOrderNumber(""));
        originalMaterialProcessingMapper.insert(originalMaterialProcessingDO);
        OriginalMaterialProcessingRespVO bean = BeanUtils.toBean(originalMaterialProcessingDO, OriginalMaterialProcessingRespVO.class);
        //批量插入委托加工订单明细
        if (createReqVO.getDetails() != null && !createReqVO.getDetails().isEmpty()) {
            createReqVO.getDetails().forEach(entrustOrderDetail -> entrustOrderDetail.setOrderId(originalMaterialProcessingDO.getId()));
            List<OriginalMaterialProcessingDetailRespVO> originalMaterialProcessingDetailRespVOS = originalMaterialProcessingDetailService.insertBatchSomeColumn(createReqVO.getDetails());
            bean.setDetails(originalMaterialProcessingDetailRespVOS);
        }
        // 返回
        return bean;
    }

    @Override
    public List<OriginalMaterialProcessingRespVO> createBatchOriginalMaterialProcessing(List<OriginalMaterialProcessingSaveReqVO> createReqVOS) {
        List<OriginalMaterialProcessingRespVO> respVOS = new ArrayList<>();
        createReqVOS.forEach(createReqVO->{
          // 插入
          OriginalMaterialProcessingDO originalMaterialProcessingDO = BeanUtils.toBean(createReqVO, OriginalMaterialProcessingDO.class);
          originalMaterialProcessingDO.setIsPush(0);
          originalMaterialProcessingDO.setStatus(OrderStatusEnum.IN_PROGRESS.getCode());
          originalMaterialProcessingDO.setSystemOrderNumber(this.generateOrderNumber(""));
          originalMaterialProcessingMapper.insert(originalMaterialProcessingDO);
          OriginalMaterialProcessingRespVO bean = BeanUtils.toBean(originalMaterialProcessingDO, OriginalMaterialProcessingRespVO.class);
          //批量插入来料加工订单明细
          if (createReqVO.getDetails() != null && !createReqVO.getDetails().isEmpty()) {
              createReqVO.getDetails().forEach(entrustOrderDetail -> entrustOrderDetail.setOrderId(originalMaterialProcessingDO.getId()));
              List<OriginalMaterialProcessingDetailRespVO> originalMaterialProcessingDetailRespVOS = originalMaterialProcessingDetailService.insertBatchSomeColumn(createReqVO.getDetails());
              bean.setDetails(originalMaterialProcessingDetailRespVOS);
          }
          respVOS.add(bean);
      });
      return  respVOS;
    }

    private String generateOrderNumber(String materialType) {
        return sequenceApi.getNextSequence("ENTRUST_ORDER_NUMBER", null, null).getData();
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateOriginalMaterialProcessing(OriginalMaterialProcessingSaveReqVO updateReqVO) {
        // 校验存在
        validateEntrustOrderOrderExists(updateReqVO.getId());
        // 更新
        OriginalMaterialProcessingDO updateObj = BeanUtils.toBean(updateReqVO, OriginalMaterialProcessingDO.class);
        originalMaterialProcessingMapper.updateById(updateObj);
        if (updateReqVO.getDetails() != null && !updateReqVO.getDetails().isEmpty()) {
            //如果明细ID为空(表示新增)，则设置订单ID
            updateReqVO.getDetails().forEach(item -> {
                if (item.getId() == null) {
                    item.setOrderId(updateReqVO.getId());
                }
            });
            originalMaterialProcessingDetailService.updateBatchSomeColumn(updateReqVO.getDetails());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteOriginalMaterialProcessing(Long id) {
        // 校验存在
        validateEntrustOrderOrderExists(id);
        // 删除
        originalMaterialProcessingMapper.deleteById(id);
        // 删除委托加工订单明细
        originalMaterialProcessingDetailService.deleteOriginalMaterialProcessingDetailByOrderIds(List.of(id));

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteOriginalMaterialProcessingListByIds(List<Long> ids) {
        // 校验存在
        validateEntrustOrderOrderExists(ids);
        // 删除
        originalMaterialProcessingMapper.deleteByIds(ids);
        // 删除委托加工订单明细
        originalMaterialProcessingDetailService.deleteOriginalMaterialProcessingDetailByOrderIds(ids);
    }

    private void validateEntrustOrderOrderExists(List<Long> ids) {
        List<OriginalMaterialProcessingDO> list = originalMaterialProcessingMapper.selectByIds(ids);
        if (CollUtil.isEmpty(list) || list.size() != ids.size()) {
            throw exception(ENTRUST_ORDER_NOT_EXISTS);
        }
    }

    private void validateEntrustOrderOrderExists(Long id) {
        if (originalMaterialProcessingMapper.selectById(id) == null) {
            throw exception(ENTRUST_ORDER_NOT_EXISTS);
        }
    }

    @Override
    public OriginalMaterialProcessingDO getOriginalMaterialProcessing(Long id) {

        return originalMaterialProcessingMapper.selectById(id);
    }

    @Override
    public PageResult<OriginalMaterialProcessingDO> getOriginalMaterialProcessingPage(OriginalMaterialProcessingPageReqVO pageReqVO) {
        return originalMaterialProcessingMapper.selectPage(pageReqVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean linkOrder(LinkOrderReqVO req) {
        SystemRelativityDO saveDO = new SystemRelativityDO();
        saveDO.setStatus(DictEnum.BSE_SYS_REL_TP_ORDER.getCode());
        saveDO.setUpId(req.getUpOrderId());
        saveDO.setDownId(req.getDownOrderId());
        //判断订单有没有关联过
        if (systemRelativityMapper.selectCount(new LambdaQueryWrapper<SystemRelativityDO>().eq(SystemRelativityDO::getUpId, saveDO.getUpId()).eq(SystemRelativityDO::getDownId, saveDO.getDownId())) > 0) {
            throw exception(CONTRACT_ORDER_EXISTS);
        }
        return systemRelativityMapper.insert(saveDO) > 0;
    }

    @Override
    public List<DownOrUpOrderRespVO> getOrderByOrderIdAndType(DownOrUpOrderReqVO reqVO) {
        OriginalMaterialProcessingDO originalMaterialProcessingDO = originalMaterialProcessingMapper.selectById(reqVO.getOrderId());
        if (originalMaterialProcessingDO == null) {
            throw exception(ORIGINAL_MATERIAL_PROCESSING_DO_NOT_EXISTS);
        }
        String contractNumber = originalMaterialProcessingDO.getContractNumber();// 合同号
        ContractRespVO contractRespVO = contractService.getBySystemContractNumber(contractNumber);

        ContractRespVO upRelation = null;
        if ("up".equals(reqVO.getOrderType())) {
            log.info("获取上游订单");
            //上游
            upRelation = contractService.getUpRelation(contractRespVO.getId());
        } else {
            //下游
            log.info("获取下游订单");
            upRelation = contractService.getDownRelation(contractRespVO.getId());
        }
        List<DownOrUpOrderRespVO> orderList = new ArrayList<>();
        if (upRelation != null) {
            String systemContractNumber = upRelation.getSystemContractNumber();

            List<OriginalMaterialProcessingDO> originalMaterialProcessingDOS = originalMaterialProcessingMapper.selectList(new LambdaQueryWrapper<OriginalMaterialProcessingDO>().eq(OriginalMaterialProcessingDO::getContractNumber, systemContractNumber));
            originalMaterialProcessingDOS.forEach(p -> {
                        DownOrUpOrderRespVO downOrUpOrderRespVO = new DownOrUpOrderRespVO();
                        downOrUpOrderRespVO.setOrderId(String.valueOf(p.getId()));
                        downOrUpOrderRespVO.setOrderNo(p.getSystemOrderNumber());
                        downOrUpOrderRespVO.setOrderType(reqVO.getOrderType());
                        downOrUpOrderRespVO.setContractId(String.valueOf(p.getId()));
                        downOrUpOrderRespVO.setContractName(p.getContractName());
                        downOrUpOrderRespVO.setContractNumber(p.getContractNumber());
                        downOrUpOrderRespVO.setOrder(BeanUtils.toBean(p, PurchaseOrderRespVO.class));
                        orderList.add(downOrUpOrderRespVO);
                    }
            );

        }
        return orderList;
    }

    @Override
    public List<OriginalMaterialProcessingRespVO> getBindOrderByOrder(DownOrUpOrderReqVO reqVO) {
        List<OriginalMaterialProcessingRespVO> orderList = new ArrayList<>();
        if ("up".equals(reqVO.getOrderType())) {
            log.info("获取上游订单");
            //上游
            List<SystemRelativityDO> systemRelativityDOS = systemRelativityMapper.selectList(new LambdaQueryWrapper<SystemRelativityDO>().eq(SystemRelativityDO::getDownId, reqVO.getOrderId()));
            if (!systemRelativityDOS.isEmpty()) {
                List<OriginalMaterialProcessingDO> originalMaterialProcessingDOS = originalMaterialProcessingMapper.selectByIds(systemRelativityDOS.stream().map(SystemRelativityDO::getUpId).toList());
                orderList = BeanUtils.toBean(originalMaterialProcessingDOS, OriginalMaterialProcessingRespVO.class);
            }
        } else {
            //下游
            log.info("获取下游订单");
            List<SystemRelativityDO> systemRelativityDOS = systemRelativityMapper.selectList(new LambdaQueryWrapper<SystemRelativityDO>().eq(SystemRelativityDO::getUpId, reqVO.getOrderId()));
            if (!systemRelativityDOS.isEmpty()) {
                List<OriginalMaterialProcessingDO> originalMaterialProcessingDOS = originalMaterialProcessingMapper.selectByIds(systemRelativityDOS.stream().map(SystemRelativityDO::getDownId).toList());
                orderList = BeanUtils.toBean(originalMaterialProcessingDOS, OriginalMaterialProcessingRespVO.class);
            }
        }
        return orderList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void closeOrder(List<Long> ids) {
        originalMaterialProcessingMapper.update(new LambdaUpdateWrapper<OriginalMaterialProcessingDO>()
                .set(OriginalMaterialProcessingDO::getStatus, OrderStatusEnum.CLOSED.getCode())
                .in(OriginalMaterialProcessingDO::getId, ids));
    }

    @Override
    public  List<OriginalMaterialProcessingDetailRespVO>  getOriginalMaterialProcessingDetailListByOrderId(Long id) {
        return originalMaterialProcessingDetailService.getOriginalMaterialProcessingDetailListByOrderId(id);
    }

    @Override
    public void submitToErp061(Long id) {

    }

}