package com.zt.plat.module.contractorder.api;

import cn.hutool.extra.spring.SpringUtil;
import com.zt.plat.framework.common.exception.ErrorCode;
import com.zt.plat.framework.common.pojo.CommonResult;
import com.zt.plat.framework.common.pojo.PageResult;
import com.zt.plat.framework.common.util.object.BeanUtils;
import com.zt.plat.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.zt.plat.module.contractorder.api.dto.order.*;
import com.zt.plat.module.contractorder.dal.dataobject.purchaseorder.PrchOrdDtlDO;
import com.zt.plat.module.contractorder.dal.dataobject.purchaseorder.PurchaseOrderDO;
import com.zt.plat.module.contractorder.dal.dataobject.salesorder.SalesOrderDO;
import com.zt.plat.module.contractorder.dal.dataobject.salesorder.SalesOrderDetailDO;
import com.zt.plat.module.contractorder.dal.mysql.purchaseorder.PrchOrdDtlMapper;
import com.zt.plat.module.contractorder.dal.mysql.purchaseorder.PurchaseOrderMapper;
import com.zt.plat.module.contractorder.dal.mysql.salesorder.SalesOrderDetailMapper;
import com.zt.plat.module.contractorder.dal.mysql.salesorder.SalesOrderMapper;
import com.zt.plat.module.contractorder.service.purchaseorder.PurchaseOrderService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.zt.plat.framework.common.pojo.CommonResult.success;

@RestController
@Validated
@Slf4j
public class OrderApiImpl implements OrderApi {
    @Resource
    private PurchaseOrderService purchaseOrderService;

    @Override
    public CommonResult<List<OrderDTO>> getOrderByOrderIds(List<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            throw new RuntimeException("订单id为空");
        }
        List<PurchaseOrderDO> ordersByIds = purchaseOrderService.getOrdersByIds(ids.stream().map(String::valueOf).toList());
        List<Long> purchaseOrderIds = new ArrayList<>();
        List<Long> salesOrderIds = new ArrayList<>();
        List<OrderDTO> order = new ArrayList<>();
        if (ordersByIds.isEmpty()) {
            return CommonResult.success(new ArrayList<>());
        }
        ordersByIds.forEach(o -> {
            if ("SALE".equals(o.getSplyBsnTp())) {
                // 销售订单
                salesOrderIds.add(o.getId());
            } else {
                // 非销售订单（采购订单）
                purchaseOrderIds.add(o.getId());
            }
        });
        if (!purchaseOrderIds.isEmpty()) {
            order.addAll(getPoOrdByIds(purchaseOrderIds));
        }
        if (!salesOrderIds.isEmpty()) {
            order.addAll(getSalesOrdByIds(salesOrderIds));
        }
        return success(order);
    }

    @Override
    public CommonResult<List<OrderDTO>> getOrderByOrderNos(List<String> orderNoS) {
        List<PurchaseOrderDO> orderByNos = purchaseOrderService.getOrderByNos(orderNoS);
        if (orderByNos.isEmpty()) {
            return success(new ArrayList<>());
        }
        List<OrderDTO> order = new ArrayList<>();
        List<Long> purchaseOrderNoS = new ArrayList<>();
        List<Long> salesOrdNoS = new ArrayList<>();
        orderByNos.forEach(f -> {
            if ("SALE".equals(f.getSplyBsnTp())) {
                // 销售订单
                salesOrdNoS.add(f.getId());
            } else if ("PUR".equals(f.getSplyBsnTp())) {
                // 非销售订单（采购订单）
                purchaseOrderNoS.add(f.getId());
            }
        });
        if (!purchaseOrderNoS.isEmpty()) {
            order.addAll(getPoOrdByIds(purchaseOrderNoS));
        }
        if (!salesOrdNoS.isEmpty()) {
            order.addAll(getSalesOrdByIds(salesOrdNoS));
        }

        return success(order);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<Boolean> updateOrderLstQty(List<UpdateOrderLstQtyDTO> updateOrderLstQtyDTOS) {
        if (updateOrderLstQtyDTOS == null || updateOrderLstQtyDTOS.isEmpty()) {
            throw new RuntimeException("请求数据错误");
        }
        SalesOrderDetailMapper salesOrderDetailMapper = SpringUtil.getBean(SalesOrderDetailMapper.class);
        PrchOrdDtlMapper prchOrdDtlMapper = SpringUtil.getBean(PrchOrdDtlMapper.class);
        updateOrderLstQtyDTOS.forEach(f -> {
            if ("SALE".equals(f.getSplyBsnTp())) {
                SalesOrderDetailDO salesOrderDetailDO = salesOrderDetailMapper.selectById(f.getOrderDetailId());
                // 处理 trfQty 可能为 null 的情况，默认值 0
                BigDecimal lstQty = Optional.ofNullable(salesOrderDetailDO.getTrfQty())
                        .orElse(BigDecimal.ZERO);
                SalesOrderDetailDO updateDO = new SalesOrderDetailDO();
                updateDO.setId(f.getOrderDetailId()); // 给更新对象设 ID
                updateDO.setTrfQty(lstQty.add(f.getLstQty())); // 累加（trfQty ） 对应采购的lstQty(已收货量)字段
                log.info("更新销售订单明细：{}", updateDO);
                salesOrderDetailMapper.updateById(updateDO);
            } else if ("PUR".equals(f.getSplyBsnTp())) {
                // 采购
                PrchOrdDtlDO prchOrdDtlDO = prchOrdDtlMapper.selectById(f.getOrderDetailId());
                BigDecimal lstQty = Optional.ofNullable(prchOrdDtlDO.getLstQty())
                        .orElse(BigDecimal.ZERO);
                PrchOrdDtlDO updateDO = new PrchOrdDtlDO();
                updateDO.setId(f.getOrderDetailId());
                updateDO.setLstQty(lstQty.add(f.getLstQty()));
                log.info("更新销售订单明细：{}", updateDO);
                prchOrdDtlMapper.updateById(updateDO);
            } else {
                throw new RuntimeException("请求数据错误");
            }
        });
        return success(true);
    }

    @Override
    public CommonResult<Boolean> voidOrderLstQty(List<UpdateOrderLstQtyDTO> updateOrderLstQtyDTOS) {
        if (updateOrderLstQtyDTOS == null || updateOrderLstQtyDTOS.isEmpty()) {
            throw new RuntimeException("请求数据错误");
        }
        SalesOrderDetailMapper salesOrderDetailMapper = SpringUtil.getBean(SalesOrderDetailMapper.class);
        PrchOrdDtlMapper prchOrdDtlMapper = SpringUtil.getBean(PrchOrdDtlMapper.class);
        updateOrderLstQtyDTOS.forEach(f -> {
            if ("SALE".equals(f.getSplyBsnTp())) {
                SalesOrderDetailDO salesOrderDetailDO = salesOrderDetailMapper.selectById(f.getOrderDetailId());
                // 处理 trfQty 可能为 null 的情况，默认值 0
                BigDecimal lstQty = Optional.ofNullable(salesOrderDetailDO.getTrfQty())
                        .orElse(BigDecimal.ZERO);
                if (lstQty.equals(BigDecimal.ZERO)) {
                    throw exception(new ErrorCode(1_008_00_609, "积累量不能等于0"));
                }
                SalesOrderDetailDO updateDO = new SalesOrderDetailDO();
                updateDO.setId(f.getOrderDetailId()); // 给更新对象设 ID
                updateDO.setTrfQty(lstQty.subtract(f.getLstQty())); // 减法
                log.info("更新销售订单明细：{}", updateDO);
                salesOrderDetailMapper.updateById(updateDO);
            } else if ("PUR".equals(f.getSplyBsnTp())) {
                // 采购
                PrchOrdDtlDO prchOrdDtlDO = prchOrdDtlMapper.selectById(f.getOrderDetailId());
                BigDecimal lstQty = Optional.ofNullable(prchOrdDtlDO.getLstQty())
                        .orElse(BigDecimal.ZERO);
                if (lstQty.equals(BigDecimal.ZERO)) {
                    throw exception(new ErrorCode(1_008_00_609, "积累量不能等于0"));
                }
                PrchOrdDtlDO updateDO = new PrchOrdDtlDO();
                updateDO.setId(f.getOrderDetailId());
                updateDO.setLstQty(lstQty.subtract(f.getLstQty()));
                log.info("更新销售订单明细：{}", updateDO);
                prchOrdDtlMapper.updateById(updateDO);
            } else {
                throw new RuntimeException("请求数据错误");
            }
        });
        return success(true);
    }

    @Override
    public CommonResult<List<SalesOrdDtlDTO>> getSalesOrderDetailsByIds(List<Long> ids) {
        List<SalesOrderDetailDO> salesOrderDetailDOS = SpringUtil.getBean(SalesOrderDetailMapper.class).selectList(
                new LambdaQueryWrapperX<SalesOrderDetailDO>()
                        .in(SalesOrderDetailDO::getId, ids)
                        .eq(SalesOrderDetailDO::getIsEnable, '1')
        );
        return success(BeanUtils.toBean(salesOrderDetailDOS, SalesOrdDtlDTO.class));
    }

    @Override
    public CommonResult<SalesOrdDtlDTO> getSalesOrderDetailsById(Long id) {
        SalesOrderDetailDO salesOrderDetailDOS = SpringUtil.getBean(SalesOrderDetailMapper.class).selectOne(
                new LambdaQueryWrapperX<SalesOrderDetailDO>()
                        .eq(SalesOrderDetailDO::getId, id)
                        .eq(SalesOrderDetailDO::getIsEnable, '1')
        );
        return success(BeanUtils.toBean(salesOrderDetailDOS, SalesOrdDtlDTO.class));
    }

    @Override
    public CommonResult<PageResult<OrderDTO>> queryOrderPlanData(OrderAndPlanDataReqDTO reqVO) {
        PageResult<PurchaseOrderDO> pageResult = purchaseOrderService.queryOrderAndPlanData(reqVO);
        List<OrderDTO> bean = BeanUtils.toBean(pageResult.getList(), OrderDTO.class);
        return success(new PageResult<>(bean, pageResult.getTotal()));
    }

    private List<SalesOrderDO> getOrderByIds(List<Long> ids) {
        return SpringUtil.getBean(SalesOrderMapper.class).selectList(SalesOrderDO::getId, ids); // 采购订单与销售订单的
    }

    private List<OrderDTO> getPoOrdByIds(List<Long> ids) {
        List<SalesOrderDO> purchaseOrderDOS = getOrderByIds(ids);
        List<OrderDTO> orderDTOS = BeanUtils.toBean(purchaseOrderDOS, OrderDTO.class);
        if (orderDTOS == null) {
            return new ArrayList<>();
        }
        PrchOrdDtlMapper prchOrdDtlMapper = SpringUtil.getBean(PrchOrdDtlMapper.class);
        List<Long> orderIds = orderDTOS.stream().map(OrderDTO::getId).toList();
        List<PrchOrdDtlDO> prchOrdDtlDOS = prchOrdDtlMapper.selectList(
                new LambdaQueryWrapperX<PrchOrdDtlDO>()
                        .in(PrchOrdDtlDO::getOrdId, orderIds)
                        .eq(PrchOrdDtlDO::getIsEnb, '1')
        );
        orderDTOS.forEach(o -> {
            List<OrdDtlDTO> ordDtlDTOS = new ArrayList<>();
            prchOrdDtlDOS.forEach(p -> {

                if (Objects.equals(o.getId(), p.getOrdId())) {
                    OrdDtlDTO ordDtlDTO = setOrderDtlDTO(o, p);
                    ordDtlDTOS.add(ordDtlDTO);
                }
            });
            o.setOrdDtlDTOS(ordDtlDTOS);
        });
        return orderDTOS;
    }

    private List<OrderDTO> getSalesOrdByIds(List<Long> ids) {
        List<SalesOrderDO> salesOrderDOS = getOrderByIds(ids);
        List<OrderDTO> orderDTOS = BeanUtils.toBean(salesOrderDOS, OrderDTO.class);
        if (orderDTOS == null) {
            return new ArrayList<>();
        }
        SalesOrderDetailMapper salesOrderDetailMapper = SpringUtil.getBean(SalesOrderDetailMapper.class);
        List<Long> orderIds = orderDTOS.stream().map(OrderDTO::getId).toList();
        List<SalesOrderDetailDO> salesOrderDetailDOS = salesOrderDetailMapper.selectList(
                new LambdaQueryWrapperX<SalesOrderDetailDO>()
                        .in(SalesOrderDetailDO::getOrderId, orderIds)
                        .eq(SalesOrderDetailDO::getIsEnable, '1')
        );
        orderDTOS.forEach(o -> {
            List<OrdDtlDTO> salesOrdDtlDTOS = new ArrayList<>();
            salesOrderDetailDOS.forEach(s -> {
                if (Objects.equals(o.getId(), s.getOrderId())) {
                    OrdDtlDTO ordDtlDTO = setOrderDtlDTO(o, s);
                    salesOrdDtlDTOS.add(ordDtlDTO);
                }
            });
            o.setOrdDtlDTOS(salesOrdDtlDTOS);
        });
        return orderDTOS;
    }

    private <T> OrdDtlDTO setOrderDtlDTO(OrderDTO orderDTO, T t) {
        OrdDtlDTO ordDtlDTO = new OrdDtlDTO();
        if (t instanceof PrchOrdDtlDO p) {
            ordDtlDTO.setId(p.getId());
            ordDtlDTO.setOrderId(p.getOrdId());
            ordDtlDTO.setLineNum(p.getLineNum());
            ordDtlDTO.setMtrlName(p.getMtrlName());
            ordDtlDTO.setMtrlNum(p.getMtrlNum());
            ordDtlDTO.setFactoryName(p.getRcvFactName());
            ordDtlDTO.setFactoryNum(p.getRcvFactNum());
            ordDtlDTO.setWarehouseName(p.getRcvWrhName());
            ordDtlDTO.setWarehouseNum(p.getRcvWrhNum());
            ordDtlDTO.setUnit(p.getUnt());
            ordDtlDTO.setQuantity(p.getQty());
            ordDtlDTO.setProjectCategory(p.getPrjCtgr());
            ordDtlDTO.setAgreementNumber(p.getAgrNum());
            ordDtlDTO.setElementAbbreviation(p.getElemAbbr());
            ordDtlDTO.setElementName(p.getElemName());
            ordDtlDTO.setElementCode(p.getElemCdg());
            ordDtlDTO.setIsEnable(p.getIsEnb());
            ordDtlDTO.setTaxNum(p.getTaxNum());
            ordDtlDTO.setTaxRte(p.getTaxRte());
            //==============================
            ordDtlDTO.setMtrlCpntNum(p.getMtrlCpntNum());
            ordDtlDTO.setMtrlCpntDsp(p.getMtrlCpntDsp());
            ordDtlDTO.setBgnDt(p.getBgnDt());
            ordDtlDTO.setDdlDt(p.getDdlDt());
            ordDtlDTO.setTrfFactName(p.getTrfFactName());
            ordDtlDTO.setTrfFactNum(p.getTrfFactNum());
            ordDtlDTO.setTrfWrhName(p.getTrfWrhName());
            ordDtlDTO.setTrfWrhNum(p.getTrfWrhNum());
            ordDtlDTO.setRmk(p.getRmk());
            ordDtlDTO.setLstQty(p.getLstQty());
            if ("PO04".equals(orderDTO.getType())) {
                ordDtlDTO.setMtrlName(orderDTO.getMaterialName());
                ordDtlDTO.setMtrlNum(orderDTO.getMaterialNumber()); // 没单位了
            }

        } else if (
                t instanceof SalesOrderDetailDO s
        ) {
            ordDtlDTO.setId(s.getId());
            ordDtlDTO.setOrderId(s.getOrderId());
            ordDtlDTO.setLineNum(s.getLineNumber());
            ordDtlDTO.setMtrlName(s.getMaterialName());
            ordDtlDTO.setMtrlNum(s.getMaterialNumber());
            ordDtlDTO.setFactoryName(s.getFactoryName());
            ordDtlDTO.setFactoryNum(s.getFactoryNumber());
            ordDtlDTO.setWarehouseName(s.getWarehouseName());
            ordDtlDTO.setWarehouseNum(s.getWarehouseNumber());
            ordDtlDTO.setUnit(s.getUnt());
            ordDtlDTO.setQuantity(s.getQuantity());
            ordDtlDTO.setProjectCategory(s.getProjectCategory());
            ordDtlDTO.setAgreementNumber(s.getAgreementNumber());
            ordDtlDTO.setElementAbbreviation(s.getElementAbbreviation());
            ordDtlDTO.setElementName(s.getElementName());
            ordDtlDTO.setElementCode(s.getElementNumber());
            ordDtlDTO.setIsEnable(s.getIsEnable());
            ordDtlDTO.setTaxNum(s.getTaxAcctasscat());
            ordDtlDTO.setLstQty(s.getTrfQty());
            ordDtlDTO.setRmk(s.getRemark());
            ordDtlDTO.setTaxRte(s.getTaxRte());
            ordDtlDTO.setInTaxUprc(s.getInTaxUnitPrice());
        }
        return ordDtlDTO;
    }
}
