package com.youchain.businessdata.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.youchain.basicdata.domain.Item;
import com.youchain.basicdata.domain.Point;
import com.youchain.basicdata.domain.Stock;
import com.youchain.basicdata.service.ItemService;
import com.youchain.basicdata.service.PointService;
import com.youchain.basicdata.service.dto.ItemDto;
import com.youchain.businessdata.domain.*;
import com.youchain.businessdata.inputJson.*;
import com.youchain.businessdata.service.*;
import com.youchain.businessdata.service.dto.MoDto;
import com.youchain.businessdata.service.dto.OrderDto;
import com.youchain.exception.handler.ApiResult;
import com.youchain.modules.system.domain.Dept;
import com.youchain.modules.system.service.DeptService;
import com.youchain.modules.system.service.dto.DeptDto;
import com.youchain.utils.BizStatus;
import com.youchain.utils.HttpPostUtil;
import com.youchain.utils.StringUtils;
import com.youchain.utils.UrlApi;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Slf4j
public class MlsServiceImpl implements MlsService {
    private final OrderService orderService;
    private final ItemService itemService;
    private final DeptService deptService;
    private final MoService moService;
    private final TaskService taskService;
    private final PointService pointService;
    private final AgvTaskService agvTaskService;
    private final PickDetailService pickDetailService;
    private final InventoryService inventoryService;


    /**
     * 获取Token
     *
     * @return
     */
    @Override
    public String getToKen() {
        String toKen = "";
        String mlsUser = "WMS";
        String mlsPwd = "EDlsFOvn3xaJm*EH";
        JSONObject jsonObject = new JSONObject(new LinkedHashMap<>());
        Map<String, Object> objMap = new LinkedHashMap<>();
        objMap.put("mlsUser", mlsUser);//快码代码
        objMap.put("mlsPwd", mlsPwd);//快码值
        jsonObject.putAll(objMap);
        String resultJson = HttpPostUtil.sendPostReq(UrlApi.extSignIn, jsonObject.toString());//返回ResponseJson*/
        JSONObject resulObject = JSON.parseObject(resultJson);
        //判断接口是否成功
        if (resulObject == null) {
            throw new RuntimeException("获取toKen接口返回数据为空!");
        }

        String code = resulObject.getString("code") == null ? "" : resulObject.getString("code");
        String msg = resulObject.getString("msg") == null ? "" : resulObject.getString("msg");

        if ("0".equals(code)) {
            toKen = resulObject.getString("data") == null ? "" : resulObject.getString("data");
            return toKen;
        } else {
            throw new RuntimeException("MLS异常信息:" + msg);
        }
    }

    /**
     * 获取送货单JSON
     *
     * @return
     */
    @Override
    public String getOrderJson(OrderInfo orderInfo) {
        JSONObject jsonObject = new JSONObject(new LinkedHashMap<>());
        Map<String, Object> objMap = new LinkedHashMap<>();
        objMap.put("ifaceCode", orderInfo.getIfaceCode());//获取送货单信息
        objMap.put("sourceSystem", orderInfo.getSourceSystem());//来源系统
        objMap.put("params", orderInfo.getParams());
        jsonObject.putAll(objMap);
        return HttpPostUtil.sendPostReq(UrlApi.publicApi, jsonObject.toString(), this.getToKen());//返回ResponseJson*/
    }

    /**
     * 获取送货单信息
     *
     * @return
     */
    @Override
    public void getOrderInfo(String resultJson) {
        if (StringUtils.isEmpty(resultJson)) {
            throw new RuntimeException("获取送货单接口失败!");
        }

        JSONObject resulObject = JSON.parseObject(resultJson);
        if (resulObject == null) {
            throw new RuntimeException("获取送货单接口返回数据为空!");
        }
        String code = resulObject.getString("code") == null ? "" : resulObject.getString("code");
        String msg = resulObject.getString("msg") == null ? "" : resulObject.getString("msg");
        //判断接口是否成功
        if (!"0".equals(code)) {
            throw new RuntimeException("获取送货单接口异常信息:" + msg);
        }

        String data = resulObject.getString("data") == null ? "" : resulObject.getString("data");
        JSONObject dataObject = JSON.parseObject(data);
        if (dataObject == null) {
            throw new RuntimeException("获取送货单接口返回数据为空!");
        }
        JSONArray details = dataObject.getJSONArray("list");
        //判断是否有送货单数据
        if (details == null || details.size() == 0) {
            throw new RuntimeException("没有获取到送货单数据!");
        }

        List<Order> ordersToCreate = new ArrayList<>();//新增订单集合
        List<Order> ordersToUpdate = new ArrayList<>();//更新订单集合
        //获取所有送货单条码号
        Set<String> barcodeNumbers = details.stream()
                .map(detail -> ((JSONObject) detail).getString("barcodeNumber"))
                .collect(Collectors.toSet());
        //获取已存在的订单
        Map<String, Order> existingOrders = orderService.findByBarcodeNumbers(barcodeNumbers);
        //循环处理每个送货单
        for (int i = 0; i < details.size(); i++) {
            JSONObject detail = details.getJSONObject(i);
            String barcodeNumber = detail.getString("barcodeNumber");
            //判断是否已存在订单
            if (existingOrders.containsKey(barcodeNumber)) {
                Order existingOrder = existingOrders.get(barcodeNumber);
                //更新订单信息
                ordersToUpdate.add(updateOrder(existingOrder, detail));
            } else {
                //新增订单
                ordersToCreate.add(createOrder(detail));
            }
        }
        //批量新增订单
        if (!ordersToCreate.isEmpty()) {
            orderService.batchCreateOrders(ordersToCreate);
        }
        //批量更新订单
        if (!ordersToUpdate.isEmpty()) {
            orderService.batchUpdateOrders(ordersToUpdate);
        }

    }

    /**
     * 创建订单
     *
     * @param detail
     * @return
     */
    private Order createOrder(JSONObject detail) {

        String barcodeNumber = detail.getString("barcodeNumber");//送货单条码号
        String isCreatedLabel = detail.getString("isCreatedLabel");//是否已生成标签N
        String itemCode = detail.getString("itemCode");//物料编码
        String iqcResult = detail.getString("iqcResult");//检验结果(不合格：REJECT，合格：ACCEPT)
        String supplierCode = detail.getString("supplierCode");//供应商编码
        //String dispatchNumber=detail.getString("dispatchNumber");//文档没有该字段
        String receivedLocationName = detail.getString("receivedLocationName");//LMES货位名称
        String receivedInvCode = detail.getString("receivedInvCode");//LMES接收子库编码
        //Integer deliveryNotifyLineId = detail.getInteger("deliveryNotifyLineId");//送货通知单行ID
        String deliveryNumber = detail.getString("deliveryNumber");//送货单号
        String receivedAreaCode = detail.getString("receivedAreaCode");//LMES接收货区编码
        String supplierName = detail.getString("supplierName");//供应商名称
        String isIqcInspected = detail.getString("isIqcInspected");//Y-已检验N-未检验
        Double deliveryQty = detail.getDouble("deliveryQty") == null ? 0 : detail.getDouble("deliveryQty");//计划数量
        //String deliveryType=detail.getString("deliveryType");//文档没有该字段
        String receivedLocationCode = detail.getString("receivedLocationCode");//LMES货位编码
        String mlsUpdateTime = detail.getString("updateTime");//更新时间
        String receivedInvName = detail.getString("receivedInvName");//LMES接收子库名称
        Double receivedQty = detail.getDouble("receivedQty") == null ? 0 : detail.getDouble("receivedQty");//实际接收数量
        //Integer deliveryLineId = detail.getInteger("deliveryLineId");//送货单行ID
        String inInspector = detail.getString("inInspector");//检验员
        Integer deliveryHeaderId = detail.getInteger("deliveryHeaderId");//送货单头ID和003接口关联
        String receivedAreaName = detail.getString("receivedAreaName");//mls接收货区名称
        String deliveryStatus = detail.getString("deliveryStatus");//送货单状态

        //创建
        Order newOrder = new Order(deliveryHeaderId, null, null,
                deliveryNumber, barcodeNumber, deliveryStatus, receivedInvCode, receivedInvName,
                receivedAreaCode, receivedAreaName, receivedLocationCode, receivedLocationName,
                itemCode, deliveryQty, inInspector, receivedQty, isIqcInspected, iqcResult, isCreatedLabel,
                supplierCode, supplierName, mlsUpdateTime == null ? null : DateUtil.parse(mlsUpdateTime).toTimestamp()
        );

        return newOrder;
    }

    /**
     * 更新订单信息
     *
     * @param order
     * @param detail
     */
    private Order updateOrder(Order order, JSONObject detail) {
        order.setDeliveryStatus(detail.getString("deliveryStatus"));
        return order;
    }

    /**
     * 获取MO票JSON信息
     *
     * @return
     */
    @Override
    public String getMoJson(MoInfo moInfo) {
        JSONObject jsonObject = new JSONObject(new LinkedHashMap<>());
        Map<String, Object> objMap = new LinkedHashMap<>();
        objMap.put("ifaceCode", moInfo.getIfaceCode());//获取送货单信息
        objMap.put("sourceSystem", moInfo.getSourceSystem());//来源系统
        objMap.put("params", moInfo.getParams());
        jsonObject.putAll(objMap);
        return HttpPostUtil.sendPostReq(UrlApi.publicApi, jsonObject.toString(), this.getToKen());

    }

    /**
     * 获取MO票信息
     *
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void getMoInfo(String resultJson) {
        if (StringUtils.isEmpty(resultJson)) {
            throw new RuntimeException("获取MO票接口失败!");
        }

        JSONObject resulObject = JSON.parseObject(resultJson);
        if (resulObject == null) {
            throw new RuntimeException("获取MO票接口返回数据为空!");
        }
        String code = resulObject.getString("code") == null ? "" : resulObject.getString("code");
        String msg = resulObject.getString("msg") == null ? "" : resulObject.getString("msg");
        if (!"0".equals(code)) {
            throw new RuntimeException("获取MO票接口异常信息:" + msg);
        }

        String data = resulObject.getString("data") == null ? "" : resulObject.getString("data");
        JSONObject dataObject = JSON.parseObject(data);
        if (dataObject == null) {
            throw new RuntimeException("获取MO票接口返回数据为空!");
        }
        JSONArray details = dataObject.getJSONArray("list");
        //判断是否有MO票数据
        if (details == null || details.size() == 0) {
            throw new RuntimeException("没有获取到MO票数据!");
        }
        //循环处理每个MO票
        for (int i = 0; i < details.size(); i++) {
            JSONObject detail = details.getJSONObject(i);
            Integer selfWorkOrderId = detail.getInteger("selfWorkOrderId");//自制件工单id
            String sourceSystem = detail.getString("sourceSystem");//来源系统
            String selfWorkOrderName = detail.getString("selfWorkOrderName");//自制件工单编号
            String itemCode = detail.getString("itemCode");//物料编码
            String labelType = detail.getString("labelType");//标签类型
            String goodsAreaCode = detail.getString("goodsAreaCode");//MLS货区
            String checkResult = detail.getString("checkResult");//检验状态
            String datetimeStockIn = detail.getString("datetimeStockin");//入库时间
            String deleteFlag = detail.getString("deleteFlag");//数据有效性；有效0，无效1
            String uom = detail.getString("uom");//单位
            String createUserCode = detail.getString("createUserCode");//创建人
            String mlsUpdateTime = detail.getString("updateTime");//修改时间
            String itemDesc = detail.getString("itemDesc");//物料描述
            String labelNo = detail.getString("labelNo");//MO票
            Long itemId = detail.getLong("itemId");//物料id
            String updateUserCode = detail.getString("updateUserCode");//修改人
            String mlsCreateTime = detail.getString("createTime");//创建时间
            Double qty = detail.getDouble("qty") == null ? 0 : detail.getDouble("qty");//可用数量
            String labelState = detail.getString("labelState");//标签状态
            Integer deliveryHeaderId = detail.getInteger("deliveryHeaderId");//送货单头ID；通过该字段能找到002接口送货单
            String workOrderName = detail.getString("workOrderName");//工单编号
            Integer workOrderId = detail.getInteger("workOrderId");//工单Id
            String goodsLocationCode = detail.getString("goodsLocationCode");//MLS货位
            String invCode = detail.getString("invCode");//MLS子库

            if ("PRINTED".equals(labelState)) {
                //判断物料是否存在；不存在新增；
                ItemDto itemDto = itemService.findByCode(itemCode);
                Item item = itemService.toEntity(itemDto);
                if (item == null) {
                    item = new Item();
                    item.setCode(itemCode);
                    item.setName(itemDesc);
                    item.setUnit(uom);
                    DeptDto deptDto = deptService.findById(7L);
                    Dept dept = deptService.toEntity(deptDto);
                    item.setDept(dept);
                    item.setSourceName(sourceSystem);
                    item.setSourceId(itemId);
                    itemService.create(item);
                }

                MoDto moDto = moService.findByLabelNo(labelNo);
                if (moDto == null) {
                    Mo mo = new Mo(labelNo, labelType, labelState, deliveryHeaderId, sourceSystem, qty,
                            workOrderId, workOrderName, selfWorkOrderId, selfWorkOrderName, null, item,
                            checkResult, Boolean.parseBoolean(deleteFlag), null, null, null, null, invCode, goodsAreaCode, goodsLocationCode,
                            datetimeStockIn == null ? null : DateUtil.parse(datetimeStockIn).toTimestamp(),
                            mlsCreateTime == null ? null : DateUtil.parse(mlsCreateTime).toTimestamp(),
                            mlsUpdateTime == null ? null : DateUtil.parse(mlsUpdateTime).toTimestamp(),
                            createUserCode, updateUserCode
                    );
                    moService.create(mo);
                } else {
                    Mo mo = moService.toEntity(moDto);
                    mo.setLabelType(labelType);
                    mo.setLabelState(labelState);
                    mo.setDeliveryHeaderId(deliveryHeaderId);
                    mo.setSourceSystem(sourceSystem);
                    mo.setQty(qty);
                    mo.setWorkOrderId(workOrderId);
                    mo.setWorkOrderName(workOrderName);
                    mo.setSelfWorkOrderId(selfWorkOrderId);
                    mo.setSelfWorkOrderName(selfWorkOrderName);
                    mo.setDatetimeStockIn(datetimeStockIn == null ? null : DateUtil.parse(datetimeStockIn).toTimestamp());
                    mo.setItem(item);
                    mo.setCheckResult(checkResult);
                    mo.setDeleteFlag(Boolean.parseBoolean(deleteFlag));
                    mo.setInvCode(invCode);
                    mo.setGoodsAreaCode(goodsAreaCode);
                    mo.setGoodsLocationCode(goodsLocationCode);
                    mo.setMlsUpdateTime(mlsUpdateTime == null ? null : DateUtil.parse(mlsUpdateTime).toTimestamp());
                    mo.setUpdateUserCode(updateUserCode);
                    moService.update(mo);
                }
            }


        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void getIssueInfo(IssueInfo issueInfo) {
        String taskNumber = issueInfo.getTaskNumber();//任务号
        // 指定Set的类型
        Set<String> workOrderNameSet = issueInfo.getWorkOrderName();
        if (workOrderNameSet.isEmpty()) {
            throw new RuntimeException("没有获取到工单号!");
        }

        List<Inventory> inventoryList = inventoryService.findInvByBillCode(workOrderNameSet);//根据工单号查询库存信息
        if (inventoryList.size() == 0) {
            throw new RuntimeException("无库存信息!");
        }

        //目标点
        Point endPoint = pointService.findByCode(null, null, null, "出库接驳口", null);
        for (Inventory inv : inventoryList) {
            //根据库存信息生成叫料任务
            Stock stock = inv.getStock();//容器
            Point startPoint = inv.getPoint();//起始点位
            Item item = inv.getItemKey().getItem();

            inv.setQueuedQty(inv.getQuantity());
            inventoryService.update(inv);
            PickDetail pd = new PickDetail();
            pd.setItem(item);
            pd.setPo(inv.getBillCode());
            pd.setPropC1(inv.getItemKey().getPropC1());
            pd.setLineNo(1l);
            pd.setOrderQty(inv.getQuantity());
            pd.setAllocatedQty(inv.getQuantity());
            pd.setStatus(BizStatus.ALLOCATE);
            pickDetailService.create(pd);

            //生成搬运任务
            AgvTask agvTask = new AgvTask(BizStatus.PICK, stock.getCode(), startPoint.getCode(), endPoint.getCode(), BizStatus.OPEN, "01");
            agvTaskService.create(agvTask);
            //生成Task
            Task task = new Task();
            task.setItem(item);
            task.setItemKey(inv.getItemKey());
            task.setPickDetail(pd);
            task.setBillCode(taskNumber);
            task.setSrcStock(inv.getStock());
            task.setDstStock(inv.getStock());
            task.setSrcPoint(startPoint);
            task.setDstPoint(endPoint);
            task.setSrcStockCode(inv.getStock().getCode());
            task.setSrcPointCode(startPoint.getCode());
            task.setDstPointCode(endPoint.getCode());
            task.setInvStatus(inv.getStatus());
            task.setTaskType(BizStatus.PICK);
            task.setTaskStatus(BizStatus.OPEN);
            task.setPlanQty(inv.getQuantity());
            task.setInvId(inv.getId());
            task.setDept(item.getDept());
            task.setAgvTask(agvTask);
            taskService.create(task);
        }


    }

    /**
     * Mo票回传
     *
     * @param returnMoInfo
     * @return
     */
    @Override
    public String returnMo(ReturnMoInfo returnMoInfo) {
        JSONObject jsonObject = new JSONObject(new LinkedHashMap<>());
        Map<String, Object> objMap = new LinkedHashMap<>();
        objMap.put("ifaceCode", returnMoInfo.getIfaceCode());//获取送货单信息
        objMap.put("sourceSystem", returnMoInfo.getSourceSystem());//来源系统
        objMap.put("params", returnMoInfo.getParams());
        jsonObject.putAll(objMap);
        return HttpPostUtil.sendPostReq(UrlApi.publicApi, jsonObject.toString(), this.getToKen());
    }

    /**
     * 叫料结果回传
     *
     * @param returnIssueInfo
     * @return
     */
    @Override
    public String returnIssue(ReturnIssueInfo returnIssueInfo) {
        JSONObject jsonObject = new JSONObject(new LinkedHashMap<>());
        Map<String, Object> objMap = new LinkedHashMap<>();
        objMap.put("ifaceCode", returnIssueInfo.getIfaceCode());//获取送货单信息
        objMap.put("sourceSystem", returnIssueInfo.getSourceSystem());//来源系统
        objMap.put("params", returnIssueInfo.getParams());
        jsonObject.putAll(objMap);
        return HttpPostUtil.sendPostReq(UrlApi.publicApi, jsonObject.toString(), this.getToKen());
    }

}
