package com.wms_main.service.controller.serviceImpl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wms_main.constant.enums.wms.*;
import com.wms_main.dao.ITAppLocationService;
import com.wms_main.dao.ITAppOrderInService;
import com.wms_main.dao.ITAppOrderOutService;
import com.wms_main.dao.ITAppStockService;
import com.wms_main.model.bo.erp.ErpGoodsDetail;
import com.wms_main.model.bo.erp.ErpVehicleNoResp;
import com.wms_main.model.dto.request.ycwms.*;
import com.wms_main.model.dto.response.ycwms.YcwmsResponse;
import com.wms_main.model.po.TAppLocation;
import com.wms_main.model.po.TAppOrderIn;
import com.wms_main.model.po.TAppOrderOut;
import com.wms_main.model.po.TAppStock;
import com.wms_main.repository.utils.ConvertUtils;
import com.wms_main.repository.utils.StringUtils;
import com.wms_main.repository.utils.UUIDUtils;
import com.wms_main.service.api.IExternalApiService;
import com.wms_main.service.controller.IYcwmsControllerService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;

@Service
@Slf4j
@RequiredArgsConstructor
public class YcwmsControllerServiceImpl implements IYcwmsControllerService {

    private final ITAppOrderInService appOrderInService;
    private final ITAppOrderOutService appOrderOutService;
    private final ITAppStockService appStockService;
    private final ITAppLocationService appLocationService;
    private final IExternalApiService externalApiService;

    @Override
    public YcwmsResponse<Object> orderIn(OrderInReq request) {
        log.info("入库单请求参数{}", JSON.toJSON(request));
        if(request == null) return YcwmsResponse.error("参数错误", null);
        if(StringUtils.isEmpty(request.getOrderId())
                || StringUtils.isEmpty(request.getVehicleNo()) || StringUtils.isEmpty(request.getVehicleSize())
                || StringUtils.isEmpty(request.getInStand()) || request.getGoodsDetail() == null || request.getGoodsDetail().isEmpty()) {
            return YcwmsResponse.error("参数错误", null);
        }
        // 校验是否存在相同的入库单
        List<TAppOrderIn> withOrderId = appOrderInService.getWithOrderId(request.getOrderId());
        if(withOrderId == null) {
            return YcwmsResponse.error("数据服务异常，请稍后重试", null);
        }
        if(!withOrderId.isEmpty()) {
            return YcwmsResponse.error("入库单已存在，请勿重复推送", null);
        }
        String vehicleNo = request.getVehicleNo();
        String inStand = ConvertUtils.convertPointToDestination(request.getInStand());
        List<ErpGoodsDetail> erpGoodsDetails = new ArrayList<>();
        try {
            YcwmsResponse<ErpVehicleNoResp> erpResp = externalApiService.getVehicleNoData(vehicleNo);
            if (erpResp != null && WmsApiResponseCodeEnums.SUCCESS.getCode() == erpResp.getCode() && !erpResp.getReturnData().getGoodsDetail().isEmpty()) {
                erpGoodsDetails = erpResp.getReturnData().getGoodsDetail();
            } else {
                log.warn("获取载具[{}]数据失败，响应：{}", vehicleNo, erpResp);
            }
        } catch (Exception e) {
            log.error("处理载具[{}]数据时发生异常：", vehicleNo, e);
        }
        List<OrderInGoodsDetail> mesGoodsDetails = request.getGoodsDetail();
        if (request.getOrderId().contains("baokai")) {
            mesGoodsDetails.clear();
        }
        // 对比inTasks和goodsDetails
        Iterator<OrderInGoodsDetail> iterator = mesGoodsDetails.iterator();
        while (iterator.hasNext()) {
            OrderInGoodsDetail goodsDetail = iterator.next();
//            boolean matchFound = erpGoodsDetails.stream().anyMatch(erpGoodsDetail ->
//                    erpGoodsDetail.getGoodsId().equals(goodsDetail.getGoodsId()) &&
//                    erpGoodsDetail.getGoodsBarcode().equals(goodsDetail.getGoodsBarcode()) &&
//                    Objects.equals(erpGoodsDetail.getQuantity(), goodsDetail.getQuantity()) &&
//                    erpGoodsDetail.getGoodsType().equals(goodsDetail.getGoodsType()) &&
//                    Objects.equals(erpGoodsDetail.getSpecification(), goodsDetail.getSpecification())
//            );
            boolean matchFound = erpGoodsDetails.stream().anyMatch(erpGoodsDetail ->
                    erpGoodsDetail.getGoodsId().equals(goodsDetail.getGoodsId()) &&
                            Objects.equals(erpGoodsDetail.getQuantity(), goodsDetail.getQuantity()) &&
                            erpGoodsDetail.getGoodsType().equals(goodsDetail.getGoodsType()));
            if (matchFound) {
                // 找到匹配的任务，删除该 goodsDetail
                iterator.remove();
            }
        }
        if (!mesGoodsDetails.isEmpty()) {
            return YcwmsResponse.error("MES与ERP校验失败", null);
        }
        List<TAppOrderIn> orderInList = new ArrayList<>();
        for (ErpGoodsDetail goodsDetail : erpGoodsDetails) {
            if(goodsDetail == null || StringUtils.isEmpty(goodsDetail.getGoodsId()) || goodsDetail.getQuantity() == null) {
                return YcwmsResponse.error("参数错误", null);
            }
            TAppOrderIn orderIn = new TAppOrderIn();
            orderIn.setRecordId(UUIDUtils.getNewUUID());
            orderIn.setOrderId(request.getOrderId());
            orderIn.setCompareId(request.getOrderId() + goodsDetail.getGoodsBarcode());
            orderIn.setVehicleNo(request.getVehicleNo());
            orderIn.setVehicleSize(request.getVehicleSize());
            orderIn.setInStand(inStand);
            orderIn.setClientId(request.getClientId());
            orderIn.setGoodsId(goodsDetail.getGoodsId());
            orderIn.setGoodsName(goodsDetail.getGoodsName());
            orderIn.setBatch(goodsDetail.getBatch());
            orderIn.setGoodsType(goodsDetail.getGoodsType());
            orderIn.setSpecification(goodsDetail.getSpecification());
            orderIn.setQuantity(goodsDetail.getQuantity());
            orderIn.setGoodsDesc(goodsDetail.getGoodsDesc());
            orderIn.setGoodsBarcode(goodsDetail.getGoodsBarcode());
            orderIn.setOrderStatus(OrderStatusEnum.CREATE.getCode());
            orderIn.setXsfbillno(goodsDetail.getXsfbillno());
            orderIn.setXsfseq(goodsDetail.getXsfseq());
            orderIn.setNeibubianhao(goodsDetail.getNeibubianhao());
            orderIn.setCreateTime(LocalDateTime.now());
            orderIn.setUpdateTime(LocalDateTime.now());
            orderInList.add(orderIn);
        }
        if(!appOrderInService.saveBatch(orderInList)) {
            return YcwmsResponse.error("入库单保存失败，请稍后再试", null);
        }
        return YcwmsResponse.success();
    }

    @Override
    public YcwmsResponse<Object> orderOut(OrderOutReq request) {
        log.info("亚驰出库单请求参数{}", JSON.toJSON(request));
        if(request == null) return YcwmsResponse.error("参数错误", null);
        if(StringUtils.isEmpty(request.getOrderId()) || request.getQuantity() == null
                || (StringUtils.isEmpty(request.getGoodsId()) || request.getBatch() == null || request.getSpecification() == null || request.getClientId() == null)) {
            return YcwmsResponse.error("参数错误", null);
        }
        List<TAppOrderOut> orderOutCheckList = appOrderOutService.getWithOrderId(request.getOrderId());
        if(orderOutCheckList == null) {
            return YcwmsResponse.error("数据服务异常，请稍后重试", null);
        }
        if(!orderOutCheckList.isEmpty()) {
            return YcwmsResponse.error("出库单已存在，请勿重复推送", null);
        }
        TAppOrderOut orderOut = new TAppOrderOut();
        orderOut.setRecordId(UUIDUtils.getNewUUID());
        orderOut.setOrderId(request.getOrderId());
        orderOut.setGoodsId(request.getGoodsId());
        orderOut.setBatch(request.getBatch());
        orderOut.setSpecification(request.getSpecification());
        orderOut.setQuantity(request.getQuantity());
        orderOut.setOrderStatus(OrderStatusEnum.CREATE.getCode());
        orderOut.setCreateTime(LocalDateTime.now());
        orderOut.setUpdateTime(LocalDateTime.now());
        orderOut.setRemark(request.getClientId());
        if(!appOrderOutService.save(orderOut)) {
            return YcwmsResponse.error("出库单保存失败，请稍后再试", null);
        }
        return YcwmsResponse.success(getLocByGoodsId(request.getGoodsId()));
    }

    @Override
    public YcwmsResponse<List<StockResp>> stock(StockReq request) {
        log.info("亚驰库存请求参数{}", JSON.toJSON(request));
        if(request == null) return YcwmsResponse.error("参数错误", null);
        // stocks: 请求库存的当前库存
        List<TAppStock> stocks = null;
        if(request.empty()) {
            stocks = appStockService.list();
        } else {
            TAppStock queryEntity = new TAppStock();
            queryEntity.setGoodsId(request.getGoodsId());
            queryEntity.setLocationId(request.getLocation());
            queryEntity.setSled(request.getSpecification());
            queryEntity.setVehicleId(request.getVehicleNo());
            stocks = appStockService.getWithEntity(queryEntity);
        }
        if(stocks == null) {
            return YcwmsResponse.error("数据服务异常，请稍后重试", null);
        }
        List<StockResp> respList = new ArrayList<>();
        // locations: 当前库存的对应库位
        List<String> locations = stocks.stream().map(TAppStock::getLocationId).distinct().toList();
        // 检查每个库存的库位location
        for (var location : locations) {
            // 库存反馈
            StockResp stockResp = new StockResp();
            // 查询location库位上当前有多少库存locationStocks
            List<TAppStock> locationStocks = stocks.stream().filter(stock -> stock.getLocationId().equals(location)).toList();
            if(locationStocks.isEmpty()) {
                continue;
            }
            stockResp.setVehicleNo(locationStocks.getFirst().getVehicleId());
            stockResp.setLocation(location);
            List<StockRespGoodsDetail> goodsDetails = new ArrayList<>();
            for (var stock : locationStocks) {
                StockRespGoodsDetail goodsDetail = new StockRespGoodsDetail();
                goodsDetail.setGoodsId(stock.getGoodsId());
                goodsDetail.setGoodsName(stock.getGoodsDesc());
                goodsDetail.setSpecification(stock.getSled());
                goodsDetail.setQuantity(stock.getTotalNum());
                goodsDetail.setGoodsDesc(stock.getGoodsDesc());
                goodsDetail.setStoreTime(stock.getFirstInTime());
                goodsDetail.setBatch(stock.getBatch());
                goodsDetail.setGoodsType(stock.getGoodsType());
                goodsDetail.setGoodsBarCode(stock.getGoodsBarCode());
                goodsDetail.setXsfbillno(stock.getXsfbillno());
                goodsDetail.setXsfseq(stock.getXsfseq());
                goodsDetail.setNeibubianhao(stock.getNeibubianhao());
                goodsDetails.add(goodsDetail);
            }
            stockResp.setGoodsDetail(goodsDetails);
            respList.add(stockResp);
        }
        return YcwmsResponse.success(respList);
    }

    public YcwmsResponse<Object> getAvailPercent(String equipmentId) {
        if (equipmentId == null || equipmentId.isEmpty()) {
            return YcwmsResponse.error("参数错误", null);
        }
        if (equipmentId.equals("3")) {
            Integer queryId = Integer.parseInt(equipmentId);
            Long locationNum500 = appLocationService.count(
                    new LambdaQueryWrapper<TAppLocation>()
                            .eq(TAppLocation::getEquipmentId, queryId)
                            .eq(TAppLocation::getLocationType, WmsLocationTypeEnums.TYPE_500.getCode())
                            .eq(TAppLocation::getIsOccupy, WmsLocationOccupyStatusEnums.OCCUPY.getCode())
            );
            Long locationNum600 = appLocationService.count(
                    new LambdaQueryWrapper<TAppLocation>()
                            .eq(TAppLocation::getEquipmentId, queryId)
                            .eq(TAppLocation::getLocationType, WmsLocationTypeEnums.TYPE_600.getCode())
                            .eq(TAppLocation::getIsOccupy, WmsLocationOccupyStatusEnums.OCCUPY.getCode())
            );
            Long locationNum = locationNum500 + locationNum600;
            Double percent = Double.parseDouble(locationNum.toString()) / WmsLocationNumEnums.LOCATION_NUM_3.getCode();
            return YcwmsResponse.success(percent);
        } else if (equipmentId.equals("2")) {
            Integer queryId = Integer.parseInt(equipmentId);
            Long locationNum = appLocationService.count(
                    new LambdaQueryWrapper<TAppLocation>()
                            .eq(TAppLocation::getEquipmentId, queryId)
                            .eq(TAppLocation::getLocationType, WmsLocationTypeEnums.TYPE_PRODUCT.getCode())
                            .eq(TAppLocation::getIsOccupy, WmsLocationOccupyStatusEnums.OCCUPY.getCode())
            );
            Double percent = Double.parseDouble(locationNum.toString()) / WmsLocationNumEnums.LOCATION_NUM_2.getCode();
            return YcwmsResponse.success(percent);
        } else if (equipmentId.equals("1")) {
            Integer queryId = Integer.parseInt(equipmentId);
            Long locationNum = appLocationService.count(
                    new LambdaQueryWrapper<TAppLocation>()
                            .eq(TAppLocation::getEquipmentId, queryId)
                            .eq(TAppLocation::getLocationType, WmsLocationTypeEnums.TYPE_PRODUCT.getCode())
                            .eq(TAppLocation::getIsOccupy, WmsLocationOccupyStatusEnums.OCCUPY.getCode())
            );
            Double percent = Double.parseDouble(locationNum.toString()) / WmsLocationNumEnums.LOCATION_NUM_1.getCode();
            return YcwmsResponse.success(percent);
        }
        return YcwmsResponse.error("equipmentId无效", null);
    }

    public YcwmsResponse<Object> localOrderOut(LocalOrderReq request) {
        log.info("亚驰单机出库单请求参数{}", JSON.toJSON(request));
        if(request == null) return YcwmsResponse.error("参数错误", null);
        if (StringUtils.isEmpty(request.getNeibubianhao())
                || StringUtils.isEmpty(request.getXsfbillno())
                || StringUtils.isEmpty(String.valueOf(request.getXsfseq()))
                || StringUtils.isEmpty(request.getSpecification())) {
            return YcwmsResponse.error("参数错误", null);
        }
        List<TAppStock> stocks = appStockService.list(
                new LambdaQueryWrapper<TAppStock>()
                        .eq(TAppStock::getNeibubianhao, request.getNeibubianhao())
                        .eq(TAppStock::getXsfbillno, request.getXsfbillno())
                        .eq(TAppStock::getXsfseq, request.getXsfseq())
                        .eq(TAppStock::getSled, request.getSpecification())
        );
        if (stocks == null || stocks.isEmpty()) {
            return YcwmsResponse.error("库存不足, 出库失败", null);
        }
        TAppOrderOut orderOut = new TAppOrderOut();
        orderOut.setRecordId(UUIDUtils.getNewUUID());
        orderOut.setOrderId(UUIDUtils.getNewUUID("baokai"));
        orderOut.setBatch(stocks.getFirst().getBatch());
        orderOut.setSpecification(request.getSpecification());
        orderOut.setOrderStatus(OrderStatusEnum.CREATE.getCode());
        orderOut.setCreateTime(LocalDateTime.now());
        orderOut.setUpdateTime(LocalDateTime.now());
        orderOut.setRemark("Local");

        String tmpGoodsId = stocks.getFirst().getGoodsId();
        if (tmpGoodsId.length() < 3) {
            orderOut.setGoodsId(tmpGoodsId);
            int tmpGoodsNum = Integer.parseInt(tmpGoodsId);
            orderOut.setQuantity((tmpGoodsNum <= 1) ? 1.0 : 4.0);
        } else {
            orderOut.setGoodsId(stocks.getFirst().getVehicleId());
            orderOut.setQuantity(0.0);
            tmpGoodsId = stocks.getFirst().getVehicleId();
        }
        if(!appOrderOutService.save(orderOut)) {
            return YcwmsResponse.error("出库单保存失败，请稍后再试", null);
        }
        return YcwmsResponse.success(getLocByGoodsId(tmpGoodsId));
    }

    public String getLocByGoodsId(String goodsId) {
        if (goodsId.length() < 3) {
            return switch (goodsId) {
                case "0" -> "LK-3";
                case "1" -> "LK-4";
                case "2" -> "LK-5";
                case "3" -> "LK-6";
                case "4" -> "LK-7";
                default -> "";
            };
        } else {
            List<TAppStock> stocks = appStockService.list(
                    new LambdaQueryWrapper<TAppStock>()
                            .eq(TAppStock::getVehicleId, goodsId)
            );
            return ConvertUtils.convertDestinationToPoint(stocks.getFirst().getBarCode());
        }
    }
}
