package com.youchain.appupdate.rest;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.youchain.annotation.AnonymousAccess;
import com.youchain.annotation.Log;
import com.youchain.appupdate.inputJson.CallStock;
import com.youchain.appupdate.inputJson.ContainerIn;
import com.youchain.appupdate.inputJson.BindStock;
import com.youchain.appupdate.inputJson.LineReturn;
import com.youchain.basicdata.domain.Item;
import com.youchain.basicdata.domain.Point;
import com.youchain.basicdata.domain.Stock;
import com.youchain.basicdata.service.BoxService;
import com.youchain.basicdata.service.ItemService;
import com.youchain.basicdata.service.PointService;
import com.youchain.basicdata.service.StockService;
import com.youchain.businessdata.domain.*;
import com.youchain.businessdata.service.*;
import com.youchain.businessdata.service.impl.InventoryLogServiceImpl;
import com.youchain.exception.handler.ApiResult;
import com.youchain.modules.quartz.utils.TimeNumberUtils;
import com.youchain.modules.system.service.DictService;
import com.youchain.utils.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.List;

import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.OK;

@RestController
@RequiredArgsConstructor
@Api(tags = "app管理")
@RequestMapping("/api/app")
@Slf4j
public class XksAppController {

    private final ItemService itemService;

    private final PointService pointService;

    private final AgvTaskService agvTaskService;

    private final StockService stockService;

    private final InventoryService inventoryService;

    private final InventoryLogServiceImpl invLogImpl;

    private final DictService dictService;

    private final PickDetailService pickDetailService;

    private final TaskService taskService;

    private final AsnDetailService asnDetailService;

    private final ItemKeyService itemKeyService;


    @PostMapping("/callStock")
    @Log("呼叫容器")
    @ApiOperation("呼叫容器")
    @AnonymousAccess
    public ResponseEntity<Object> callStock(@RequestBody CallStock callStock) {
        String agv_on_off = "OFF";
        String code = "0";
        String message = "";
        agv_on_off = dictService.getDictDescription("agv_on_off") == null ? "OFF" : dictService.getDictDescription("agv_on_off").getDescription();
        String areaName = callStock.getAreaName();
        String pointCode = callStock.getPointCode();//目标点位
        String itemCode = callStock.getItemCode();//物料编号
        int scene = callStock.getScene();//业务场景
        Point endPoint = pointService.findByCode(pointCode, null, null, null, null);
        if (endPoint == null) {
            return new ResponseEntity<>(ApiResult.success(BAD_REQUEST.value(), "请扫描正确点位!", ""), HttpStatus.BAD_REQUEST);
        }
        //叫空车
        if (scene == 1) {

            if (endPoint.getStatus().equals(BaseStatus.FREE)) {
                //查询所有可用的空料车
                Stock stock = stockService.findByKStock(areaName);
                if (stock == null) {
                    return new ResponseEntity<>(ApiResult.success(BAD_REQUEST.value(), areaName + "没有空料车!", ""), HttpStatus.BAD_REQUEST);
                }
                Point startPoint = stock.getPoint();
                //生成搬运任务
                AgvTask agvTask = new AgvTask(BizStatus.EMPTY_OUT, stock.getCode(), startPoint.getCode(), endPoint.getCode(), BizStatus.OPEN, "RACK_MOVE_EMPTY");
                agvTaskService.create(agvTask);
                if (agv_on_off.equals("ON")) {
                    String resultJson = agvTaskService.sendAgvTaskImpl(agvTask);//发送任务
                    JSONObject resulObject = JSON.parseObject(resultJson);
                    code = resulObject.getString("code") == null ? "" : resulObject.getString("code");
                    message = resulObject.getString("message") == null ? "" : resulObject.getString("message");
                }
                if (code.equals("0")) {
                    //目标点位占用
                    endPoint.setStatus(BaseStatus.USED);
                    pointService.update(endPoint);
                } else {
                    return new ResponseEntity<>(ApiResult.success(BAD_REQUEST.value(), "AGV返回消息:" + message, ""), HttpStatus.BAD_REQUEST);
                }
            } else {
                return new ResponseEntity<>(ApiResult.success(BAD_REQUEST.value(), endPoint.getCode() + "点位已有任务，请勿重复操作!", ""), HttpStatus.BAD_REQUEST);
            }


        } else if (scene == 2) {
            //叫满车
            Item item = itemService.existItem(itemCode);
            if (item == null) {
                return new ResponseEntity<>(ApiResult.success(BAD_REQUEST.value(), "请扫描正确的物料!", ""), HttpStatus.BAD_REQUEST);
            }
            if (endPoint.getStatus().equals(BaseStatus.FREE)) {
                List<Inventory> inventoryList = inventoryService.queryInventory(item.getId(), areaName);
                if (inventoryList.size() == 0) {
                    return new ResponseEntity<>(ApiResult.success(BAD_REQUEST.value(), itemCode + "物料无库存,呼叫失败!", ""), HttpStatus.BAD_REQUEST);
                }
                PickDetail pickDetail = pickDetailService.createPickDetail(item, "");
                try {
                    pickDetailService.allocateAll(pickDetail.getId(), endPoint, areaName);
                } catch (Exception e) {
                    return new ResponseEntity<>(ApiResult.success(BAD_REQUEST.value(), e.getMessage(), ""), HttpStatus.BAD_REQUEST);
                }
                List<Task> taskList = taskService.getPickNotAllTask(pickDetail.getId());
                AgvTask agvTask = taskList.get(0).getAgvTask();
                if (agv_on_off.equals("ON")) {
                    String resultJson = agvTaskService.sendAgvTaskImpl(agvTask);//发送任务
                    JSONObject resulObject = JSON.parseObject(resultJson);
                    code = resulObject.getString("code") == null ? "" : resulObject.getString("code");
                    message = resulObject.getString("message") == null ? "" : resulObject.getString("message");
                }
                if (code.equals("0")) {
                    //点位占用
                    endPoint.setStatus(BaseStatus.USED);
                    pointService.update(endPoint);
                } else {
                    return new ResponseEntity<>(ApiResult.success(BAD_REQUEST.value(), "AGV返回消息:" + message, ""), HttpStatus.BAD_REQUEST);
                }

            } else {
                return new ResponseEntity<>(ApiResult.success(BAD_REQUEST.value(), endPoint.getCode() + "点位已有任务，请勿重复操作!", ""), HttpStatus.BAD_REQUEST);
            }
        }

        return new ResponseEntity<>(ApiResult.success(OK.value(), "呼叫成功!", ""), HttpStatus.OK);

    }

    @PostMapping("/bindStock")
    @Log("满料入库")
    @ApiOperation("满料入库")
    @AnonymousAccess
    public ResponseEntity<Object> bindStock(@RequestBody BindStock bindStock) {
        String agv_on_off = "OFF";
        String code = "0";
        String message = "";
        agv_on_off = dictService.getDictDescription("agv_on_off") == null ? "OFF" : dictService.getDictDescription("agv_on_off").getDescription();


        String itemCode = bindStock.getItemCode();//物料编号
        String stockCode = bindStock.getStockCode();//容器编号
        String pointCode = bindStock.getPointCode();//点位编号
        Item item = itemService.existItem(itemCode);
        if (item == null) {
            return new ResponseEntity<>(ApiResult.success(BAD_REQUEST.value(), "请扫描正确的物料!", ""), HttpStatus.BAD_REQUEST);
        }

        Stock stock = stockService.findByCode(stockCode, null);
        if (stock == null) {
            return new ResponseEntity<>(ApiResult.success(BAD_REQUEST.value(), "请扫描正确的容器!", ""), HttpStatus.BAD_REQUEST);
        }
        if (stock.getStatus().equals(BaseStatus.USED)) {
            return new ResponseEntity<>(ApiResult.success(BAD_REQUEST.value(), stockCode + "容器已占用,请更换容器!", ""), HttpStatus.BAD_REQUEST);
        }

        Point srcPoint = pointService.findByCode(pointCode, null, null, null, null);
        if (srcPoint == null) {
            return new ResponseEntity<>(ApiResult.success(BAD_REQUEST.value(), "请扫描正确点位!", ""), HttpStatus.BAD_REQUEST);
        }
        if (srcPoint.getStatus().equals(BaseStatus.FREE)) {
            //根据起点的库区判断楼层
            String areaName = "";
            if (srcPoint.getArea().getName().substring(0, 1).equals("1")) {
                areaName = "1F存储区";
            } else {
                areaName = "2F原材料B区";
            }

            Point endPoint = pointService.findByCode(null, BaseStatus.FREE, BaseStatus.STORAGE, areaName, null);
            if (endPoint == null) {
                return new ResponseEntity<>(ApiResult.success(BAD_REQUEST.value(), areaName + "没有空闲点位!", ""), HttpStatus.BAD_REQUEST);
            }

            //生成AGV任务
            AgvTask agvTask = new AgvTask(BizStatus.ASN, stock.getCode(), srcPoint.getCode(), endPoint.getCode(), BizStatus.OPEN, "RACK_MOVE_FULL");
            agvTaskService.create(agvTask);
            if (agv_on_off.equals("ON")) {
                String resultJson = agvTaskService.sendAgvTaskImpl(agvTask);//发送任务
                JSONObject resulObject = JSON.parseObject(resultJson);
                code = resulObject.getString("code") == null ? "" : resulObject.getString("code");
                message = resulObject.getString("message") == null ? "" : resulObject.getString("message");
            }
            if (code.equals("0")) {
                //生成入库任务
                Date date = cn.hutool.core.date.DateUtil.date();
                String propC1 = DateUtil.format(date, "yyyyMMdd");
                AsnDetail asnDetail = asnDetailService.createAsnDetail(item, stock, srcPoint, propC1, null);
                asnDetail.setOrderQty(item.getExtendD1());
                asnDetail.setPo(null);
                asnDetail.setPropC3(null);
                asnDetailService.create(asnDetail);
                //生成Itemkey
                ItemKey itemKey = itemKeyService.getItemKey(item, asnDetail.getPropC1(), asnDetail.getOrderNumber());

                //生成收货记录
                Task task = new Task(item, itemKey, asnDetail.getOrderNumber(), BizStatus.ASN, asnDetail, null, null, null, stock, stock, srcPoint, endPoint, stock.getCode(), stock.getCode(), srcPoint.getCode(), endPoint.getCode(), null, BizStatus.OPEN, asnDetail.getOrderQty(), null, null, item.getDept(), agvTask);
                taskService.create(task);

                //容器改为占用,目标点位占用
                stock.setStatus(BaseStatus.USED);
                stockService.update(stock);

                //点位改为占用
                srcPoint.setStatus(BaseStatus.USED);
                pointService.update(srcPoint);
            } else {
                return new ResponseEntity<>(ApiResult.success(BAD_REQUEST.value(), "AGV返回消息:" + message, ""), HttpStatus.BAD_REQUEST);
            }
        } else {
            return new ResponseEntity<>(ApiResult.success(BAD_REQUEST.value(), srcPoint.getCode() + "点位已有任务，请勿重复操作!", ""), HttpStatus.BAD_REQUEST);
        }

        return new ResponseEntity<>(ApiResult.success(OK.value(), "绑定成功!", ""), HttpStatus.OK);
    }

    @PostMapping("/lineReturn")
    @Log("线边返空")
    @ApiOperation("线边返空")
    @AnonymousAccess
    public ResponseEntity<Object> lineReturn(@RequestBody LineReturn lineReturn) {
        String agv_on_off = "OFF";
        String code = "0";
        String message = "";
        agv_on_off = dictService.getDictDescription("agv_on_off") == null ? "OFF" : dictService.getDictDescription("agv_on_off").getDescription();

        String areaName = lineReturn.getAreaName();//库区名称
        String stockCode = lineReturn.getStockCode();//容器编号
        String pointCode = lineReturn.getPointCode();//点位编号

        Stock stock = stockService.findByCode(stockCode, null);
        if (stock == null) {
            return new ResponseEntity<>(ApiResult.success(BAD_REQUEST.value(), "请扫描正确的容器!", ""), HttpStatus.BAD_REQUEST);
        }


        Point srcPoint = pointService.findByCode(pointCode, null, null, null, null);
        if (srcPoint == null) {
            return new ResponseEntity<>(ApiResult.success(BAD_REQUEST.value(), "请扫描正确点位!", ""), HttpStatus.BAD_REQUEST);
        }

        //根据库区查询空闲的空车点位
        Point endPoint = pointService.findByCode(null, BaseStatus.FREE, BaseStatus.STORAGE, areaName, null);
        if (endPoint == null) {
            return new ResponseEntity<>(ApiResult.success(BAD_REQUEST.value(), areaName+"没有空闲点位!", ""), HttpStatus.BAD_REQUEST);
        }

        //默认先出场在入场
        ContainerIn containerIn = new ContainerIn();
        containerIn.setContainerCode(stockCode);
        containerIn.setPosition(srcPoint.getCode());
        this.containerOut(containerIn);
        this.containerIn(containerIn);

        //生成返库车任务
        AgvTask agvTask = new AgvTask(BizStatus.EMPTY_IN, stock.getCode(), srcPoint.getCode(), endPoint.getCode(), BizStatus.OPEN, "RACK_MOVE_EMPTY");
        agvTaskService.create(agvTask);
        if (agv_on_off.equals("ON")) {
            String resultJson = agvTaskService.sendAgvTaskImpl(agvTask);//发送任务
            JSONObject resulObject = JSON.parseObject(resultJson);
            code = resulObject.getString("code") == null ? "" : resulObject.getString("code");
            message = resulObject.getString("message") == null ? "" : resulObject.getString("message");
        }
        if (code.equals("0")) {
            //目标点位占用
            endPoint.setStatus(BaseStatus.USED);
            pointService.update(endPoint);
        } else {
            return new ResponseEntity<>(ApiResult.success(BAD_REQUEST.value(), "AGV返回消息:" + message, ""), HttpStatus.BAD_REQUEST);
        }

        return new ResponseEntity<>(ApiResult.success(OK.value(), "返空成功!", ""), HttpStatus.OK);
    }


    @PostMapping("/containerIn")
    @Log("容器入场")
    @ApiOperation("容器入场")
    @PreAuthorize("@el.check('app:containerIn')")
    public ResponseEntity<Object> containerIn(@RequestBody ContainerIn containerIn) {
        String code = "0";
        String message = "";
        String agv_on_off = "OFF";
        agv_on_off = dictService.getDictDescription("agv_on_off") == null ? "OFF" : dictService.getDictDescription("agv_on_off").getDescription();
        String containerCode = containerIn.getContainerCode();//容器号
        String position = containerIn.getPosition();//点位
        Stock stock = stockService.findByCode(containerCode, null);
        if (stock == null) {
            return new ResponseEntity<>(ApiResult.fail(BAD_REQUEST.value(), "请扫描正确容器，操作失败！", ""), HttpStatus.BAD_REQUEST);
        }
        Point point = pointService.findByCode(position, null, null, null, null);
        if (point == null) {
            return new ResponseEntity<>(ApiResult.fail(BAD_REQUEST.value(), "请扫描正确点位，操作失败！", ""), HttpStatus.BAD_REQUEST);
        }
        String areaName = point.getArea().getName();//库区名称

        //空车入场和满车入场
        if (areaName.equals(AreaNameDic.OneFK)||areaName.equals(AreaNameDic.TwoFK)||areaName.equals(AreaNameDic.TwoFCX)) {
            //是否调用AGV
            if (agv_on_off.equals("ON")) {
                //调用容器入场接口
                String jsonObject = agvTaskService.containerIn(containerCode, position);
                String resultJson = HttpPostUtil.sendPostReq(UrlApi.containerIn, jsonObject.toString());
                JSONObject resulObject = JSON.parseObject(resultJson);
                code = resulObject.getString("code") == null ? "" : resulObject.getString("code");
                message = resulObject.getString("message") == null ? "" : resulObject.getString("message");
            }
            //空车入场
            if (code.equals("0")) {
                stock.setPoint(point);
                stockService.update(stock);
                point.setStatus(BaseStatus.USED);
                pointService.update(point);
            } else {
                return new ResponseEntity<>(ApiResult.fail(BAD_REQUEST.value(), "AGV返回信息:" + message, ""), HttpStatus.BAD_REQUEST);
            }
        } else if (areaName.equals(AreaNameDic.OneFC) || areaName.equals(AreaNameDic.TwoFB)) {
            //满车入场，需要物料号且生成库存信息
            String itemCode = containerIn.getItemCode();//物料
            Item item = itemService.existItem(itemCode);
            if (item == null) {
                return new ResponseEntity<>(ApiResult.fail(BAD_REQUEST.value(), areaName + "区入场请输入物料编号!", ""), HttpStatus.BAD_REQUEST);
            }
           /* if ((point.getDescription() != null && !item.getGoodType().equals(point.getDescription()))) {
                return new ResponseEntity<>(ApiResult.fail(BAD_REQUEST.value(), "物料类型和点位对应的类型不匹配!", ""), HttpStatus.BAD_REQUEST);
            }*/
            //是否调用AGV
            if (agv_on_off.equals("ON")) {
                //调用容器入场接口
                String jsonObject = agvTaskService.containerIn(containerCode, position);
                String resultJson = HttpPostUtil.sendPostReq(UrlApi.containerIn, jsonObject.toString());
                JSONObject resulObject = JSON.parseObject(resultJson);
                code = resulObject.getString("code") == null ? "" : resulObject.getString("code");
                message = resulObject.getString("message") == null ? "" : resulObject.getString("message");
            }
            if (code.equals("0")) {
                List<Inventory> inventoryList = inventoryService.queryInventory(stock);
                for (Inventory inventory : inventoryList) {
                    Long[] ids = new Long[1];
                    ids[0] = inventory.getId();
                    inventoryService.deleteAll(ids);
                }

                AsnDetail asnDetail = new AsnDetail();
                asnDetail.setItem(item);
                asnDetail.setLineNo(1l);
                asnDetail.setStatus(BizStatus.RECEIVED);
                asnDetail.setOrderQty(item.getExtendD1());
                asnDetail.setReceivedQty(item.getExtendD1());
                asnDetail.setDept(item.getDept());
                Date date = cn.hutool.core.date.DateUtil.date();
                String propC1 = DateUtil.format(date, "yyyyMMdd");
                asnDetail.setPropC1(propC1);
                asnDetail.setStock(stock);
                asnDetail.setPo(TimeNumberUtils.getRCCode());
                asnDetailService.create(asnDetail);

                //生成Itemkey
                ItemKey itemKey = itemKeyService.getItemKey(item, asnDetail.getPropC1(), asnDetail.getOrderNumber());


                //生成入库记录
                Task task = new Task(item, itemKey, asnDetail.getOrderNumber(), BizStatus.ASN, asnDetail, null, null, null, stock, stock, null, point, stock.getCode(), stock.getCode(), null, point.getCode(), null, BizStatus.RECEIVED, asnDetail.getOrderQty(), null, null, item.getDept(), null);
                task.setMoveQty(task.getPlanQty());
                taskService.create(task);

                Inventory inventory = inventoryService.getInventory(task.getItemKey(), task.getDstPoint(), task.getSrcStock(), task.getDept(), BizStatus.RECEIVING_UP);
                inventory.addQty(inventory, task.getPlanQty());
                inventoryService.update(inventory);
                stock.setStatus(BaseStatus.USED);
                stock.setPoint(inventory.getPoint());
                stockService.update(stock);
                point.setStatus(BaseStatus.USED);
                pointService.update(point);
            } else {
                return new ResponseEntity<>(ApiResult.fail(BAD_REQUEST.value(), message, ""), HttpStatus.BAD_REQUEST);
            }
        } else {
            return new ResponseEntity<>(ApiResult.fail(BAD_REQUEST.value(), areaName + "不能入场", ""), HttpStatus.BAD_REQUEST);
        }
        return new ResponseEntity<>(ApiResult.success(OK.value(), "入场成功!", ""), HttpStatus.OK);
    }

    @PostMapping("/containerOut")
    @Log("容器出场")
    @ApiOperation("容器出场")
    @PreAuthorize("@el.check('app:containerOut')")
    public ResponseEntity<Object> containerOut(@RequestBody ContainerIn containerIn) {
        String agv_on_off = "OFF";
        agv_on_off = dictService.getDictDescription("agv_on_off").getDescription();
        String code = "0";
        String message = "";
        String containerCode = containerIn.getContainerCode();
        Stock stock = stockService.findByCode(containerCode, null);
        if (stock == null) {
            return new ResponseEntity<>(ApiResult.fail(BAD_REQUEST.value(), "请扫描正确容器，操作失败！", ""), HttpStatus.BAD_REQUEST);
        }
        //出场查询是否有库存 有则出库存，没有则直接出场
        List<Inventory> inventoryList = inventoryService.queryInventory(stock);
        for (Inventory inventory : inventoryList) {
            invLogImpl.storeInventoryLog(BizStatus.INVENTORY_ADJUST, BizStatus.REDUCE, "容器出场", inventory.getItemKey(), inventory.getPoint(), null, inventory.getStock(), null, inventory.getQuantity(), inventory.getQuantity(), null, null, inventory.getId(), "容器出场库存扣减");
            Long[] ids = new Long[1];
            ids[0] = inventory.getId();
            inventoryService.deleteAll(ids);
        }
        //调用容器出场接口
        String jsonObject = agvTaskService.containerOut(containerCode);
        if (agv_on_off.equals("ON")) {
            String resultJson = HttpPostUtil.sendPostReq(UrlApi.containerOut, jsonObject.toString());
            JSONObject resulObject = JSON.parseObject(resultJson);
            code = resulObject.getString("code") == null ? "" : resulObject.getString("code");
            message = resulObject.getString("message") == null ? "" : resulObject.getString("message");
        }
        if (code.equals("0")) {
            Point point = stock.getPoint();
            if (point != null) {
                point.setStatus(BaseStatus.FREE);
                pointService.update(point);
            }
            stock.setPoint(null);
            stock.setStatus(BaseStatus.FREE);
            stockService.update(stock);
        } else {
            return new ResponseEntity<>(ApiResult.fail(BAD_REQUEST.value(), "AGV返回信息:" + message, ""), HttpStatus.BAD_REQUEST);
        }

        return new ResponseEntity<>(ApiResult.success(OK.value(), "出场成功!", ""), HttpStatus.OK);
    }

}
