package com.fjhx.victoriatourist.service.group.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.common.constant.SourceConstant;
import com.fjhx.item.entity.product.po.ProductInfo;
import com.fjhx.item.service.product.ProductInfoService;
import com.fjhx.victoriatourist.entity.group.dto.GetCombinableQuantityDto;
import com.fjhx.victoriatourist.entity.group.dto.GroupRecordDetailsSelectDto;
import com.fjhx.victoriatourist.entity.group.dto.GroupRecordDto;
import com.fjhx.victoriatourist.entity.group.po.GroupRecordDetails;
import com.fjhx.victoriatourist.entity.group.vo.GetCombinableQuantityVo;
import com.fjhx.victoriatourist.entity.group.vo.GroupRecordDetailsVo;
import com.fjhx.victoriatourist.mapper.group.GroupRecordDetailsMapper;
import com.fjhx.victoriatourist.service.group.GroupRecordDetailsService;
import com.fjhx.victoriatourist.service.group.GroupRecordService;
import com.fjhx.wms.entity.stock.bo.InOutBo;
import com.fjhx.wms.entity.stock.emums.JournalType;
import com.fjhx.wms.entity.stock.po.Stock;
import com.fjhx.wms.service.stock.StockService;
import com.fjhx.wms.service.warehouse.WarehouseService;
import com.ruoyi.common.core.domain.BaseIdPo;
import com.ruoyi.common.core.domain.BasePo;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.wrapper.IWrapper;
import com.ruoyi.system.utils.UserUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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


/**
 * <p>
 * 组合记录明细 服务实现类
 * </p>
 *
 * @author
 * @since 2023-04-18
 */
@Service
public class GroupRecordDetailsServiceImpl extends ServiceImpl<GroupRecordDetailsMapper, GroupRecordDetails> implements GroupRecordDetailsService {

    @Autowired
    private WarehouseService warehouseService;

    @Autowired
    private ProductInfoService productInfoService;

    @Autowired
    private StockService stockService;

    @Autowired
    private GroupRecordService groupRecordService;

    @Override
    public Page<GroupRecordDetailsVo> getPage(GroupRecordDetailsSelectDto dto) {
        IWrapper<GroupRecordDetails> wrapper = getWrapper();
        wrapper.eq("grd", GroupRecordDetails::getType, dto.getType());
        wrapper.orderByDesc("grd", GroupRecordDetails::getId);

        Page<GroupRecordDetailsVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);

        List<GroupRecordDetailsVo> records = page.getRecords();
        if (records.size() == 0) {
            return page;
        }

        // 操作人
        UserUtil.assignmentNickName(records, BasePo::getCreateUser, GroupRecordDetailsVo::setCreateUserName);

        // 半成品、组合后放置仓库id
//        DynamicDataSourceContextHolder.push(SourceConstant.WMS);
        warehouseService.attributeAssignBuilder(records)
                .assignFun(GroupRecordDetails::getGroupWarehouseId, (item, warehouse) ->
                        item.setGroupWarehouseName(warehouse.getName()))
                .assignFun(GroupRecordDetails::getProductWarehouseId, (item, warehouse) ->
                        item.setProductWarehouseName(warehouse.getName()))
                .build();
//        DynamicDataSourceContextHolder.poll();

        // 产品信息
        productInfoService.attributeAssign(records, GroupRecordDetails::getProductId, (item, product) -> {
            item.setProductCode(product.getCode());
            item.setProductName(product.getName());
            item.setProductSpec(product.getSpec());
        });

        return page;
    }

    @Override
    public List<GroupRecordDetailsVo> detail(Long id) {
        if (id == null) {
            throw new ServiceException("产品组合记录id不能为空");
        }
        List<GroupRecordDetails> list = list(q -> q.eq(GroupRecordDetails::getGroupRecordId, id));
        List<GroupRecordDetailsVo> groupRecordDetails = BeanUtil.copyToList(list, GroupRecordDetailsVo.class);
        // 产品信息
        productInfoService.attributeAssign(groupRecordDetails, GroupRecordDetails::getProductId, (item, product) -> {
            item.setProductCode(product.getCode());
            item.setProductName(product.getName());
            item.setProductSpec(product.getSpec());
        });
        return groupRecordDetails;
    }

    @Override
    public GetCombinableQuantityVo getCombinableQuantity(GetCombinableQuantityDto dto) {

        List<Long> productIdList = dto.getProductIdList();
        List<ProductInfo> productInfoList = productInfoService.listByIds(productIdList);
        if (productInfoList.size() == 0) {
            throw new ServiceException("产品列表为空");
        }

        Map<Long, Map<Long, BigDecimal>> combinableQuantity = new HashMap<>();
        Set<Long> productIdSet = new HashSet<>();
        for (ProductInfo productInfo : productInfoList) {
            Map<Long, BigDecimal> groupProductNumMap = getGroupProductNumMap(productInfo);
            combinableQuantity.put(productInfo.getId(), groupProductNumMap);
            productIdSet.addAll(groupProductNumMap.keySet());
        }

        List<Stock> stockList = stockService.list(q -> q
                .in(Stock::getProductId, productIdSet)
                .eq(Stock::getWarehouseId, dto.getWarehouseId()));

        Map<Long, BigDecimal> stockMap = stockList.stream().collect(Collectors.toMap(
                Stock::getProductId,
                Stock::getQuantity
        ));

        GetCombinableQuantityVo vo = new GetCombinableQuantityVo();
        vo.setCombinableQuantity(combinableQuantity);
        vo.setStockMap(stockMap);
        return vo;
    }

    @DSTransactional
    @Override
    public void add(GroupRecordDto dto) {

        // 添加组合主表
        groupRecordService.save(dto);

        List<GroupRecordDetails> groupRecordDetailsList = dto.getGroupRecordDetailsList();
        groupRecordDetailsList.forEach(item -> {
            item.setGroupRecordId(dto.getId());
            item.setType(dto.getType());
            item.setGroupWarehouseId(dto.getGroupWarehouseId());
            item.setProductWarehouseId(dto.getProductWarehouseId());
        });

        // 添加组合明细表
        saveBatch(groupRecordDetailsList);

        // 组合产品id
        List<Long> productIdList = groupRecordDetailsList.stream()
                .map(GroupRecordDetails::getProductId).collect(Collectors.toList());
        // 组合产品信息
        Map<Long, ProductInfo> productInfoMap = productInfoService.mapKEntity(
                BaseIdPo::getId, q -> q.in(BaseIdPo::getId, productIdList));

        for (GroupRecordDetails groupRecordDetails : groupRecordDetailsList) {

            // 获取组合产品有哪些半成品组合而成
            ProductInfo productInfo = productInfoMap.get(groupRecordDetails.getProductId());
            Map<Long, BigDecimal> groupProductNumMap = getGroupProductNumMap(productInfo);

            InOutBo bo = new InOutBo();
            bo.setProductId(groupRecordDetails.getProductId());
            bo.setQuantity(groupRecordDetails.getGroupNum());

            List<InOutBo> boList = new ArrayList<>();
            groupProductNumMap.forEach((k, v) -> {
                InOutBo outBo = new InOutBo();
                outBo.setProductId(k);
                outBo.setQuantity(v.multiply(groupRecordDetails.getGroupNum()));
                boList.add(outBo);
            });

            // 组合产品入库或出库
            stockService.inOut(Collections.singletonList(bo),
                    dto.getGroupWarehouseId(),
                    dto.getType() == 1 ? JournalType.COMBINATION_IN : JournalType.SPLIT_OUT,
                    groupRecordDetails.getId());

            // 半成品出库或入库
            stockService.inOut(boList,
                    dto.getProductWarehouseId(),
                    dto.getType() == 1 ? JournalType.COMBINATION_OUT : JournalType.SPLIT_IN,
                    groupRecordDetails.getId());
        }

    }

    /**
     * 获取组合关联产品数量
     */
    private Map<Long, BigDecimal> getGroupProductNumMap(ProductInfo productInfo) {
        String victoriatouristJson = productInfo.getVictoriatouristJson();
        if (StrUtil.isBlank(victoriatouristJson)) {
            throw new ServiceException("id为" + productInfo.getId() + "的产品victoriatouristJson字段为空");
        }

        JSONObject json = JSON.parseObject(victoriatouristJson);
        JSONArray productCombinationList = json.getJSONArray("productCombinationList");
        if (ObjectUtil.isEmpty(productCombinationList)) {
            throw new ServiceException("id为" + productInfo.getId() + "的产品组合信息为空");
        }

        // 获取组合所需产品和数量
        List<JSONObject> list = productCombinationList.toJavaList(JSONObject.class);
        return list.stream().collect(Collectors.toMap(
                item -> item.getLong("linkProductId"),
                item -> item.getBigDecimal("linkQuantity"),
                BigDecimal::add
        ));
    }

}
