/*
*  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 cn.hutool.core.date.DateTime;
import com.alibaba.fastjson.JSON;
import com.youchain.basicdata.domain.Point;
import com.youchain.basicdata.domain.Stock;
import com.youchain.businessdata.domain.InventoryLog;
import com.youchain.businessdata.domain.ItemKey;
import com.youchain.utils.*;
import lombok.RequiredArgsConstructor;
import com.youchain.businessdata.repository.InventoryLogRepository;
import com.youchain.businessdata.service.InventoryLogService;
import com.youchain.businessdata.service.dto.InventoryLogDto;
import com.youchain.businessdata.service.dto.InventoryLogQueryCriteria;
import com.youchain.businessdata.service.mapstruct.InventoryLogMapper;
import lombok.extern.slf4j.Slf4j;
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.Date;
import java.sql.Timestamp;
import java.util.*;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;

/**
* @website https://eladmin.vip
* @description 服务实现
* @author houjianlan
* @date 2023-08-31
**/
@Service
@Slf4j
@RequiredArgsConstructor
public class InventoryLogServiceImpl implements InventoryLogService {

    private final InventoryLogRepository inventoryLogRepository;
    private final InventoryLogMapper inventoryLogMapper;

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

    @Override
    public List<InventoryLogDto> queryAll(InventoryLogQueryCriteria criteria){
        List<InventoryLog> list=inventoryLogRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder));
        return inventoryLogMapper.toDto(inventoryLogRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
    @Transactional
    public InventoryLogDto findById(Long id) {
        InventoryLog inventoryLog = inventoryLogRepository.findById(id).orElseGet(InventoryLog::new);
        ValidationUtil.isNull(inventoryLog.getId(),"InventoryLog","id",id);
        return inventoryLogMapper.toDto(inventoryLog);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public InventoryLogDto create(InventoryLog resources) {
        return inventoryLogMapper.toDto(inventoryLogRepository.save(resources));
    }

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

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

    @Override
    public void download(List<InventoryLogDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (InventoryLogDto inventoryLog : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("操作类型", inventoryLog.getLogType());
            map.put("增加/减少", inventoryLog.getIncDec());
            map.put("单据号", inventoryLog.getRelatedBill());
            map.put("点位", inventoryLog.getItemKey());
            map.put("存货日期", inventoryLog.getStoragedate());
            map.put("入库单号", inventoryLog.getSoi());
            map.put("发生数量", inventoryLog.getOccurQuantity());
            map.put("发生时间", inventoryLog.getOccurTime());
            map.put("状态", inventoryLog.getStatus());
            map.put("引用对象", inventoryLog.getRefObj());
            map.put("引用ID", inventoryLog.getRefObjId());
            map.put("描述", inventoryLog.getDescription());
            map.put("仓库ID", inventoryLog.getDept());
            map.put("创建人", inventoryLog.getCreateBy());
            map.put("修改人", inventoryLog.getUpdateBy());
            map.put("创建时间", inventoryLog.getCreateTime());
            map.put("修改时间", inventoryLog.getUpdateTime());
            map.put("源点位", inventoryLog.getSrcPoint());
            map.put("源点位号", inventoryLog.getSrcPointCode());
            map.put("源容器", inventoryLog.getSrcStock());
            map.put("源容器号", inventoryLog.getSrcStockCode());
            map.put("点位", inventoryLog.getDstPoint());
            map.put("目标点位号", inventoryLog.getDstPointCode());
            map.put("目标容器", inventoryLog.getDstStock());
            map.put("目标容器号", inventoryLog.getDstStockCode());
            map.put("源数量", inventoryLog.getSrcQty());
            map.put("目标数量", inventoryLog.getDstQty());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    /**
     * @Description
     * @Author Houjianlan
     * @Date
     */
    @Override
    public InventoryLog storeInventoryLog(String logType, int incDec, String relatedBill,ItemKey itemKey, Point srcPoint, Point dstPoint, Stock srcStock, Stock dstStock,
                       Double srcQty,Double occurQty,String refObj,Long refObjId,Long invId,String description) {
        InventoryLog log =new InventoryLog();
        log.setLogType(logType);
        log.setIncDec(incDec);
        log.setRelatedBill(relatedBill);
        log.setItemKey(itemKey);
        log.setSrcPoint(srcPoint);
        if(srcPoint!=null) {
            log.setSrcPointCode(srcPoint.getCode());
        }
        log.setDstPoint(dstPoint);
        if(dstPoint!=null){
            log.setDstPointCode(dstPoint.getCode());
        }
        log.setSrcStock(srcStock);
        if(srcStock!=null){
            log.setSrcStockCode(srcStock.getCode());
        }
        log.setDstStock(dstStock);
        if(dstStock!=null){
            log.setDstStockCode(dstStock.getCode());
        }
        log.setSrcQty(srcQty);
        log.setOccurQuantity(occurQty);
        if(incDec== BizStatus.ADD){
            log.setDstQty(srcQty+occurQty);
        }else  if(incDec== BizStatus.INVARIANT){
            log.setDstQty(srcQty);
        }else  if(incDec== BizStatus.REDUCE){
            log.setDstQty(srcQty-occurQty);
        }
        log.setOccurTime(new Timestamp(System.currentTimeMillis()));
        log.setRefObj(refObj);
        log.setRefObjId(refObjId);
        log.setInvId(invId);
        log.setDescription(description);
        create(log);
        return log;
    }
}