/*
*  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.youchain.annotation.AnonymousAccess;
import com.youchain.annotation.Log;
import com.youchain.basicdata.domain.Item;
import com.youchain.basicdata.domain.Point;
import com.youchain.basicdata.service.PointService;
import com.youchain.businessdata.domain.*;
import com.youchain.businessdata.inputJson.IPTask;
import com.youchain.businessdata.inputJson.IScanPut;
import com.youchain.businessdata.inputJson.buttenJson.PickTicketButton;
import com.youchain.businessdata.repository.*;
import com.youchain.businessdata.returnJson.RPPickList;
import com.youchain.businessdata.returnJson.RPTaskList;
import com.youchain.businessdata.service.*;
import com.youchain.businessdata.service.dto.PickTicketDto;
import com.youchain.businessdata.service.dto.PickTicketQueryCriteria;
import com.youchain.exception.BadRequestException;
import com.youchain.modules.system.domain.Dept;
import com.youchain.utils.*;
import lombok.extern.slf4j.Slf4j;
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.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import io.swagger.annotations.*;
import java.io.IOException;
import java.security.Security;
import java.sql.Time;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;
import javax.servlet.http.HttpServletResponse;

/**
* @website https://eladmin.vip
* @author JiangKun
* @date 2024-01-11
**/
@Slf4j
@RestController
@RequiredArgsConstructor
@Api(tags = "pickTicket管理")
@RequestMapping("/api/pickTicket")
public class PickTicketController {

    private final PickTicketService pickTicketService;
    private final PickTicketRepository pickTicketRepository;
    private final PickDetailRepository pickDetailRepository;
    private final TaskRepository taskRepository;
    private final TaskLogRepository taskLogRepository;
    private final XppRecordService xppRecordService;
    private final XppRecordRepository xppRecordRepository;
    private final TaskService taskService;
    private final TaskLogService taskLogService;
    private final InventoryService inventoryService;
    private final InventoryLogService inventoryLogService;
    private final PointService pointService;
    private final ItemKeyService itemKeyService;
    private final CodeUtils codeUtils;



    @GetMapping("/getIdByPickTicket")
    @Log("查询pickTicket")
    @ApiOperation("查询pickTicket")
    @AnonymousAccess
    public ResponseEntity<Object> getIdByPickTicket(@RequestParam("id") Long id) {
        return new ResponseEntity<>(pickTicketRepository.findById(id), HttpStatus.OK);
    }

    @GetMapping(value = "/createNo")
    @Log("出库管理生成单号")
    @ApiOperation("出库管理生成单号")
    @AnonymousAccess
    public ResponseEntity<Object> createNo(@RequestParam("code") String code) {
        //获取最大单号
        PickTicket pickTicket = pickTicketRepository.queryMaxCode();
        //生成日期 YYMMDD 格式的日期
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YYMMDD");
        String formatDate = simpleDateFormat.format(new Date());
        //返回的单号
        String returnNo = null;
        //判断是否有数据
        if (Objects.isNull(pickTicket)){
            log.warn("表中还没有数据");
            return new ResponseEntity<>((code+formatDate+"001"), HttpStatus.OK);
        }
        //获取出库管理的code值
        String pTCode = pickTicket.getCode();
        int i = Integer.parseInt(pTCode.substring(pTCode.length() - 3))+1;
        if (i > 999) {
            i = 001;
        }
        returnNo = code + formatDate + String.format("%03d", i);
        return new ResponseEntity<>(returnNo, HttpStatus.OK);
    }


    @Log("导出数据")
    @ApiOperation("导出数据")
    @GetMapping(value = "/download")
    @AnonymousAccess
    public void exportPickTicket(HttpServletResponse response, PickTicketQueryCriteria criteria) throws Exception {
        pickTicketService.download(pickTicketService.queryAll(criteria), response);
    }

    @GetMapping
    @Log("查询pickTicket")
    @ApiOperation("查询pickTicket")
    @AnonymousAccess
    public ResponseEntity<Object> queryPickTicket(PickTicketQueryCriteria criteria, Pageable pageable){
        return new ResponseEntity<>(pickTicketService.queryAll(criteria,pageable),HttpStatus.OK);
    }

    @PutMapping
    @Log("修改pickTicket")
    @ApiOperation("修改pickTicket")
    @PreAuthorize("@el.check('super:man')")
    public ResponseEntity<Object> updatePickTicket(@Validated @RequestBody PickTicket resources ){
        pickTicketService.update(resources);
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }

    @DeleteMapping
    @Log("删除pickTicket")
    @ApiOperation("删除pickTicket")
    @PreAuthorize("@el.check('super:man')")
    public ResponseEntity<Object> deletePickTicket(@RequestBody Long[] ids) {
        //删除手工备货操作需要进行数量回退
        pickTicketService.deletePickTicket(ids);
        return new ResponseEntity<>(HttpStatus.OK);
    }


    @PostMapping("/queryPickListApp")
    @Log("备货列表查询")
    @ApiOperation("备货列表查询")
    @AnonymousAccess
    public ResponseEntity<Object> queryPickListApp(@RequestBody IScanPut t){
        List<RPPickList> ts= pickTicketService.queryPickList(t);
        return new ResponseEntity<>(ts,HttpStatus.OK);
    }

    @PostMapping("/queryPickTaskListApp")
    @Log("备货列表明细查询")
    @ApiOperation("备货列表明细查询")
    @AnonymousAccess
    public ResponseEntity<Object> queryPickTaskListApp(@RequestBody IPTask t){
        List<RPTaskList> ts= taskService.queryTaskApp(t);
        return new ResponseEntity<>(ts,HttpStatus.OK);
    }

    @PostMapping
    @Log("新增pickTicket")
    @ApiOperation("新增pickTicket")
    @PreAuthorize("@el.check('super:man')")
    public ResponseEntity<Object> createPickTicket(@Validated @RequestBody PickTicket resources){
        if(resources.getBillType().getName().equals(BaseStatus.BT_QTCK)) {
            resources.setCode(codeUtils.getCode_yyMMdd(resources.getBillType().getPrefix(), 3));
        }
        return new ResponseEntity<>(pickTicketService.create(resources),HttpStatus.CREATED);
    }


    @PostMapping("/pickingOperations")
    @Log("拣货操作")
    @ApiOperation("拣货操作")
    @PreAuthorize("@el.check('super:man')")
    public ResponseEntity<Object> pickingOperations(@RequestBody PickTicketButton resources){
        pickTicketService.pickingOperation(resources);
        return new ResponseEntity<>("操作成功",HttpStatus.OK);
    }
    @PostMapping("/pickWhole")
    @Log("备货操作-整单拣货")
    @ApiOperation("备货操作-整单拣货")
    @PreAuthorize("@el.check('super:man')")
    @Transactional
    public ResponseEntity<Object> pickWhole(@RequestBody Long ptId){
        String bhr=SecurityUtils.getCurrentUsername();
        List<Task> ts=taskRepository.getNotPickTask(ptId);
        if(ts.size()<=0){
            return new ResponseEntity<>("没有需要拣货的明细",HttpStatus.BAD_REQUEST);
        }
        for(Task t:ts) {
            pickTicketService.pickForTask(t.getId(), t.getSrcStockCode(), t.getPlanQty()-t.getMoveQty(), null, bhr);
        }
        return new ResponseEntity<>("操作成功",HttpStatus.OK);
    }

    @PostMapping("/pickBatch")
    @Log("备货操作-批量拣货")
    @ApiOperation("备货操作-批量拣货")
    @PreAuthorize("@el.check('super:man')")
    @Transactional
    public ResponseEntity<Object> pickBatch(@RequestBody Long[] taskIds){
        String bhr=SecurityUtils.getCurrentUsername();
        for(Long id:taskIds) {
            Task t=taskRepository.getById(id);
            pickTicketService.pickForTask(t.getId(), t.getSrcStockCode(), t.getPlanQty()-t.getMoveQty(), null, bhr);
        }
        return new ResponseEntity<>("操作成功",HttpStatus.OK);
    }

    @PostMapping("/pickSingle")
    @Log("备货操作-单一拣货")
    @ApiOperation("备货操作-单一拣货")
    @PreAuthorize("@el.check('super:man')")
    @Transactional
    public ResponseEntity<Object> pickSingle(@RequestBody PickTicketButton resources){
        String bhr=SecurityUtils.getCurrentUsername();
        Long taskId=resources.getTaskId()[0];
        double pickQty=resources.getOnePickConfirmNumber();
        pickTicketService.pickForTask(taskId, null, pickQty, null, bhr);
        return new ResponseEntity<>("操作成功",HttpStatus.OK);
    }

    @PostMapping("/pickForXpp")
    @Log("备货操作-现品票拣货")
    @ApiOperation("备货操作-现品票拣货")
    @PreAuthorize("@el.check('super:man')")
    @Transactional
    public ResponseEntity<Object> pickForXpp(@RequestBody PickTicketButton resources){
        Long ptId=resources.getPickTicketId();
        String xppQRCode=resources.getXppQRCode();
        //现品票二维码
        XppRecord xpp = xppRecordRepository.findByCode(xppQRCode);
        if (Objects.isNull(xpp)){
            throw new BadRequestException(HttpStatus.NOT_FOUND, "未找到对应的现品票二维码");
        }
        if(xpp.getCkTaskLog()!=null){
            throw new BadRequestException(HttpStatus.NOT_FOUND, "现品票已出库");
        }
        Task rkT=xpp.getRkTask();
        if(rkT==null){
            throw new BadRequestException(HttpStatus.NOT_FOUND, "现品票未上架");
        }
        ItemKey ik=rkT.getItemKey();
        //取现品票上的库位进行拣货
        Long srcPointId=null;
        if(xpp.getInvPoint()!=null){
            srcPointId=xpp.getInvPoint().getId();
        }
        List<Task> ts=taskService.queryTask(null,null,ik.getId(),ptId,srcPointId);
        Task t=null;
        for(Task task:ts){
            if(task.getMoveQty()<task.getPlanQty()){
                t=task;
            }
        }
        if(ts.size()<=0){
            throw new BadRequestException(HttpStatus.NOT_FOUND, ik.getItem().getCode()+"已全部备货");
        }
        if(t==null){
//            t=ts.get(0);
            throw new BadRequestException(HttpStatus.NOT_FOUND, ik.getItem().getCode()+"找不到待拣货任务");
        }
        String bhr=SecurityUtils.getCurrentUsername();
        pickTicketService.pickForTask(t.getId(),t.getSrcStockCode(),xpp.getNrs(),xpp,bhr);
        return new ResponseEntity<>("操作成功",HttpStatus.OK);
    }

    @PostMapping("/xppPickGoods")
    @Log("App现品票拣货")
    @ApiOperation("App现品票拣货")
    @AnonymousAccess
    @Transactional
    public ResponseEntity<Object> xppPickGoods(@RequestBody PickTicketButton resources){
        //现品票二维码
        String xppQRCode = resources.getXppQRCode();
        XppRecord xpp = xppRecordRepository.findByCode(xppQRCode);
        if (Objects.isNull(xpp)){
            throw new BadRequestException(HttpStatus.NOT_FOUND, "未找到对应的现品票二维码");
        }
        if(xpp.getCkTaskLog()!=null){
            throw new BadRequestException(HttpStatus.NOT_FOUND, "现品票已出库");
        }
        Task rkT=xpp.getRkTask();
        if(rkT==null){
            throw new BadRequestException(HttpStatus.NOT_FOUND, "现品票未上架");
        }
        ItemKey ik=rkT.getItemKey();
        //取现品票上的库位进行拣货
        Long srcPointId=null;
        if(xpp.getInvPoint()!=null){
            srcPointId=xpp.getInvPoint().getId();
        }
        List<Task> ts=taskService.queryTask(null,null,ik.getId(),resources.getPickTicketId(),srcPointId);
        Task t=null;
        for(Task task:ts){
            if(task.getMoveQty()<task.getPlanQty()){
                t=task;
            }
        }
        if(ts.size()<=0){
            throw new BadRequestException(HttpStatus.NOT_FOUND, ik.getItem().getCode()+"已全部备货");
        }
        if(t==null){
//            t=ts.get(0);
            throw new BadRequestException(HttpStatus.NOT_FOUND, ik.getItem().getCode()+"找不到待拣货任务");
        }
        pickTicketService.pickForTask(t.getId(),resources.getStockCode(),xpp.getNrs(),xpp,resources.getBhr());
        HashMap<String,Object> map=new HashMap<>();
        Item it=ik.getItem();
        PickTicket pt=t.getPickDetail().getPickTicket();
        map.put("itemCode",it.getCode());
        map.put("itemName",it.getName());
        map.put("dds",pt.getOrderQuantity());
        map.put("bhs",pt.getPickedQuantity());
        map.put("ddbh",xpp.getDdbh());
        map.put("bcsl",xpp.getNrs());
        map.put("fzh",xpp.getFzh());
        map.put("tjkw",t.getSrcPoint().getCode());
        return new ResponseEntity<>(map,HttpStatus.OK);
    }

    @PostMapping("/queryTaskLogDataS")
    @Log("拣货取消的数据查询")
    @ApiOperation("拣货取消的数据查询")
    @PreAuthorize("@el.check('super:man')")
    public ResponseEntity<List<TaskLog>> queryTaskLogDataS(@RequestBody PickTicketButton resources){
        return new ResponseEntity<>(pickTicketService.queryTaskLogDataS(resources.getPickTicketId()),HttpStatus.CREATED);
    }

    @PostMapping("/pickingCancel")
    @Log("拣货取消")
    @ApiOperation("拣货取消")
    @PreAuthorize("@el.check('super:man')")
    public ResponseEntity<Object> pickingCancel(@RequestBody PickTicketButton resources){
        pickTicketService.pickingCancel(resources);
        return new ResponseEntity<>("拣货取消成功",HttpStatus.CREATED);
    }

    @PostMapping("/xbjsVerify")
    @Log("线边接收确认")
    @ApiOperation("线边接收确认")
    @PreAuthorize("@el.check('super:man')")
    public ResponseEntity<Object> xbjsVerify(@RequestBody Long[] ids) {
        for (Long id : ids) {
            PickTicket pt=pickTicketRepository.getById(id);
            List<TaskLog> logs=taskLogRepository.getTaskLogsByPtId(id);
            double shNum = 0d;
            for (TaskLog log : logs) {
                log.setSlQty(log.getShipQty());
                log.setSlBy(SecurityUtils.getCurrentUsername());
                taskLogService.update(log);
                shNum+=log.getSlQty();
                //生成具体的库存信息
                Task task=log.getTask();
                PickDetail pickDetail=task.getPickDetail();
//                Point point=pt.getShArea().getPoint();
                Point point=pointService.findEntityById(pt.getShArea().getPointId());
                Dept dept= UserUtils.getDept();
                //线边接收不需要管理到批次，重新生成itemKey
                ItemKey itemKey=itemKeyService.getItemKey(log.getItemKey().getItem(),null,null,null,null,null,null);
                Inventory inventory=inventoryService.getInventory(itemKey,pt.getShArea(),point,pickDetail.getPoint(),dept,BizStatus.SL_ALL);
                double srcQty=inventory.getQuantity();
                inventory.setQuantity(inventory.getQuantity()+log.getSlQty());
                inventoryService.update(inventory);
                inventoryLogService.storeInventoryLog(BizStatus.SL_ALL, BizStatus.ADD, null, pt.getShArea(), log.getItemKey(), inventory.getPoint(), inventory.getPoint(), null,null, srcQty, log.getSlQty(),null,log.getSrcStockCode(),
                        BizStatus.SL_ALL, log.getId(), inventory.getId(), "线边接收");
            }
            pt.setSlQty(shNum);
            pt.setSlBy(SecurityUtils.getCurrentUsername());
            pt.setSlDate(new Timestamp(new Date().getTime()));
            pt.setStatus(BizStatus.SL_ALL);
            pickTicketService.update(pt);

        }
        return new ResponseEntity<>(HttpStatus.OK);
    }

    @PostMapping("/shipmentRegistration")
    @Log("发货登记")
    @ApiOperation("发货登记")
    @PreAuthorize("@el.check('super:man')")
    public ResponseEntity<Object> shipmentRegistration(@RequestBody Long id) {
        pickTicketService.shipmentRegistration(id);
        return new ResponseEntity<>(HttpStatus.OK);
    }

    @PostMapping("/queryDetails")
    @Log("根据pickTicket的id查询详情数据")
    @ApiOperation("根据pickTicket的id查询详情数据")
    @PreAuthorize("@el.check('super:man')")
    public ResponseEntity<Object> queryDetails(@RequestBody Long id){
        Map<String,Object> map = new HashMap<>();
        PickTicketDto pickTicketDto = pickTicketService.findById(id);
        //查询出库明细
        map.put("pickDetailList",pickDetailRepository.queryByPickTicketId(id));
        //查询分配记录
        map.put("pickDetailAllocateList",taskRepository.queryByBillCode(pickTicketDto.getCode()));
        //查询拣货记录
        map.put("pickDetailPickingList",taskLogRepository.getTaskLogsByPtId(id));
        return new ResponseEntity<>(map,HttpStatus.OK);
    }

}
