package com.hys.app.service.erp.impl;

import com.hys.app.converter.erp.SupplierSettlementConverter;
import com.hys.app.converter.erp.SupplierSettlementItemConverter;
import com.hys.app.converter.erp.WarehouseEntryConverter;
import com.hys.app.framework.database.WebPage;
import com.hys.app.framework.exception.ServiceException;
import com.hys.app.framework.database.mybatisplus.base.BaseServiceImpl;
import com.hys.app.framework.util.CurrencyUtil;
import com.hys.app.mapper.erp.SupplierSettlementMapper;
import com.hys.app.model.erp.dos.SupplierSettlementDO;
import com.hys.app.model.erp.dos.SupplierSettlementItemDO;
import com.hys.app.model.erp.dos.WarehouseEntryDO;
import com.hys.app.model.erp.dos.WarehouseEntryProductDO;
import com.hys.app.model.erp.dto.SupplierSettlementDTO;
import com.hys.app.model.erp.dto.SupplierSettlementQueryParams;
import com.hys.app.model.erp.enums.NoBusinessTypeEnum;
import com.hys.app.model.erp.enums.WarehouseEntryStatusEnum;
import com.hys.app.model.erp.vo.SupplierSettlementVO;
import com.hys.app.service.erp.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.hys.app.framework.util.CollectionUtils.convertList;
import static com.hys.app.framework.util.CollectionUtils.convertMultiMap;

/**
 * 供应商结算单业务层实现
 *
 * @author 张崧
 * @since 2023-12-15 14:09:09
 */
@Service
public class SupplierSettlementManagerImpl extends BaseServiceImpl<SupplierSettlementMapper, SupplierSettlementDO> implements SupplierSettlementManager {

    @Autowired
    private SupplierSettlementConverter converter;

    @Autowired
    private SupplierSettlementItemConverter itemConverter;

    @Autowired
    private WarehouseEntryConverter warehouseEntryConverter;

    @Autowired
    private WarehouseEntryManager warehouseEntryManager;

    @Autowired
    private WarehouseEntryProductManager warehouseEntryProductManager;

    @Autowired
    private NoGenerateManager noGenerateManager;

    @Autowired
    private SupplierSettlementItemManager supplierSettlementItemManager;

    @Override
    public WebPage<SupplierSettlementVO> list(SupplierSettlementQueryParams queryParams) {
        WebPage<SupplierSettlementDO> webPage = baseMapper.selectPage(queryParams);

//        List<Long> supplierIds = convertList(webPage.getData(), SupplierSettlementDO::getSupplierId);
//        Map<Long, String> supplierNameMap = supplierManager.listAndConvertMap(supplierIds, SupplierDO::getId, SupplierDO::getCustomName);

        return converter.convert(webPage);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(SupplierSettlementDTO supplierSettlementDTO) {
        check(supplierSettlementDTO);

        // 查询入库单的批次明细，并按入库单id分组
        List<WarehouseEntryProductDO> warehouseEntryProductList = warehouseEntryProductManager.listByWarehouseEntryIds(supplierSettlementDTO.getWarehouseEntryIds());
        Map<Long, List<WarehouseEntryProductDO>> warehouseEntryProductMap = warehouseEntryProductList.stream().collect(Collectors.groupingBy(WarehouseEntryProductDO::getWarehouseEntryId));

        // 入库单按供应商id分组
        Map<Long, List<WarehouseEntryDO>> groupBySupplierId = convertMultiMap(supplierSettlementDTO.getWarehouseEntryList(), WarehouseEntryDO::getSupplierId);

        // 每个供应商生成一个结算单
        List<SupplierSettlementItemDO> allItemList = new ArrayList<>();
        for (List<WarehouseEntryDO> warehouseEntryList : groupBySupplierId.values()) {

            // 结算单明细
            List<SupplierSettlementItemDO> itemList = itemConverter.combination(warehouseEntryList, warehouseEntryProductMap);

            // 保存结算单
            SupplierSettlementDO supplierSettlementDO = new SupplierSettlementDO();
            supplierSettlementDO.setSn(noGenerateManager.generate(NoBusinessTypeEnum.SupplierSettlement));
            supplierSettlementDO.setSupplierId(warehouseEntryList.get(0).getSupplierId());
            supplierSettlementDO.setSupplierName(warehouseEntryList.get(0).getSupplierName());
            supplierSettlementDO.setStartTime(warehouseEntryList.stream().mapToLong(WarehouseEntryDO::getEntryTime).min().getAsLong());
            supplierSettlementDO.setEndTime(warehouseEntryList.stream().mapToLong(WarehouseEntryDO::getEntryTime).max().getAsLong());
            double totalPrice = itemList.stream().mapToDouble(SupplierSettlementItemDO::getTotalPrice).reduce(0, CurrencyUtil::add);
            supplierSettlementDO.setTotalPrice(totalPrice);
            super.save(supplierSettlementDO);

            // 将入库单修改为已结算
            List<Long> warehouseEntryIds = convertList(warehouseEntryList, WarehouseEntryDO::getId);
            warehouseEntryManager.settlementComplete(supplierSettlementDO.getId(), warehouseEntryIds);

            // 填充结算单id
            itemList.forEach(supplierSettlementItemDO -> supplierSettlementItemDO.setSupplierSettlementId(supplierSettlementDO.getId()));
            allItemList.addAll(itemList);
        }

        // 保存结算单明细
        supplierSettlementItemManager.saveBatch(allItemList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void edit(SupplierSettlementDTO supplierSettlementDTO) {
        check(supplierSettlementDTO);
        updateById(converter.convert(supplierSettlementDTO));
    }

    @Override
    public SupplierSettlementVO getDetail(Long id) {
        SupplierSettlementVO supplierSettlementVO = converter.convert(getById(id));
        // 结算单明细
        List<SupplierSettlementItemDO> itemList = supplierSettlementItemManager.listBySupplierSettlementId(id);
        supplierSettlementVO.setItemList(itemConverter.convert(itemList));

        // 结算单下的入库单列表
        List<Long> warehouseEntryIds = itemList.stream().map(SupplierSettlementItemDO::getWarehouseEntryId).distinct().collect(Collectors.toList());
        List<WarehouseEntryDO> warehouseEntryList = warehouseEntryManager.listByIds(warehouseEntryIds);
        supplierSettlementVO.setWarehouseEntryList(warehouseEntryConverter.convert(warehouseEntryList));

        return supplierSettlementVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(List<Long> ids) {
        removeBatchByIds(ids);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancel(Long id) {
        removeById(id);
        supplierSettlementItemManager.deleteBySettlementId(id);
        warehouseEntryManager.settlementCancel(id);
    }

    private void check(SupplierSettlementDTO supplierSettlementDTO) {
        List<WarehouseEntryDO> warehouseEntryList = warehouseEntryManager.listByIds(supplierSettlementDTO.getWarehouseEntryIds());
        if (warehouseEntryList.isEmpty()) {
            throw new ServiceException("入库单不存在");
        }

        for (WarehouseEntryDO warehouseEntryDO : warehouseEntryList) {
            if (warehouseEntryDO.getSupplierSettlementFlag()) {
                throw new ServiceException("入库单：" + warehouseEntryDO.getSn() + "已经生成过结算单");
            }
            if (warehouseEntryDO.getStatus() != WarehouseEntryStatusEnum.AuditPass) {
                throw new ServiceException("入库单：" + warehouseEntryDO.getSn() + "不是已入库状态");
            }
        }


        supplierSettlementDTO.setWarehouseEntryList(warehouseEntryList);
    }

}

