/*
*  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.BomAccount;
import com.youchain.basicdata.domain.Point;
import com.youchain.basicdata.service.BomAccountService;
import com.youchain.basicdata.service.PointService;
import com.youchain.businessdata.domain.Inventory;
import com.youchain.businessdata.domain.InventoryLog;
import com.youchain.businessdata.domain.ItemKey;
import com.youchain.businessdata.domain.Spareparts;
import com.youchain.businessdata.service.InventoryLogService;
import com.youchain.businessdata.service.InventoryService;
import com.youchain.businessdata.service.ItemKeyService;
import com.youchain.exception.BadRequestException;
import com.youchain.modules.system.service.DictDetailService;
import com.youchain.utils.*;
import lombok.RequiredArgsConstructor;
import com.youchain.businessdata.repository.SparepartsRepository;
import com.youchain.businessdata.service.SparepartsService;
import com.youchain.businessdata.service.dto.SparepartsDto;
import com.youchain.businessdata.service.dto.SparepartsQueryCriteria;
import com.youchain.businessdata.service.mapstruct.SparepartsMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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;

/**
* @website https://eladmin.vip
* @description 服务实现
* @author ShenYinAn
* @date 2024-01-30
**/
@Service
@Slf4j
@RequiredArgsConstructor
public class SparepartsServiceImpl implements SparepartsService {

    private final SparepartsRepository sparepartsRepository;
    private final SparepartsMapper sparepartsMapper;
    private final InventoryService inventoryService;
    private final InventoryLogService inventoryLogService;
    private final BomAccountService bomAccountService;
    private final DictDetailService dictDetailService;
    private final PointService pointService;
    private final ItemKeyService itemKeyService;

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

    @Override
    public List<SparepartsDto> queryAll(SparepartsQueryCriteria criteria){
        return sparepartsMapper.toDto(sparepartsRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
    @Transactional
    public SparepartsDto findById(Long id) {
        Spareparts spareparts = sparepartsRepository.findById(id).orElseGet(Spareparts::new);
        ValidationUtil.isNull(spareparts.getId(),"Spareparts","id",id);
        return sparepartsMapper.toDto(spareparts);
    }

    @Override
    @Transactional
    public Spareparts getEntity(Long id) {
        Spareparts spareparts = sparepartsRepository.findById(id).orElseGet(Spareparts::new);
        return spareparts;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SparepartsDto create(Spareparts resources) {
        return sparepartsMapper.toDto(sparepartsRepository.save(resources));
    }

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

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

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

    public void hySpareParts(Long id){
        Spareparts s=this.getEntity(id);
        if(!s.getStatus().equals(BizStatus.UN_CONSUME)){
            throw new BadRequestException("状态必须未未耗用");
        }
        String gw=s.getStationType();
        List<BomAccount> bs = bomAccountService.queryBomAccount(s.getBigItemId().getId(), null,gw);
        if (bs.size() <= 0) {
            throw new BadRequestException(s.getBigItemId().getCode() + "未查到对应工位清单");
        }
        for(BomAccount ba:bs){
            if(ba.getZPoint()==null){
                throw new BadRequestException(ba.getItem().getCode()+"维护制造库位");
            }
            double qty=s.getOrderQuantity()*ba.getSingles();
            log.info(ba.getId()+"=="+ba.getItem().getId());
            //扣除线边库存
            List<Inventory> inventorys=inventoryService.getXbHyInv(ba.getItem(),ba.getRArea(),gw,ba.getZPoint(),"耗用");
            if(inventorys.size()>0){
                int num=0;
                for(Inventory inv:inventorys){
                    if(qty<=0){
                        break;
                    }
                    num++;
                    if(num<inventorys.size()&&inv.getQuantity()<=0){
                        continue;
                    }
                    double srcQty=inv.getQuantity();
                    double hyQty=0;
                    if(inv.getQuantity()>qty||num==inventorys.size()){
                        hyQty=qty;
                        qty-=hyQty;
                    }else{
                        hyQty=inv.getQuantity();
                        qty-=hyQty;
                    }
                    inv.setQuantity(inv.getQuantity()-hyQty);
                    inventoryService.update(inv);
                    InventoryLog log= inventoryLogService.storeInventoryLog(BizStatus.XB_HY,-1,ba.getBigItem().getCode(),ba.getRArea(),inv.getItemKey(),
                            inv.getPoint(),inv.getPoint(),null,null,srcQty,hyQty,null,null,s.getBigItemId().getCode(),
                            s.getId(),inv.getId(),"零件耗用");
                    log.setZzkw(ba.getZPoint());
                    inventoryLogService.update(log);
                }
            }else{
//                Point point=ba.getCArea().getPoint();
                Point point=pointService.findEntityById(ba.getRArea().getPointId());
                if(point==null){
                    throw new BadRequestException(ba.getRArea().getCode()+"库区无对应待投料库位");
                }
                ItemKey itemKey=itemKeyService.getItemKey(ba.getItem(),null,null,null,null,null,null);
                Inventory inventory = new Inventory();
                inventory.setItemKey(itemKey);
                inventory.setPoint(point);
                inventory.setPointCode(point.getCode());
                inventory.setZzkw(ba.getZPoint());
                inventory.setDept(UserUtils.getDept());
                inventory.setArea(ba.getRArea());
                inventory.setQuantity(-qty);
                inventoryService.create(inventory);
                InventoryLog log=inventoryLogService.storeInventoryLog(BizStatus.XB_HY,-1,ba.getBigItem().getCode(),ba.getRArea(),inventory.getItemKey(),
                        inventory.getPoint(),inventory.getPoint(),null,null,0d,qty,null,null,s.getBigItemId().getCode(),
                        s.getId(),inventory.getId(),"零件耗用");
                log.setZzkw(ba.getZPoint());
                inventoryLogService.update(log);
            }
        }
        s.setStatus(BizStatus.CONSUME);
        s.setHyBy(SecurityUtils.getCurrentUsername());
        s.setHyTime(new Timestamp(new Date().getTime()));
        this.update(s);
    }
}
