package com.youchain.appupdate.rest;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.youchain.annotation.AnonymousAccess;
import com.youchain.annotation.Log;
import com.youchain.appupdate.inputJson.ContainerIn;
import com.youchain.appupdate.inputJson.ScanItemCode;
import com.youchain.basicdata.domain.Box;
import com.youchain.basicdata.domain.Item;
import com.youchain.basicdata.domain.Point;
import com.youchain.appupdate.inputJson.BindOrder;
import com.youchain.appupdate.inputJson.CallBox;
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.basicdata.service.dto.BoxDto;
import com.youchain.basicdata.service.dto.PointDto;
import com.youchain.businessdata.domain.AsnDetail;
import com.youchain.businessdata.domain.Inventory;
import com.youchain.businessdata.domain.ItemKey;
import com.youchain.businessdata.domain.Task;
import com.youchain.businessdata.service.*;
import com.youchain.businessdata.service.impl.InventoryLogServiceImpl;
import com.youchain.exception.handler.ApiResult;
import com.youchain.modules.system.domain.DictDetail;
import com.youchain.modules.system.service.DictDetailService;
import com.youchain.modules.system.service.DictService;
import com.youchain.modules.system.service.dto.DictDto;
import com.youchain.modules.system.service.dto.DictQueryCriteria;
import com.youchain.utils.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.mica.core.utils.JsonUtil;
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.LinkedHashMap;
import java.util.List;
import java.util.Map;

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 XyjAppController {

    private final BoxService boxService;

    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;
    @PostMapping("/bindOrder")
    @Log("绑定工单号")
    @ApiOperation("绑定工单号")
    @PreAuthorize("@el.check('app:bindOrder')")
    public ResponseEntity<Object> bindOrder(@RequestBody BindOrder bindOrder) {
        long boxId = bindOrder.getBoxId();
        String itemCode = bindOrder.getItemCode();//物料编号
        String orderNumber = bindOrder.getOrderNumber();//工单号
        BoxDto boxDto = boxService.findById(boxId);//按钮盒
        Box box = boxService.toEntity(boxDto);//转实体
        if (box == null) {
            return new ResponseEntity<>(ApiResult.fail(BAD_REQUEST.value(), "请选择按钮盒!", ""), HttpStatus.BAD_REQUEST);
        }

        Item item = itemService.existItem(itemCode);
        if (item == null) {
            return new ResponseEntity<>(ApiResult.fail(BAD_REQUEST.value(), "请扫描正确的物料信息!", ""), HttpStatus.BAD_REQUEST);
        }
        box.setItem(item);
        box.setOrderNumber(orderNumber);
        boxService.update(box);
        return new ResponseEntity<>(ApiResult.success(OK.value(), "绑定成功!", ""), HttpStatus.OK);

    }

    @PostMapping("/queryBox")
    @Log("查询按钮盒列表")
    @ApiOperation("查询按钮盒列表")
    @PreAuthorize("@el.check('app:queryBox')")
    public ResponseEntity<Object> queryBox(@RequestBody String json) {

        JSONObject jsonObject = JSON.parseObject(json);
        String areaName = jsonObject.getString("areaName");

        //按钮盒的点位-BOX
        JSONArray jsonArray = new JSONArray();
        List<Box> boxList = boxService.queryBoxList(areaName);
        if (boxList.size() > 0) {
            for (Box box : boxList) {
                JSONObject obj = new JSONObject(new LinkedHashMap<>());
                obj.put("boxId", box.getId());
                obj.put("boxCode", box.getName());
                obj.put("areaName", box.getPoint().getArea().getName());
                obj.put("itemCode", box.getItem() == null ? "" : box.getItem().getCode());
                //物料类型
                obj.put("goodType", box.getItem() == null ? "" : box.getItem().getGoodType());
                obj.put("orderNumber", box.getOrderNumber());

                jsonArray.add(obj);
            }
            return new ResponseEntity<>(ApiResult.success(OK.value(), "", jsonArray), HttpStatus.OK);
        } else {
            return new ResponseEntity(ApiResult.fail(BAD_REQUEST.value(), "未找到按钮盒信息!", ""), HttpStatus.BAD_REQUEST);
        }
    }


    @PostMapping("/callBox")
    @Log("按钮盒呼叫")
    @ApiOperation("按钮盒呼叫")
    @AnonymousAccess
    public ResponseEntity<Object> callBox(@RequestBody CallBox callBox) {
        BoxDto boxDto = boxService.findById(callBox.getId());//按钮盒
        try {
            boxService.callBox(boxDto);
        } catch (Exception e) {
            return new ResponseEntity<>(ApiResult.success(BAD_REQUEST.value(), e.getMessage(), ""), HttpStatus.BAD_REQUEST);
        }
        return new ResponseEntity<>(ApiResult.success(OK.value(), "呼叫成功!", ""), HttpStatus.OK);
    }
    @PostMapping("/callTrolley")
    @Log("按钮车呼叫")
    @ApiOperation("按钮车呼叫")
    @AnonymousAccess
    public ResponseEntity<Object> callTrolley(@RequestParam("id") Long id,@RequestParam("pointCode") String pointCode) {
        PointDto pointDto = pointService.findById(id);
        try {
            boxService.callTrolley(pointDto,pointCode);
        } catch (Exception e) {
            return new ResponseEntity<>(ApiResult.success(BAD_REQUEST.value(), e.getMessage(), ""), 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 containerCode = containerIn.getContainerCode();//容器号
        String position = containerIn.getPosition();//点位
        int checkCode = containerIn.getCheckCode();
        Stock stock = stockService.findByCode(containerCode, null);
        if (stock == null) {
            return new ResponseEntity<>(ApiResult.fail(BAD_REQUEST.value(), "请扫描正确容器，操作失败！", ""), HttpStatus.BAD_REQUEST);
        }else if(checkCode==1){
            return new ResponseEntity<>(ApiResult.success(OK.value(), "校验成功!", ""), HttpStatus.OK);
        }
        Point point = pointService.findByCode(position, null, null, null, null);
        if (point == null) {
            return new ResponseEntity<>(ApiResult.fail(BAD_REQUEST.value(), "请扫描正确点位，操作失败！", ""), HttpStatus.BAD_REQUEST);
        }else if(checkCode==2){
            return new ResponseEntity<>(ApiResult.success(OK.value(), "校验成功!", ""), HttpStatus.OK);
        }
        String areaName=point.getArea().getName();//库区名称

        String enterOrientation = "";
        if (point.getArea().getName().equals("前后桶部装空车缓存区") || point.getArea().getName().equals("前后桶空车区")) {
            enterOrientation = "-90";
        }
        String code="0";
        String message=null;
        String agv_on_off="OFF";
        String jsonObject = agvTaskService.containerIn(containerCode, position, enterOrientation);
        agv_on_off=dictService.getDictDescription("agv_on_off")==null?"OFF":dictService.getDictDescription("agv_on_off").getDescription();
        //空车入场和满车入场
        if(areaName.equals(AreaNameDic.QHTBZK)||areaName.equals(AreaNameDic.QHTK)||areaName.equals(AreaNameDic.ZCK)||areaName.equals(AreaNameDic.ZCJXB)||areaName.equals(AreaNameDic.ZCFB)){
            //是否调用AGV
            if(agv_on_off.equals("ON")) {
                //调用容器入场接口
                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(), message, ""), HttpStatus.BAD_REQUEST);
            }
        }else if(areaName.equals(AreaNameDic.QHTL)||areaName.equals(AreaNameDic.ZCM)||areaName.equals(AreaNameDic.MFM)){
            //满车入场，需要物料号且生成库存信息
            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()))||
                    (areaName.equals(AreaNameDic.ZCM)&&!item.getGoodType().equals(BizStatus.ZC))||
                    (areaName.equals(AreaNameDic.MFM)&&!item.getGoodType().equals(BizStatus.MF))){
                return new ResponseEntity<>(ApiResult.fail(BAD_REQUEST.value(), "物料类型和点位对应的类型不匹配!", ""), HttpStatus.BAD_REQUEST);
            }
            //是否调用AGV
            if(agv_on_off.equals("ON")) {
                //调用容器入场接口
                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) {
                    inventory.setQuantity(0d);
                    inventory.setQueuedQty(0d);
                    inventoryService.update(inventory);
                    if(inventory.getQuantity()<=0){
                        Long[] ids= new Long[1];
                        ids[0]=inventory.getId();
                        inventoryService.deleteAll(ids);
                    }
                }
                Task task=boxService.createTask(item,stock,point);
                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 containerCode = containerIn.getContainerCode();
        String position = containerIn.getPosition();
        int checkCode = containerIn.getCheckCode();
        Stock stock = stockService.findByCode(containerCode, null);
        if (stock == null) {
            return new ResponseEntity<>(ApiResult.fail(BAD_REQUEST.value(), "请扫描正确容器，操作失败！", ""), HttpStatus.BAD_REQUEST);
        }else if(checkCode==1){
            return new ResponseEntity<>(ApiResult.success(OK.value(), "校验成功!", ""), HttpStatus.OK);
        }
        Point point = pointService.findByCode(position, null, null, null, null);
        if (point == null) {
            return new ResponseEntity<>(ApiResult.fail(BAD_REQUEST.value(), "请扫描正确点位，操作失败！", ""), HttpStatus.BAD_REQUEST);
        }

        //出场查询是否有库存 有则出库存，没有则直接出场
        List<Inventory> inventoryList = inventoryService.queryInventory(stock);
        for (Inventory inventory:inventoryList) {
//            if(inventory.getQueuedQty()>0){
//                return new ResponseEntity<>(ApiResult.fail(BAD_REQUEST.value(), "容器对应库存锁定", ""), HttpStatus.BAD_REQUEST);
//            }
            invLogImpl.storeInventoryLog(BizStatus.INVENTORY_ADJUST,BizStatus.REDUCE,"容器出场",inventory.getItemKey(),inventory.getPoint(),
                    null,inventory.getStock(),null,inventory.getQuantity(),inventory.getQuantity(),null,null,inventory.getId(),"容器出场库存扣减");
            inventory.setQuantity(0d);
            inventory.setQueuedQty(0d);
            inventoryService.update(inventory);
        }
        //调用容器出场接口
        String jsonObject = agvTaskService.containerOut(containerCode);

        String agv_on_off="OFF";
        agv_on_off=dictService.getDictDescription("agv_on_off").getDescription();
        String code="0";
        String message=null;
        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")) {
            stock.setPoint(null);
            stock.setStatus(BaseStatus.FREE);
            stockService.update(stock);
            point.setStatus(BaseStatus.FREE);
            pointService.update(point);
        } else {
            return new ResponseEntity<>(ApiResult.fail(BAD_REQUEST.value(), message, ""), HttpStatus.BAD_REQUEST);
        }

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

    @PostMapping("/boxUnBind")
    @Log("解绑")
    @ApiOperation("解绑")
    @PreAuthorize("@el.check('app:boxUnBind')")
    public ResponseEntity<Object> boxUnBind(@RequestBody CallBox callBox) {

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

    @PostMapping("/ModbusRead")
    @Log("Modbus读取")
    @ApiOperation("Modbus读取")
    @PreAuthorize("@el.check('app:ModbusRead')")
    public ResponseEntity<Object> ModbusRead() {
        System.out.println("Modbus读取=====================1");
        //  Number v3520 = Modbus4jReadUtils.readHoldingRegister(1, 3500, DataType.CHAR);// 注意,float
        System.out.println("Modbus读取=====================2");
        //nt intNumber3520 = v3520.intValue();
        // System.out.println("intNumber3520:" + intNumber3520);
        return new ResponseEntity<>(ApiResult.success(OK.value(), "读取成功!", ""), HttpStatus.OK);
    }

    @GetMapping("/scanItemCode")
    @Log("扫描物料")
    @ApiOperation("扫描物料")
    @PreAuthorize("@el.check('app:scanItemCode')")
    public ResponseEntity<Object> scanItemCode(ScanItemCode scanItemCode) {
        String itemCode = scanItemCode.getItemCode();
        Item item = itemService.existItem(itemCode);
        if (item == null) {
            return new ResponseEntity<>(ApiResult.fail(BAD_REQUEST.value(), "请扫描正确的物料信息!", ""), HttpStatus.BAD_REQUEST);
        }
        JSONObject obj = new JSONObject(new LinkedHashMap<>());
        obj.put("itemName", item.getName());
        return new ResponseEntity<>(ApiResult.success(OK.value(), "", obj), HttpStatus.OK);

        }
    }
