package com.fjhx.service.stock.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.base.Condition;
import com.fjhx.constants.StatusConstant;
import com.fjhx.entity.stock.Stock;
import com.fjhx.entity.water.WaterTag;
import com.fjhx.enums.InTypeEnum;
import com.fjhx.enums.MaterialTypeEnum;
import com.fjhx.mapper.stock.StockMapper;
import com.fjhx.service.stock.StockService;
import com.fjhx.utils.BigDecimalUtil;
import com.fjhx.utils.WrapperUtil;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 库存表 服务实现类
 * </p>
 *
 * @author ${author}
 * @since 2022-09-22
 */
@Service
public class StockServiceImpl extends ServiceImpl<StockMapper, Stock> implements StockService {

    @Override
    public void edit(Enum<?> typeEnum, List<WaterTag> waterTagList) {

        // 标签按物料id分组，统计出改变件数和数量
        Map<Long, Stock> changeStockMap = waterTagList.stream().collect(Collectors.toMap(
                WaterTag::getMaterialId,
                item -> {
                    Stock stock = new Stock();
                    stock.setMaterialId(item.getMaterialId());
                    stock.setNumber(1);
                    stock.setQuantity(stock.getQuantity());
                    return stock;
                },
                (v1, v2) -> {
                    v1.setNumber(v1.getNumber() + v2.getNumber());
                    v1.setQuantity(v1.getQuantity().add(v2.getQuantity()));
                    return v1;
                }
        ));

        // 获取库存信息
        List<Stock> stockList = listByIds(changeStockMap.keySet());
        // 库存信息
        Map<Long, Stock> stockMap = stockList.stream().collect(Collectors.toMap(Stock::getMaterialId, item -> item));

        // 循环改变物料信息
        for (Stock item : changeStockMap.values()) {
            Long materialId = item.getMaterialId();

            // 获取原库存信息
            Stock stock = stockMap.get(materialId);

            // 如果是入库
            if (typeEnum instanceof InTypeEnum) {
                if (stock != null) {
                    stock.setQuantity(stock.getQuantity().add(item.getQuantity()));
                    stock.setNumber(stock.getNumber() + item.getNumber());
                } else {
                    item.setCheckStatus(StatusConstant.NO);
                    stockList.add(item);
                }
            }
            // 如果是出库
            else {
                if (stock != null) {
                    BigDecimal quantity = stock.getQuantity().subtract(item.getQuantity());
                    stock.setQuantity(BigDecimalUtil.max(quantity, BigDecimal.ZERO));

                    int number = stock.getNumber() - item.getNumber();
                    stock.setNumber(Math.max(number, 0));
                }
            }
        }

        // 更新库存信息
        saveOrUpdateBatch(stockList);

    }

    @Override
    public Map<String, Object> statistics() {

        HashMap<String, Object> result = new HashMap<>();

        // 查询统计数据
        List<Map<String, Object>> list = baseMapper.statistics();

        Map<Integer, Map<String, Object>> typeCollect = list.stream().collect(Collectors.toMap(
                item -> Convert.toInt(item.get("technologyType")),
                item -> {
                    Map<String, Object> map = putInfo(item);
                    map.put("type", MaterialTypeEnum.getName(Convert.toInt(item.get("technologyType"))));
                    return map;
                },
                this::addStatistics
        ));

        Map<String, Map<String, Object>> purposeCollect = list.stream()
                .filter(item -> !MaterialTypeEnum.INK.getType().equals(Convert.toInt(item.get("technologyType"))))
                .collect(Collectors.toMap(
                        item -> Convert.toStr(item.get("purpose")),
                        item -> {
                            Map<String, Object> map = putInfo(item);
                            map.put("materialPurpose", item.get("purpose"));
                            return map;
                        },
                        this::addStatistics
                ));

        result.put("ink", typeCollect.get(MaterialTypeEnum.INK.getType()));
        result.put("typeStatistics", Arrays.asList(
                typeCollect.get(MaterialTypeEnum.JET_PRINT.getType()),
                typeCollect.get(MaterialTypeEnum.TRANSFER.getType()),
                typeCollect.get(MaterialTypeEnum.TYPING.getType()),
                typeCollect.get(MaterialTypeEnum.OTHER.getType())
        ));

        Map<String, Object> fabric = addStatistics(
                typeCollect.get(MaterialTypeEnum.JET_PRINT.getType()),
                typeCollect.get(MaterialTypeEnum.TRANSFER.getType()),
                typeCollect.get(MaterialTypeEnum.TYPING.getType()),
                typeCollect.get(MaterialTypeEnum.OTHER.getType())
        );
        fabric.remove("type");
        result.put("fabric", fabric);
        result.put("purposeStatistics", new ArrayList<>(purposeCollect.values()));

        return result;
    }

    @Override
    public Page<Map<String, Object>> getPage(Condition condition) {
        QueryWrapper<?> wrapper = createRemainingTodayWrapper(condition);

        Page<Map<String, Object>> page = baseMapper.getPage(condition.getPage(), wrapper);

        return null;
    }

    /**
     * 赋值统计信息
     */
    private Map<String, Object> putInfo(Map<String, Object> map) {

        HashMap<String, Object> itemMap = new HashMap<>();

        // 卷数
        Integer number = Convert.toInt(map.get("number"));
        // 数量
        BigDecimal quantity = Convert.toBigDecimal(map.get("quantity"));
        // 面积
        BigDecimal area = BigDecimalUtil.init(quantity).multiply(map.get("width")).divide(100, 2).getValue();
        // 金额
        BigDecimal money = BigDecimalUtil.multiply(quantity, map.get("price"), 2);

        itemMap.put("number", number);
        itemMap.put("quantity", quantity);
        itemMap.put("area", area);
        itemMap.put("money", money);

        return itemMap;
    }

    @SafeVarargs
    private final Map<String, Object> addStatistics(Map<String, Object>... item) {
        Map<String, Object> v1 = new HashMap<>(item[0]);

        for (int i = 1; i < item.length; i++) {
            Map<String, Object> v2 = item[i];

            v1.put("number", Convert.toInt(v1.get("number")) + Convert.toInt(v2.get("number")));
            v1.put("quantity", BigDecimalUtil.add(v1.get("quantity"), v2.get("quantity")));
            v1.put("area", BigDecimalUtil.add(v1.get("area"), v2.get("area")));
            v1.put("money", BigDecimalUtil.add(v1.get("money"), v2.get("money")));
        }

        return v1;
    }

    private QueryWrapper<?> createRemainingTodayWrapper(Condition condition) {
        QueryWrapper<?> wrapper = WrapperUtil.init(condition)
                .keyword("m.code", "m.name") // 关键字查询
                .eq("m.material_classify_id", "materialClassifyId") // 物料分类
                .eq("m.purpose", "purpose") // 用途
                .getWrapper();

        // 查询指定分类的物料
        wrapper.and(q -> q.likeRight("m.code", "01.").or().likeRight("m.code", "03.008."));

        Integer inventoryResults = condition.getInt("inventoryResults");
        wrapper.eq(inventoryResults == 0,
                "IF( a.CheckTagCount = a.TagQuantity AND a.CheckTagCount = a.HandTagCount, 1, 0)", inventoryResults);

        // 仓库id
//        Long houseId = condition.getLong("houseId");
//        if (ObjectUtil.isNotEmpty(houseId)) {
//            List<String> materialCodeList = baseMapper.selectMaterialIdByHouseId(houseId);
//            wrapper.in("m.code", materialCodeList);
//        }

        // 工艺类型
        Integer technologyType = condition.getInt("technologyType");
        if (ObjectUtil.isNotEmpty(technologyType)) {
            if (technologyType == 5) {
                wrapper.in("m.TechnologyType", 0, 1, 2, 4);
            } else {
                wrapper.eq("m.TechnologyType", technologyType);
            }
        }

        wrapper.groupBy("m.id");
        wrapper.orderByAsc("m.Name");
        return wrapper;
    }


}
