/*
 *  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.service.impl;

import com.youchain.basicdata.domain.Area;
import com.youchain.basicdata.domain.BomAccount;
import com.youchain.basicdata.repository.BillTypeRepository;
import com.youchain.basicdata.repository.BomAccountRepository;
import com.youchain.businessdata.domain.PickDetail;
import com.youchain.businessdata.domain.PickInstruction;
import com.youchain.businessdata.domain.PickTicket;
import com.youchain.businessdata.repository.PickDetailRepository;
import com.youchain.businessdata.repository.PickTicketRepository;
import com.youchain.businessdata.service.InventoryService;
import com.youchain.businessdata.service.PickDetailService;
import com.youchain.businessdata.service.PickTicketService;
import com.youchain.businessdata.service.dto.PickDetailDto;
import com.youchain.businessdata.service.dto.PickTicketDto;
import com.youchain.businessdata.service.mapstruct.PickTicketMapper;
import com.youchain.exception.BadRequestException;
import com.youchain.utils.*;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import com.youchain.businessdata.repository.PickInstructionRepository;
import com.youchain.businessdata.service.PickInstructionService;
import com.youchain.businessdata.service.dto.PickInstructionDto;
import com.youchain.businessdata.service.dto.PickInstructionQueryCriteria;
import com.youchain.businessdata.service.mapstruct.PickInstructionMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.sql.Timestamp;
import java.util.*;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;

/**
 * @author DengJiangKun
 * @website https://eladmin.vip
 * @description 服务实现
 * @date 2024-02-28
 **/
@Service
@RequiredArgsConstructor
public class PickInstructionServiceImpl implements PickInstructionService {

    private final PickInstructionRepository pickInstructionRepository;
    private final PickInstructionMapper pickInstructionMapper;
    private final BillTypeRepository billTypeRepository;
    private final PickTicketService pickTicketService;
    private final PickTicketRepository pickTicketRepository;
    private final PickTicketMapper pickTicketMapper;
    private final PickDetailService pickDetailService;
    private final PickDetailRepository pickDetailRepository;
    private final CodeUtils codeUtils;
    private final BomAccountRepository bomAccountRepository;
    private final InventoryService inventoryService;

    @Override
    public Map<String, Object> queryAll(PickInstructionQueryCriteria criteria, Pageable pageable) {
        Page<PickInstruction> page = pickInstructionRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        return PageUtil.toPage(page.map(pickInstructionMapper::toDto));
    }

    @Override
    public List<PickInstructionDto> queryAll(PickInstructionQueryCriteria criteria) {
        return pickInstructionMapper.toDto(pickInstructionRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder)));
    }

    @Override
    @Transactional
    public PickInstructionDto findById(Long id) {
        PickInstruction pickInstruction = pickInstructionRepository.findById(id).orElseGet(PickInstruction::new);
        ValidationUtil.isNull(pickInstruction.getId(), "PickInstruction", "id", id);
        return pickInstructionMapper.toDto(pickInstruction);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PickInstructionDto create(PickInstruction resources) {
        return pickInstructionMapper.toDto(pickInstructionRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(PickInstruction resources) {
        PickInstruction pickInstruction = pickInstructionRepository.findById(resources.getId()).orElseGet(PickInstruction::new);
        ValidationUtil.isNull(pickInstruction.getId(), "PickInstruction", "id", resources.getId());
        pickInstruction.copy(resources);
        pickInstructionRepository.save(pickInstruction);
    }

    @Override
    public void deleteAll(Long[] ids) {
        for (Long id : ids) {
            pickInstructionRepository.deleteById(id);
        }
    }

    @Override
    public void download(List<PickInstructionDto> all, HttpServletResponse response) throws Exception {
        List<Map<String, Object>>  list= ExcelDownUtils.CreateMap(all,"PickInstruction");
        FileUtil.downloadExcel(list, response);
    }

    @Override
    @Transactional
    public void generatePrepFlag(Long[] ids) throws Exception {
        List<PickInstruction> pickInstructions = pickInstructionRepository.queryPinckInsAllByLongS(ids);
        if (pickInstructions.isEmpty()) {
            throw new BadRequestException("未查到数据");
        }
        List<PickInstruction> details=new ArrayList<PickInstruction>();
        Area ckArea = null;
        Area rkArea = null;
        //全部的订单数
        Double allNum = 0d;
        String code=null;
        for (PickInstruction pickInstruction : pickInstructions) {
            if (ckArea == null) {
                ckArea = pickInstruction.getCkArea();
            } else {
                if (!Objects.equals(ckArea.getId(), pickInstruction.getCkArea().getId())) {
                    throw new BadRequestException("你选的出库库区不同");
                }
            }
            if (rkArea == null) {
                rkArea = pickInstruction.getRkArea();
            } else {
                if (!Objects.equals(rkArea.getId(), pickInstruction.getRkArea().getId())) {
                    throw new BadRequestException("你选的入库库区不同");
                }
            }
            allNum += pickInstruction.getIndicatedQty() - pickInstruction.getAllocatedQty();
            if(pickInstruction.getIndicatedQty() - pickInstruction.getAllocatedQty()>0){
                details.add(pickInstruction);
            }
            code=pickInstruction.getAllocationNumber();
        }
        if(details.size()<=0){
            throw new BadRequestException("已全部出单");
        }
        //生成pickTicket
        PickTicket pickTicket = pickTicketService.storePick(billTypeRepository.findByName(BaseStatus.BT_DD), rkArea,ckArea, "大", code);
        pickTicket.setOrderQuantity(allNum);
        pickTicket.setGcCode(rkArea.getGcCode());
        //成功的订单数据
        Double cgNumber = 0d;
        for (PickInstruction pickInstruction : details) {
            //出单数量
            Double bcAllocatedQty = 0d;
            Double invQty=inventoryService.getInvQty(pickInstruction.getItem().getId(),ckArea.getId(),null);
            if(invQty.intValue()<=0){
                continue;
            }
            double xqQty=pickInstruction.getIndicatedQty()- pickInstruction.getAllocatedQty();
            if(xqQty>invQty){
                xqQty=invQty;
            }
            //已出单数量
            PickDetail pickDetail = new PickDetail();
            pickDetail.setShArea(rkArea);
            pickDetail.setArea(ckArea);
            pickDetail.setItem(pickInstruction.getItem());
            pickDetail.setOrderQty(xqQty);
            pickDetail.setPickTicket(pickTicket);
            pickDetail.setPoint(pickInstruction.getZzkwPoint());
            pickDetail.setPropC3(pickInstruction.getAllocationNumber());
            pickDetail.setStatus(BizStatus.OPEN);
            pickDetail.setPickId(pickInstruction.getId());
            if(pickInstruction.getBomId()!=null) {
                BomAccount bomAccount = bomAccountRepository.getById(pickInstruction.getBomId());
                if (bomAccount != null) {
                    pickDetail.setAc(bomAccount.getAc());
                    pickDetail.setSupplier(bomAccount.getSupplier());
                    pickDetail.setContents(bomAccount.getContents());
                }
            }
            PickDetail pickDetailDto = pickDetailRepository.save(pickDetail);
            pickDetailService.allocate(pickDetailDto.getId(), pickDetailDto.getOrderQty());
            bcAllocatedQty = pickDetail.getAllocatedQty();
            //回写
            pickInstruction.setAllocatedQty(pickInstruction.getAllocatedQty()+bcAllocatedQty);
            //本次出单数量
            pickInstruction.setBcAllocatedQty(bcAllocatedQty);
            pickInstruction.setStatus(BizStatus.YCD);
            this.update(pickInstruction);
        }
    }
}