/*
*  Copyright 2019-2020 Zheng Jie
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
package com.youchain.businessdata.rest;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.youchain.annotation.AnonymousAccess;
import com.youchain.annotation.Log;
import com.youchain.basicdata.domain.Point;
import com.youchain.basicdata.repository.PointRepository;
import com.youchain.basicdata.service.dto.PointQueryCriteria;
import com.youchain.businessdata.domain.Inventory;
import com.youchain.businessdata.domain.PickDetail;
import com.youchain.businessdata.domain.Task;
import com.youchain.businessdata.repository.InventoryRepository;
import com.youchain.businessdata.repository.PickDetailRepository;
import com.youchain.businessdata.repository.TaskRepository;
import com.youchain.businessdata.service.AgvTaskService;
import com.youchain.businessdata.service.InventoryService;
import com.youchain.businessdata.service.PickDetailService;
import com.youchain.businessdata.service.TaskService;
import com.youchain.businessdata.service.dto.TaskQueryCriteria;
import com.youchain.exception.handler.ApiResult;
import com.youchain.utils.BaseStatus;
import com.youchain.utils.BizStatus;
import com.youchain.utils.UrlApi;
import com.youchain.utils.UserUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.util.StandardSessionIdGenerator;
import org.springframework.data.domain.Pageable;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import io.swagger.annotations.*;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import javax.servlet.http.HttpServletResponse;

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

/**
* @website https://eladmin.vip
* @author houjianlan
* @date 2023-08-16
**/
@RestController
@RequiredArgsConstructor
@Api(tags = "task管理")
@RequestMapping("/api/task")
@Slf4j
public class TaskController {

    private final TaskService taskService;
    private final TaskRepository taskRepository;
    private final InventoryService inventoryService;
    private final PickDetailRepository pickDetailRepository;
    private final PickDetailService pickDetailService;
    private final InventoryRepository inventoryRepository;
    private final PointRepository pointRepository;
    private final AgvTaskService agvTaskService;

    @Log("导出数据")
    @ApiOperation("导出数据")
    @GetMapping(value = "/download")
    @PreAuthorize("@el.check('task:list')")
    public void exportTask(HttpServletResponse response, TaskQueryCriteria criteria) throws IOException {
        taskService.download(taskService.queryAll(criteria), response);
    }

    @GetMapping
    @Log("查询task")
    @ApiOperation("查询task")
    @PreAuthorize("@el.check('task:list')")
    public ResponseEntity<Object> queryTask(TaskQueryCriteria criteria, Pageable pageable){
        return new ResponseEntity<>(taskService.queryAll(criteria,pageable),HttpStatus.OK);
    }
    @PostMapping("/manualReceiving")
    @Log("人工入库")
    @ApiOperation("人工入库,AGV成品入库")
    @AnonymousAccess
    @Transactional(rollbackFor = Exception.class)
    public synchronized ResponseEntity<Object> manualReceiving(@RequestBody JSONObject request){
        String rfid=request.getString("RFID");
        int agvFlag=request.getIntValue("agvFlag");
        Point point= pointRepository.getById(request.getLong("pointId"));
        String type=point.getType();
        // 人工入库 直接生成库存
        ApiResult apiResult = taskService.manualReceiving(rfid,point,agvFlag);
        if (type.equals(BaseStatus.BOX)){
            if (apiResult.getStatus()==200){
                // AGV入库 生成搬运任务（目标库区，单据任务类型）
                apiResult = agvTaskService.addAgvAsn(apiResult.getData().toString());
            }
        }
        if (apiResult.getStatus()!=200&&apiResult.getStatus()!=201){
            //回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return new ResponseEntity<>(apiResult, HttpStatus.valueOf(apiResult.getStatus()));
    }
    @PostMapping("/devanRfid")
    @ApiOperation("人工出库，人工入库-解析RFID关联的库存信息")
    @AnonymousAccess
    public ResponseEntity<Object> devanRfid(@RequestBody String data){
        JSONObject jsonObject=JSONObject.parseObject(data);
        String rfid=jsonObject.getString("rfid");
        String type=jsonObject.getString("type");
        ApiResult apiResult;
        if (type.equals("ASN")){
            apiResult = taskService.devanRfidAsn(rfid,BaseStatus.STORAGE);
        }else {
            apiResult = taskService.devanRfidPT(rfid);
        }
        return new ResponseEntity<>(apiResult, HttpStatus.valueOf(apiResult.getStatus()));
    }
    @PostMapping("/picking")
    @Log("人工出库-拣货确认")
    @AnonymousAccess
    public ResponseEntity<Object> picking(@RequestBody String data){
        JSONObject jsonObject=JSONObject.parseObject(data);

//        String rfid=jsonObject.getString("RFID");

        Long taskId=jsonObject.getLong("taskId");
        ApiResult apiResult;
        /** 通过RFID获取Task后出库*/
        apiResult = taskService.picking(new Long[]{taskId});
        return new ResponseEntity<>(apiResult, HttpStatus.valueOf(apiResult.getStatus()));
    }
    /** 人工出库-解析RFID关联的(未分配)库存信息*/
    @PostMapping("/replaceInv")
    @Log("出库-替换分配库存")
    @AnonymousAccess
    @Transactional
    public ApiResult replaceInv(@RequestBody String data) {
        System.out.println("接收:"+data);
        JSONObject jsonObject=JSONObject.parseObject(data);
        Long invId=jsonObject.getLong("invId");
        Long taskId=jsonObject.getLong("taskId");
        Task task=taskRepository.getById(taskId);
        PickDetail pickDetail=task.getPickDetail();
        Inventory inventory=inventoryRepository.getById(invId);//实际出库 库存
        ApiResult apiResult;
        /** 取消分配库存 */
        apiResult = pickDetailService.cancelAllocate(pickDetail.getId(),inventory.getQuantity());
        if (apiResult.getStatus()!=200){
            return apiResult;
        }
        /** 重新分配 */
        Point point=pointRepository.findByCode(pickDetail.getPropC5());
        List<Inventory> inventoryList= Arrays.asList(inventory);
        int agvFlag=0;
        if (pickDetail.getPropC4().equals("AGV_PT")){
            agvFlag=1;
        }
        apiResult = pickDetailService.allocate(pickDetail, UserUtils.getDept(), inventory.getQuantity(),agvFlag,point,inventoryList);
        if (apiResult!=null){
            return apiResult;
        }
        return ApiResult.fail(200,"操作成功",null);
    }

    @GetMapping(value = "/queryAsnTask")
    @Log("查询task")
    @ApiOperation("查询task")
    @PreAuthorize("@el.check('task:list')")
    public ResponseEntity<Object> queryAsnTask(TaskQueryCriteria criteria){
        return new ResponseEntity<>(taskService.queryAll(criteria),HttpStatus.OK);
    }
    @PostMapping(value = "/butSTputaway")
    @Log("料箱上架")
    @AnonymousAccess
    public ResponseEntity<Object> butSTputaway(@RequestBody String request){
        System.out.println("butSTputaway:"+request);
        JSONObject requestJson=JSONObject.parseObject(request);
        Long taskId=requestJson.getLong("taskId");
        Long pointId=requestJson.getLong("pointId");
        taskService.butSTputaway(taskId,pointId);
        ApiResult apiResult = ApiResult.fail(200, "操作成工", null);
        return new ResponseEntity<>(apiResult, HttpStatus.valueOf(apiResult.getStatus()));
    }
    @PostMapping(value = "/rmCkPickUp")
    @Log("AGV料箱出库-料箱拣货生成Task任务")
    @AnonymousAccess
    public ResponseEntity<Object> rmCkPickUp(@RequestBody String request){
        System.out.println("rmCkPickUp:"+request);
        JSONArray taskIds=JSONArray.parseArray(request);
        /** AGV料箱出库生成AgvTask*/
        ApiResult apiResult = taskService.rmCkPickUp(taskIds);
        return new ResponseEntity<>(apiResult, HttpStatus.valueOf(apiResult.getStatus()));
    }

    @GetMapping("/queryPickTask")
    @Log("拣货确认-拣货记录")
    @ApiOperation("拣货确认-拣货记录")
    @AnonymousAccess
    public  ResponseEntity<Object> queryPickTask(TaskQueryCriteria criteria){
        return new ResponseEntity<>(taskService.queryAll(criteria),HttpStatus.OK);
    }

    @PostMapping
    @Log("新增task")
    @ApiOperation("新增task")
    @PreAuthorize("@el.check('task:add')")
    public ResponseEntity<Object> createTask(@Validated @RequestBody Task resources){
        return new ResponseEntity<>(taskService.create(resources),HttpStatus.CREATED);
    }

    @PutMapping
    @Log("修改task")
    @ApiOperation("修改task")
    @PreAuthorize("@el.check('task:edit')")
    public ResponseEntity<Object> updateTask(@Validated @RequestBody Task resources){
        taskService.update(resources);
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }

    @DeleteMapping
    @Log("删除task")
    @ApiOperation("删除task")
    @PreAuthorize("@el.check('task:del')")
    public ResponseEntity<Object> deleteTask(@RequestBody Long[] ids) {
        taskService.deleteAll(ids);
        return new ResponseEntity<>(HttpStatus.OK);
    }
    @PostMapping("/readRfid")
    @Log("半成品/料箱 AGV入库-读取RFID码生成ItemKey和Task任务")
    @AnonymousAccess
    public ResponseEntity<Object> readRfid(@RequestBody JSONObject body) {
        String rfid=body.getString("rfid");
        int agvFlag=body.getIntValue("agvFlag");
        Point pointStartCode=pointRepository.findByTypeAndArea(BaseStatus.PLATFORM,"TAGM");
        // 收货生成Task
        try {
            ApiResult apiResult = taskService.manualReceiving(rfid,pointStartCode,agvFlag);
            if (apiResult.getStatus()!=200){
                return new ResponseEntity<>(apiResult, HttpStatus.valueOf(apiResult.getStatus()));
            }
            synchronized (BaseStatus.Lock.rfid_SJ) {
                /** 半成品/料箱 AGV入库*/
                String billCode=apiResult.getData().toString();
                String areaCode="";
                if (billCode.equals(BizStatus.RM_RK)){
                    areaCode=BizStatus.LX;
                }else if (billCode.equals(BizStatus.SM_RK)){
                    areaCode=BizStatus.BCP;
                }
                apiResult = agvTaskService.addAgvAsn(billCode);
            }
            return new ResponseEntity<>(apiResult, HttpStatus.valueOf(apiResult.getStatus()));
        }catch (Exception e){
            ApiResult apiResult = ApiResult.fail(500, "事务错误", e.getMessage());
            return new ResponseEntity<>(apiResult, HttpStatus.valueOf(apiResult.getStatus()));
        }
    }
    @PostMapping("/STAgvReceiving")
    @Log("容器入场-搬运容器到RFID门")
    @AnonymousAccess
    @Transactional
    public ResponseEntity<Object> STAgvReceiving(@RequestBody JSONObject jsonObject) {
        System.out.println("容器入场："+jsonObject);
        String storageType = jsonObject.getString("storageType");
        JSONArray ids=jsonObject.getJSONArray("ids");
        ApiResult apiResult = agvTaskService.pointStockRk(storageType,ids.getLong(0));
        Point pointEndCode= BaseStatus.DoorPoint;
        if (apiResult.getStatus()==200){
            apiResult = agvTaskService.addAgvTask(ids.getLong(0),pointEndCode.getCode());
        }
        return new ResponseEntity<>(apiResult, HttpStatus.valueOf(apiResult.getStatus()));
    }
    @PostMapping("/pointStockRk")
    @Log("容器入场")
    @AnonymousAccess
    @Transactional
    public ResponseEntity<Object> pointStockRk(@RequestBody JSONObject jsonObject) {
        System.out.println("容器入场："+jsonObject);
        String storageType = jsonObject.getString("storageType");
        JSONArray ids=jsonObject.getJSONArray("ids");
        ApiResult apiResult = agvTaskService.pointStockRk(storageType,ids.getLong(0));
        return new ResponseEntity<>(apiResult, HttpStatus.valueOf(apiResult.getStatus()));
    }
    @PostMapping("/pointStockCk")
    @Log("容器出场")
    @AnonymousAccess
    @Transactional
    public ResponseEntity<Object> pointStockCk(@RequestBody JSONObject jsonObject) {
        JSONArray ids=jsonObject.getJSONArray("ids");
        Point point=pointRepository.getById(ids.getLong(0));
        String storageType = point.getStorageType();
        ApiResult apiResult;
        if (storageType==null||storageType.length()<1){
            apiResult = ApiResult.fail(500,"库位没有容器",null);
        } else if (point.getStatus().equals(BaseStatus.USED)) {
            apiResult = ApiResult.fail(500,"容器错误",null);
        } else {
            apiResult = agvTaskService.pointStockCk(storageType,ids.getLong(0));
        }
        return new ResponseEntity<>(apiResult, HttpStatus.valueOf(apiResult.getStatus()));
    }
}
