package com.fjhx.purchase.service.subscribe.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONWriter;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
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.common.service.corporation.CorporationService;
import com.fjhx.item.entity.product.vo.ProductInfoVo;
import com.fjhx.item.service.product.ProductInfoService;
import com.fjhx.purchase.entity.purchase.po.PurchaseDetail;
import com.fjhx.purchase.entity.purchase.vo.PurchaseDetailVo;
import com.fjhx.purchase.entity.subscribe.dto.SubscribeDetailDto;
import com.fjhx.purchase.entity.subscribe.dto.SubscribeDetailSelectDto;
import com.fjhx.purchase.entity.subscribe.po.Subscribe;
import com.fjhx.purchase.entity.subscribe.po.SubscribeDetail;
import com.fjhx.purchase.entity.subscribe.vo.SubscribeDetailVo;
import com.fjhx.purchase.mapper.subscribe.SubscribeDetailMapper;
import com.fjhx.purchase.service.purchase.PurchaseDetailService;
import com.fjhx.purchase.service.subscribe.SubscribeDetailService;
import com.fjhx.tenant.entity.dict.dto.DictTenantDataSelectDto;
import com.fjhx.tenant.entity.dict.vo.DictTenantDataVo;
import com.fjhx.tenant.service.dict.DictTenantDataService;
import com.fjhx.wms.entity.warehouse.po.Warehouse;
import com.fjhx.wms.service.warehouse.WarehouseService;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.wrapper.IWrapper;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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


/**
 * <p>
 * 申购单 服务实现类
 * </p>
 *
 * @author
 * @since 2023-04-03
 */
@DS(SourceConstant.PURCHASE)
@Service
public class SubscribeDetailServiceImpl extends ServiceImpl<SubscribeDetailMapper, SubscribeDetail> implements SubscribeDetailService {

    @Autowired
    private ProductInfoService productInfoService;

    @Autowired
    private WarehouseService warehouseService;

    @Autowired
    private PurchaseDetailService purchaseDetailService;

    @Autowired
    private DictTenantDataService dictTenantDataService;

    @Autowired
    private CorporationService corporationService;

    /**
     * 分页
     *
     * @param dto
     * @return
     */
    @Override
    public Page<SubscribeDetailVo> getPage(SubscribeDetailSelectDto dto) {
        IWrapper<SubscribeDetail> wrapper = getWrapper();
        // 申购单号
        wrapper.like("t2", Subscribe::getCode, dto.getCode());
        // 申购时间
        wrapper.between("t2", Subscribe::getCreateTime, dto.getBeginTime(), dto.getEndTime());
        // 申购状态
        wrapper.ge("t2", Subscribe::getSubcribeStatus, dto.getSubscribeStatus());
        // 关键字
        wrapper.like("t2", Subscribe::getCode, dto.getKeyword());
        // 状态
        if (ObjectUtil.isNotEmpty(dto.getStatus())) {
            wrapper.in("t1", SubscribeDetail::getStatus, Arrays.asList(dto.getStatus().split(",")));
        }

        // 如果类型存在带入类型查询
        List<ProductInfoVo> productList = productInfoService.getListByProductType(
                dto.getProductType(), dto.getDefinition(), dto.getProductName(), dto.getProductCode());
        if (ObjectUtil.isEmpty(productList)) {
            return new Page<>();
        }
        List<Long> productIds = productList.stream().map(ProductInfoVo::getId).collect(Collectors.toList());
        wrapper.in("t1", SubscribeDetail::getBussinessId, productIds);

        // 维多利亚扩展根据到货仓库id过滤
        wrapper.eq("json_unquote(t2.victoriatourist_json -> '$.receiptWarehouseId')", dto.getReceiptWarehouseId());
        if (ObjectUtil.isNotEmpty(dto.getDeptId())) {
            wrapper.eq("json_unquote(pi.victoriatourist_json -> '$.deptId')", dto.getDeptId().toString());
        }

        // 待采购过滤掉指定状态 例如不要 99 作废
        if (StrUtil.isNotBlank(dto.getNeStatus())) {
            wrapper.notIn("t1", SubscribeDetail::getStatus, dto.getNeStatus().split(","));
        }
        wrapper.orderByDesc("t1", SubscribeDetail::getCreateTime);

        Page<SubscribeDetailVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
        List<SubscribeDetailVo> list = page.getRecords();

        if (list.size() == 0) {
            return page;
        }

        // 赋值产品信息
        for (SubscribeDetailVo s : list) {
            Map<Long, ProductInfoVo> productMap = productList.stream().collect(Collectors.toMap(ProductInfoVo::getId, Function.identity()));
            ProductInfoVo productInfo = productMap.get(s.getBussinessId());
            s.setProductCode(productInfo.getCode());
            s.setProductName(productInfo.getName());
            s.setProductType(productInfo.getType());
            s.setProductCategory(productInfo.getClassifyName());
            s.setProductUnit(productInfo.getUnit());
            s.setProductDefinition(productInfo.getDefinition());
            s.setProductCustomCode(productInfo.getCustomCode());
            s.setProductSpec(productInfo.getSpec());

            String victoriatouristJson = productInfo.getVictoriatouristJson();
            JSONObject json = ObjectUtil.isNotEmpty(victoriatouristJson) ? JSONObject.parseObject(victoriatouristJson) : new JSONObject();
            s.setDeptId(json.getLong("deptId"));
        }

        // 赋值采购数量
        List<Long> subscribeDetailIds = list.stream().map(SubscribeDetail::getId).collect(Collectors.toList());
        List<PurchaseDetailVo> purchaseDetailsList = purchaseDetailService.getPurchaseCountListBySubscribeDetailIds(subscribeDetailIds);
//        List<PurchaseDetail> purchaseDetailsList = purchaseDetailService.list(q -> q.in(PurchaseDetail::getSubscribeDetailId, subscribeDetailIds));
        Map<Long, List<PurchaseDetail>> purchaseDetailsMap = purchaseDetailsList.stream().collect(Collectors.groupingBy(PurchaseDetail::getSubscribeDetailId));
        for (SubscribeDetailVo subscribeDetailVo : list) {
            List<PurchaseDetail> purchaseDetails = purchaseDetailsMap.get(subscribeDetailVo.getId());
            if (ObjectUtil.isEmpty(purchaseDetails)) {
                subscribeDetailVo.setPurchaseCount(BigDecimal.ZERO);
                continue;
            }
            BigDecimal count = purchaseDetails.stream().map(PurchaseDetail::getCount).reduce(BigDecimal.ZERO, BigDecimal::add);
            subscribeDetailVo.setPurchaseCount(count);
        }

        corporationService.attributeAssign(list, SubscribeDetailVo::getCorporationId, (item, corporation) -> {
            item.setCorporationName(corporation.getName());
        });

        return page;
    }

    @Override
    public Page<SubscribeDetailVo> getPageByWdly(SubscribeDetailSelectDto dto) {
        Page<SubscribeDetailVo> page = getPage(dto);
        List<SubscribeDetailVo> records = page.getRecords();
        if (ObjectUtil.isEmpty(records)) {
            return page;
        }

        //获取到货仓库id列表
        List<Long> wids = new ArrayList<>();
        for (SubscribeDetailVo subscribeDetailVo : records) {
            String victoriatouristJson = subscribeDetailVo.getVictoriatouristJson();
            if (ObjectUtil.isNotEmpty(victoriatouristJson)) {
                JSONObject json = JSONObject.parseObject(victoriatouristJson);
                wids.add(json.getLong("receiptWarehouseId"));
            }
        }
        //赋值到货仓库名称
        if (ObjectUtil.isNotEmpty(wids)) {
            List<Warehouse> warehouses = warehouseService.listByIds(wids);
            Map<Long, String> warehousesMap = warehouses.stream().collect(Collectors.toMap(Warehouse::getId, Warehouse::getName));
            for (SubscribeDetailVo subscribeDetailVo : records) {
                String victoriatouristJson = subscribeDetailVo.getVictoriatouristJson();
                if (ObjectUtil.isNotEmpty(victoriatouristJson)) {
                    JSONObject json = JSONObject.parseObject(victoriatouristJson);
                    json.put("receiptWarehouseName", warehousesMap.get(json.getLong("receiptWarehouseId")));
                    subscribeDetailVo.setVictoriatouristJson(JSONObject.toJSONString(json,JSONWriter.Feature.WriteLongAsString));
                }
            }
        }
        //赋值采购数量
        for (SubscribeDetailVo record : records) {
            List<PurchaseDetail> list = purchaseDetailService.list(q -> q.eq(PurchaseDetail::getSubscribeDetailId, record.getId()));
            BigDecimal count = list.stream()
                    .map(PurchaseDetail::getCount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            record.setPurchaseCount(count);
        }

        return page;
    }

    /**
     * 根据IDS获取明细
     *
     * @param ids
     * @return
     */
    @Override
    public List<SubscribeDetailVo> detail(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            throw new ServiceException("参数异常");
        }
        List<SubscribeDetailVo> list = baseMapper.getDetail(ids);
        if (CollectionUtils.isNotEmpty(list)) {
            //根据申购businessId取出所有产品
            List<Long> productIds = list.stream().map(SubscribeDetail::getBussinessId).collect(Collectors.toList());
            List<ProductInfoVo> productInfoVos = productInfoService.getListByProductIds(productIds);
            Map<Long, List<ProductInfoVo>> productMap = productInfoVos.stream().collect(Collectors.groupingBy(ProductInfoVo::getId));
            for (SubscribeDetailVo s : list) {
                if (MapUtils.isNotEmpty(productMap)) {
                    ProductInfoVo p = productMap.get(s.getBussinessId()).get(0);
                    s.setProductCategory(p.getClassifyName());
                    s.setProductCode(p.getCode());
                    s.setProductUnit(p.getUnit());
                    s.setProductType(p.getType());
                    s.setProductName(p.getName());
                    s.setProductSpec(p.getSpec());
                    s.setProductCustomCode(p.getCustomCode());
                    s.setProductDefinition(p.getDefinition());

                    //维多利亚赋值部门id
                    String victoriatouristJson = p.getVictoriatouristJson();
                    JSONObject json = ObjectUtil.isNotEmpty(victoriatouristJson) ? JSONObject.parseObject(victoriatouristJson) : new JSONObject();
                    s.setDeptId(json.getLong("deptId"));
                }
            }
        }
        return list;
    }

    @Override
    public void add(SubscribeDetailDto subscribeDetailDto) {
        this.save(subscribeDetailDto);
    }

    @Override
    public void edit(SubscribeDetailDto subscribeDetailDto) {
        this.updateById(subscribeDetailDto);
    }

    @Override
    public void delete(Long id) {
        this.removeById(id);
    }

    /**
     * 申购统计（申购单分页）
     */
    @Override
    public Map<String, Object> subscribeStatistics(SubscribeDetailSelectDto dto) {
        //存放申购统计数据
        Map<String, Object> map = new HashMap<>();

        //存放申购统计详情数据
        List<Map<String,Object>> list = new ArrayList<>();

        QueryWrapper<Object> query = Wrappers.query();
        query.groupBy("pi.type");
        //查询申购统计（产品类型分组）
        List<SubscribeDetailVo> subscribeDetailVos = baseMapper.subscribeStatistics(query);
        Map<String, List<SubscribeDetailVo>> subscribeDetailVoMap = subscribeDetailVos.stream()
                .collect(Collectors.groupingBy(SubscribeDetailVo::getType));

        //计算申购笔合计数据
        Integer amount = subscribeDetailVos.stream().map(SubscribeDetailVo::getCounts).reduce(Integer::sum).orElse(0);
        map.put("amount",amount);
        //计算申购货品种类合计数据
        Integer typeAmount = subscribeDetailVos.stream().map(SubscribeDetailVo::getTypeCount).reduce(Integer::sum).orElse(0);
        map.put("typeAmount",typeAmount);
        //切换数据源
        DynamicDataSourceContextHolder.push(SourceConstant.BASE);
        //获取产品类型字典数据
        List<DictTenantDataVo> dictTenantDataVoList = getDict("product_type");
        DynamicDataSourceContextHolder.poll();

        if (ObjectUtil.isEmpty(dictTenantDataVoList)){
            throw  new ServiceException("数据有误：产品没有配置产品类型字典，请先添加产品类型字典");
        }

        //赋值笔数、货品种类数据
        for (DictTenantDataVo dictTenantDataVo : dictTenantDataVoList) {
            //设置初始值
            Map<String,Object> typeMap = new HashMap<>();
            typeMap.put("type",dictTenantDataVo.getDictValue());
            typeMap.put("count",0);
            typeMap.put("typeCount",0);

            //赋值
            List<SubscribeDetailVo> subscribeDetailVoList = subscribeDetailVoMap.get(dictTenantDataVo.getDictKey());
            if (ObjectUtil.isNotEmpty(subscribeDetailVoList)){
                typeMap.put("count",subscribeDetailVoList.get(0).getCounts());
                typeMap.put("typeCount",subscribeDetailVoList.get(0).getTypeCount());
            }
            list.add(typeMap);
        }
        map.put("productTypeList",list);
        return map;
    }

    //根据字典编码获取字典的数据
    private List<DictTenantDataVo> getDict(String code){
        DictTenantDataSelectDto dto = new DictTenantDataSelectDto();
        dto.setDictCode(code);
        return dictTenantDataService.getList(dto);
    }

}
