/*
*  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 cn.ysk.cashier.service.impl.productimpl;

import cn.hutool.core.util.StrUtil;
import cn.ysk.cashier.dto.product.StockCountDTO;
import cn.ysk.cashier.mybatis.mapper.TbProducSkutMapper;
import cn.ysk.cashier.pojo.order.TbOrderInfo;
import cn.ysk.cashier.pojo.product.TbProductStockDetail;
import cn.ysk.cashier.repository.order.StockCountRepository;
import cn.ysk.cashier.repository.order.TbOrderInfoRepository;
import cn.ysk.cashier.utils.*;
import lombok.RequiredArgsConstructor;
import cn.ysk.cashier.repository.product.TbProductStockDetailRepository;
import cn.ysk.cashier.service.product.TbProductStockDetailService;
import cn.ysk.cashier.dto.product.TbProductStockDetailDto;
import cn.ysk.cashier.dto.product.TbProductStockDetailQueryCriteria;
import cn.ysk.cashier.mapper.product.TbProductStockDetailMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
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.math.BigDecimal;
import java.util.*;
import java.io.IOException;
import javax.persistence.EntityManager;
import javax.servlet.http.HttpServletResponse;

/**
* @website https://eladmin.vip
* @description 服务实现
* @author lyf
* @date 2024-01-19
**/
@Service
@RequiredArgsConstructor
@Slf4j
public class TbProductStockDetailServiceImpl implements TbProductStockDetailService {

    private final TbProductStockDetailRepository tbProductStockDetailRepository;
    private final TbProductStockDetailMapper tbProductStockDetailMapper;

    private final StockCountRepository stockCountRepository;
    private final EntityManager entityManager;
    private final TbOrderInfoRepository tbOrderInfoRepository;
    private final TbProducSkutMapper skutMapper;


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


    @Override
    public Map<String,Object> queryPage(TbProductStockDetailQueryCriteria criteria){
        Sort sort = Sort.by(Sort.Direction.DESC, "id");
        Pageable pageable = PageRequest.of(criteria.getPage(), criteria.getSize(), sort);

        Page<TbProductStockDetail> page = tbProductStockDetailRepository.findAll((root, criteriaQuery, criteriaBuilder)
                -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        Page<TbProductStockDetailDto> map = page.map(tbProductStockDetailMapper::toDto);

        ArrayList<Map<String, Object>> contents = new ArrayList<>();
        for (TbProductStockDetailDto tbProductStockDetailDto : map.getContent()) {
            Map<String, Object> map1 = BeanUtil.transBean2Map(tbProductStockDetailDto);
            if (StrUtil.isNotBlank(tbProductStockDetailDto.getOrderId())) {
                TbOrderInfo tbOrderInfo = tbOrderInfoRepository.findById(Integer.valueOf(tbProductStockDetailDto.getOrderId())).orElse(null);
                if (tbOrderInfo != null) {
                    map1.put("orderNo", tbOrderInfo.getOrderNo());
                }
            }
            contents.add(map1);

            tbProductStockDetailDto.setTypes();
        }
        Map<String,Object> info = new LinkedHashMap<>(2);
        info.put("content",contents);
        info.put("totalElements",page.getTotalElements());
        return info;
    }


    @Override
    public List<TbProductStockDetailDto> queryAll(TbProductStockDetailQueryCriteria criteria){
        return tbProductStockDetailMapper.toDto(tbProductStockDetailRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
    @Transactional
    public TbProductStockDetailDto findById(Long id) {
        TbProductStockDetail tbProductStockDetail = tbProductStockDetailRepository.findById(id).orElseGet(TbProductStockDetail::new);
        ValidationUtil.isNull(tbProductStockDetail.getId(),"TbProductStockDetail","id",id);
        return tbProductStockDetailMapper.toDto(tbProductStockDetail);
    }

    @Override
    public HashMap<String, BigDecimal> sumStockNumber(String productId) {
        BigDecimal bigDecimal = tbProductStockDetailRepository.sumStockNumber(productId);
        HashMap<String, BigDecimal> map = new HashMap<>();
        map.put("exchange",bigDecimal);
        return map;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TbProductStockDetailDto create(TbProductStockDetail resources) {


        return tbProductStockDetailMapper.toDto(tbProductStockDetailRepository.save(resources));
    }

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

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

    @Override
    public void download(List<TbProductStockDetailDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (TbProductStockDetailDto tbProductStockDetail : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("skuId", tbProductStockDetail.getSkuId());
            map.put("商品Id", tbProductStockDetail.getProductId());
            map.put("商品名称", tbProductStockDetail.getProductName());
            map.put("是否开启库存", tbProductStockDetail.getIsStock());
            map.put("规格", tbProductStockDetail.getSpecSnap());
            map.put("商品单位", tbProductStockDetail.getUnitName());
            map.put("店铺Id", tbProductStockDetail.getShopId());
            map.put(" recordId",  tbProductStockDetail.getRecordId());
            map.put("操作批次号", tbProductStockDetail.getBatchNumber());
            map.put("库存操作来源：收银端调用 CASHIER   系统后台调用SHOP", tbProductStockDetail.getSourcePath());
            map.put("关联订单Id", tbProductStockDetail.getOrderId());
            map.put(" 1入库-1出库", tbProductStockDetail.getSubType());
            map.put("purchase采购入库 transfer调拔入库 ", tbProductStockDetail.getType());
            map.put("上次剩余数量", tbProductStockDetail.getLeftNumber());
            map.put("出入库时间", tbProductStockDetail.getStockTime());
            map.put("本次操作库存数量", tbProductStockDetail.getStockNumber());
            map.put("入库合计成本金额", tbProductStockDetail.getCostAmount());
            map.put("出售合计金额", tbProductStockDetail.getSalesAmount());
            map.put("操作人", tbProductStockDetail.getOperator());
            map.put("备注", tbProductStockDetail.getRemark());
            map.put("库存镜像", tbProductStockDetail.getStockSnap());
            map.put(" barCode",  tbProductStockDetail.getBarCode());
            map.put(" coverImg",  tbProductStockDetail.getCoverImg());
            map.put(" createdAt",  tbProductStockDetail.getCreatedAt());
            map.put(" updatedAt",  tbProductStockDetail.getUpdatedAt());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public void addSaleRecord(Integer orderId) {
        List<StockCountDTO> stockCountDTOS = stockCountRepository.countStockById(orderId);
        log.info("查询到订单id: {}的所有库存数据: {}", orderId, stockCountDTOS);
        stockCountDTOS.forEach(s->{
            if (s.getStockCount() > 0) {
                TbProductStockDetail productStockDetail = new TbProductStockDetail();
                productStockDetail.setCreatedAt(System.currentTimeMillis());
                productStockDetail.setUpdatedAt(System.currentTimeMillis());
                productStockDetail.setShopId(s.getShopId());
                productStockDetail.setProductId(s.getProId().toString());
                productStockDetail.setProductName(s.getProName());
                productStockDetail.setOrderId(orderId.toString());
//            productStockDetail.setSkuId(s.getSkuId().toString());
                productStockDetail.setIsStock(s.getIsStock());//是否开启库存
                productStockDetail.setLeftNumber(s.getStockNumber()+s.getStockCount());//原库存
                productStockDetail.setSpecSnap(s.getSpecSnap());
                productStockDetail.setUnitName(s.getUnitName());
                productStockDetail.setStockNumber(-Double.valueOf(s.getStockCount()));
                productStockDetail.setSourcePath("NORMAL");
                productStockDetail.setType("售出记录");
                productStockDetail.setRemark("售出记录:" + orderId);
                productStockDetail.setSubType(-1);
                tbProductStockDetailRepository.save(productStockDetail);
            }
            skutMapper.incrRealSalesNumber(s.getSkuId().intValue(),s.getStockCount());
        });
    }

}
