/*
 *  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.*;
import com.youchain.basicdata.repository.*;
import com.youchain.businessdata.domain.Inventory;
import com.youchain.businessdata.repository.PickTicketRepository;
import com.youchain.businessdata.returnJson.RPTaskList;
import com.youchain.businessdata.domain.PickDetail;
import com.youchain.businessdata.domain.PickTicket;
import com.youchain.businessdata.domain.Task;
import com.youchain.businessdata.inputJson.IPPickDetail;
import com.youchain.businessdata.inputJson.IScanPut;
import com.youchain.businessdata.repository.PickDetailRepository;
import com.youchain.businessdata.service.*;
import com.youchain.businessdata.service.dto.*;
import com.youchain.exception.BadRequestException;
import com.youchain.exception.handler.ApiResult;
import com.youchain.utils.BaseStatus;
import com.youchain.utils.BizStatus;
import com.youchain.utils.DateUtil;
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.util.*;
import javax.servlet.http.HttpServletResponse;

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

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

    private final PickDetailService pickDetailService;
    private final TaskService taskService;
    private final PickDetailRepository pickDetailRepository;
    private final PickTicketService pickTicketService;
    private final InventoryService inventoryService;
    private final BillTypeRepository billTypeRepository;
    private final AreaRepository areaRepository;
    private final ItemRepository itemRepository;
    private final AutomaticPlanningRepository automaticPlanningRepository;
    private final BomAccountRepository bomAccountRepository;
    private final PickTicketRepository pickTicketRepository;

    @PostMapping("/getIdData")
    @Log("根据主表id查询pickDetail的数据")
    @ApiOperation("根据主表id查询pickDetail的数据")
    @AnonymousAccess
    public ResponseEntity<Object> getIdData(@RequestBody Long ids) {
        return new ResponseEntity<>(pickDetailRepository.queryByPickTicketId(ids), HttpStatus.OK);
    }

    @Log("导出数据")
    @ApiOperation("导出数据")
    @GetMapping(value = "/queryPickDetailZsc/download")
    @AnonymousAccess
    public void exportPickDetail(HttpServletResponse response, PickDetailQueryCriteria criteria) throws Exception {
        pickDetailService.download(pickDetailService.queryZscAll(criteria), response);
    }

    @GetMapping
    @Log("查询pickDetail")
    @ApiOperation("查询pickDetail")
    @AnonymousAccess
    public ResponseEntity<Object> queryPickDetail(PickDetailQueryCriteria criteria, Pageable pageable) {
        return new ResponseEntity<>(pickDetailService.queryAll(criteria, pageable), HttpStatus.OK);
    }

    @GetMapping(value = "/queryPickDetailZsc")
    @Log("查询pickDetail")
    @ApiOperation("查询pickDetail")
    @AnonymousAccess
    public ResponseEntity<Object> queryPickDetailZsc(PickDetailQueryCriteria criteria, Pageable pageable) {
        return new ResponseEntity<>(pickDetailService.queryPickDetailAll(criteria, pageable), HttpStatus.OK);
    }

    @PostMapping
    @Log("新增pickDetail")
    @ApiOperation("新增pickDetail")
    @AnonymousAccess
    @Transactional
    public ResponseEntity<Object> createPickDetail(@Validated @RequestBody PickDetail resources) throws Exception {
        //判断库存数量有没有这么多
        InventoryQueryCriteria inventoryQueryCriteria = new InventoryQueryCriteria();
        double quantityNum = 0;
        if (resources.getPoint() != null) {
           double qty=inventoryService.getInvQty(resources.getItem().getId(),resources.getPickTicket().getArea().getId(),
                    resources.getPoint().getId());
           if(qty<resources.getOrderQty()){
               throw new BadRequestException(HttpStatus.NOT_FOUND, "库存不足，库存"+qty);
           }
        } else {
//            inventoryQueryCriteria.setAreaName(resources.getPickTicket().getArea().getName());
//            inventoryQueryCriteria.setItemCodeOne(resources.getItem().getCode());
//            List<InventoryDto> inventoryDtos = inventoryService.queryAll(inventoryQueryCriteria);
//            for (InventoryDto inv : inventoryDtos) {
//                quantityNum += (inv.getQuantity()-inv.getQueuedQty());
//            }
        }
            //新增加订单数量
            PickTicket pickTicket = resources.getPickTicket();
            pickTicket.setOrderQuantity(pickTicket.getOrderQuantity() + resources.getOrderQty());
            pickTicketService.update(pickTicket);
            resources.setStatus(BizStatus.OPEN);
            PickDetailDto pickDetailDto = pickDetailService.create(resources);
        return new ResponseEntity<>("操作成功", HttpStatus.CREATED);
    }

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

    @DeleteMapping
    @Log("删除pickDetail")
    @ApiOperation("删除pickDetail")
    @PreAuthorize("@el.check('super:man')")
    public ResponseEntity<Object> deletePickDetail(@RequestBody Long[] ids) {
        //删除时需判断是否有分配
        for(Long id:ids){
            PickDetail pickDetail=pickDetailRepository.getById(id);
            if(pickDetail.getAllocatedQty()+pickDetail.getBcQty()>0){
                return new ResponseEntity<>(pickDetail.getItem().getCode()+"已出单，不允许删除",BAD_REQUEST);
            }else{
//                pickDetailRepository.deleteById(id);
            }
        }
        pickDetailService.deleteAll(ids);
        return new ResponseEntity<>(HttpStatus.OK);
    }

    @PostMapping("/allocatePick")
    @Log("拣货分配审核")
    @ApiOperation("拣货分配审核")
    @AnonymousAccess
    public synchronized ResponseEntity<Object> allocatePick(@RequestBody Long[] ids) throws Exception {
        List<Long> picktickIds = Arrays.asList(ids);
        Collections.sort(picktickIds);//升序排序
        if (picktickIds.size() > 0) {
            try {
                for (Long picktickId : picktickIds) {
                    List<PickDetail> pickDetailList = pickDetailService.queryPickDetailList(picktickId);
                    for (PickDetail pd : pickDetailList) {
                        pickDetailService.allocate(pd.getId(), pd.getOrderQty() - pd.getAllocatedQty());
                    }
                }
            } catch (Exception e) {
                return new ResponseEntity(ApiResult.fail(BAD_REQUEST.value(), e.getMessage(), ""), HttpStatus.BAD_REQUEST);
            }
        } else {
            return new ResponseEntity(ApiResult.fail(BAD_REQUEST.value(), "参数错误或者为null", ""), HttpStatus.BAD_REQUEST);
        }
        return new ResponseEntity<>(HttpStatus.OK);
    }

    @PostMapping("/sbPickdetail")
    @Log("设变")
    @ApiOperation("设变")
    @AnonymousAccess
    public ResponseEntity<Object> sbPickdetail(@RequestBody HashMap<String,Object> map) {
        Long pdId=Long.parseLong(map.get("pdId").toString());
        Double sbQty=Double.parseDouble(map.get("sbQty").toString());
        if(map.get("sbItemCode")==null){
            throw new BadRequestException("无关联设变");
        }
        String sbItemCode=map.get("sbItemCode").toString();
        Item sbIt=itemRepository.findByCode(sbItemCode);
        PickDetail oldD=pickDetailRepository.getById(pdId);
        double unSb=oldD.getOrderQty()-oldD.getAllocatedQty()-oldD.getBcQty();
        if(sbIt==null){
            throw new BadRequestException(sbItemCode+"物料不存在");
        }
        if(unSb<sbQty){
            throw new BadRequestException("需求不足数小于"+sbQty);
        }
        oldD.setRemark("设变"+oldD.getOrderQty());
        //查询库存是否足够
        Double invQty=inventoryService.getInvQty(sbIt.getId(),oldD.getPickTicket().getArea().getId(),null);
        if(invQty.intValue()<sbQty.intValue()){
            throw new BadRequestException("库存不足"+invQty.intValue());
        }
        //查找对应的BOM
        PickTicket pt=oldD.getPickTicket();
        if(pt.getPickedQuantity()>0){
            throw new BadRequestException(pt.getCode()+"已备货，不能设变");
        }
        Area shArea=pt.getShArea();
        List<BomAccount> bomList=bomAccountRepository.getItemBomList(sbIt.getId());
        if(bomList.size()<=0){
            throw new BadRequestException(sbIt.getCode()+"找不到对应的Bom工位清单"+sbQty);
        }
        BomAccount bomAccount=bomList.get(0);
        PickDetail newD= pickDetailService.createPickDetail(pt,sbIt,oldD.getPo(),sbQty,oldD.getSupplier());
        newD.setRemark("设变");
        newD.setSourceId(oldD.getId());
        newD.setBomId(bomAccount.getId());
        newD.setAc(bomAccount.getAc());
        newD.setSupplier(bomAccount.getSupplier());
        newD.setPoint(bomAccount.getZPoint());
        pickDetailService.allocate(newD.getId(), newD.getOrderQty() - newD.getAllocatedQty());
        oldD.setOrderQty(oldD.getOrderQty()-sbQty);
        oldD.setSourceId(newD.getId());
        pickDetailService.update(oldD);
        return new ResponseEntity<>(HttpStatus.OK);
    }

    @PostMapping("/cancelAllocate")
    @Log("取消分配")
    @ApiOperation("取消分配")
    @AnonymousAccess
    public synchronized ResponseEntity<Object> cancelAllocate(@RequestBody Long[] ids)  {
        List<Long> pickDetailIds = Arrays.asList(ids);
        if (pickDetailIds.size() > 0) {
            for (Long id : pickDetailIds) {
                pickDetailService.cancelAllocate(id);
            }
        }
        return new ResponseEntity<>(HttpStatus.OK);
    }

    @PostMapping("/queryTaskApp")
    @Log("查询拣货列表")
    @ApiOperation("查询拣货列表")
    @PreAuthorize("@el.check('super:man')")
    @AnonymousAccess
    public ResponseEntity<Object> queryTaskApp(@RequestBody IScanPut s) {
        List<RPTaskList> t = taskService.queryTaskApp(null);
        return new ResponseEntity<>(t, HttpStatus.OK);
    }

    @PostMapping("/pickingApp")
    @Log("APP拣货确认")
    @ApiOperation("APP拣货确认")
    @PreAuthorize("@el.check('super:man')")
    @AnonymousAccess
    public ResponseEntity<Object> pickingApp(@RequestBody IPPickDetail d) throws Exception {
        return pick_in(d.getPickDetailId());
    }

    @PostMapping("/picking")
    @Log("拣货")
    @ApiOperation("拣货确认")
    @AnonymousAccess
    public synchronized ResponseEntity<Object> picking(@RequestBody Long pickDetailId) throws Exception {
        return pick_in(pickDetailId);
    }

    public ResponseEntity<Object> pick_in(Long pickDetailId) {
        //查询未完成的拣货任务
        List<Task> Tasks = taskService.getPickNotAllTask(pickDetailId);
        if (Tasks.size() > 0) {
            try {
                for (Task task : Tasks) {
                    log.error("正在拣货-----");
                    taskService.pickConfirm(task.getId(), task.getPlanQty());
                }
            } catch (Exception e) {
                return new ResponseEntity(ApiResult.fail(BAD_REQUEST.value(), e.getMessage(), ""), HttpStatus.BAD_REQUEST);
            }
        } else {
            return new ResponseEntity(ApiResult.fail(BAD_REQUEST.value(), "已拣货完成，请勿重复操作！", ""), HttpStatus.BAD_REQUEST);
        }
        log.error("完成拣货-----");
        return new ResponseEntity(ApiResult.fail(HttpStatus.OK.value(), "已拣货完成，请勿重复操作！", ""), HttpStatus.OK);

    }


    @PostMapping("/pickBarBack")
    @Log("退拣")
    @ApiOperation("退拣")
    @AnonymousAccess
    public synchronized ResponseEntity<Object> pickBarBack(@RequestBody Long pickDetailId) throws Exception {
        //查询已完成的拣货任务
        List<Task> Tasks = taskService.getPickAllTask(pickDetailId);
        if (Tasks.size() > 0) {
            try {
                for (Task task : Tasks) {
                    taskService.pickBarBack(task.getId(), task.getMoveQty());
                }
            } catch (Exception e) {
                return new ResponseEntity(ApiResult.fail(BAD_REQUEST.value(), e.getMessage(), ""), HttpStatus.BAD_REQUEST);
            }
        } else {
            return new ResponseEntity(ApiResult.fail(BAD_REQUEST.value(), "已退拣完成，请勿重复操作！", ""), HttpStatus.BAD_REQUEST);
        }
        return new ResponseEntity<>(HttpStatus.OK);
    }

    @PostMapping("/autoBcbl")
    @Log("指示残-波次补料")
    @ApiOperation("指示残-波次补料")
    @PreAuthorize("@el.check('super:man')")
    @AnonymousAccess
    public ResponseEntity<Object> autoBcbl() {
        BillType bt=billTypeRepository.findByName(BaseStatus.BT_BCBL);
        if(bt==null){
            return new ResponseEntity<>("维护波次补料类型", BAD_REQUEST);
        }
        List<AutomaticPlanning>  plans=automaticPlanningRepository.getAll();
        if(plans.size()>0){
            AutomaticPlanning plan=plans.get(0);
            Date blDate=plan.getJhDate();
            blDate=new Date();
//        for(AutomaticPlanning plan:plans){
            //得到出库单的出库库区
            List<Object[]> outAreaGcs=pickTicketRepository.queryBhCkAreas(DateUtil.dateYmd(plan.getJhDate()));
            for(Object[] outAreaGc:outAreaGcs) {
                Long outAreaId=Long.parseLong(outAreaGc[0].toString());
                String gc=outAreaGc[1].toString();
                List<Object[]> objs = pickDetailService.getQueryBcbl(blDate,outAreaId,gc);
                if (objs.size() > 0) {
                    Area outArea = areaRepository.getById(outAreaId);
                    PickTicket pickTicket = pickTicketService.storePick(bt, null, outArea, "大", "波次补料");
                    for (Object[] obj : objs) {
                        PickDetail oldDetail = pickDetailRepository.getById(Long.parseLong(obj[0].toString()));
                        double orderQty = oldDetail.getOrderQty() - oldDetail.getAllocatedQty() - oldDetail.getBcQty();
                        PickDetail pickDetail = pickDetailService.createPickDetail(pickTicket, oldDetail.getItem(), null, orderQty, oldDetail.getSupplier());
                        pickDetail.setPoint(oldDetail.getPoint());
                        pickDetail.setPropC3(oldDetail.getPropC3());
                        pickDetail.setAc(oldDetail.getAc());
                        pickDetail.setContents(oldDetail.getContents());
                        pickDetail.setBomId(oldDetail.getBomId());
                        pickDetail.setSourceId(oldDetail.getId());
                        pickDetail.setSourceName(oldDetail.getPickTicket().getCode());
                        pickDetail.setArea(oldDetail.getArea());
                        pickDetail.setShArea(oldDetail.getShArea());
                        pickDetailService.update(pickDetail);
                        pickDetailService.allocate(pickDetail.getId(), pickDetail.getOrderQty());
                        double bcQty = pickDetail.getAllocatedQty();
                        //将出单数写入到订单数
                        pickDetail.setOrderQty(bcQty);
                        pickDetailService.update(pickDetail);
                        //本次出单数量
                        pickTicket.setOrderQuantity(pickTicket.getOrderQuantity() + bcQty);
                        pickTicket.setGcCode(oldDetail.getPickTicket().getGcCode());
                        pickTicketService.update(pickTicket);
                        //回写,刷新补货数量
                        oldDetail.setBcQty(pickDetailRepository.getBcQty(oldDetail.getId()));
                        pickDetailService.update(oldDetail);
                    }
                }
            }
        }
        return new ResponseEntity<>("补料成功",HttpStatus.OK);
    }

}
