package cn.iocoder.foodnexus.module.operations.service.inquirepriceitem;

import cn.iocoder.foodnexus.framework.common.util.CommonUtil;
import cn.iocoder.foodnexus.module.operations.controller.admin.inquiresupplierpush.vo.AppInquireSupplierPushDetailsRespVO;
import cn.iocoder.foodnexus.module.operations.dal.dataobject.inquiresupplierpush.InquireSupplierPushDO;
import cn.iocoder.foodnexus.module.product.dal.dataobject.spu.ProductSpuDO;
import cn.iocoder.foodnexus.module.product.service.category.ProductCategoryService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;

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

import cn.iocoder.foodnexus.module.operations.controller.admin.inquirepriceitem.vo.*;
import cn.iocoder.foodnexus.module.operations.dal.dataobject.inquirepriceitem.InquirePriceItemDO;
import cn.iocoder.foodnexus.framework.common.pojo.PageResult;
import cn.iocoder.foodnexus.framework.common.util.object.BeanUtils;

import cn.iocoder.foodnexus.module.operations.dal.mysql.inquirepriceitem.InquirePriceItemMapper;

import static cn.iocoder.foodnexus.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.foodnexus.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.foodnexus.module.operations.enums.ErrorCodeConstants.*;

/**
 * 询价管理子 Service 实现类
 *
 * @author 超级管理员
 */
@Service
@Validated
public class InquirePriceItemServiceImpl implements InquirePriceItemService {

    @Resource
    private InquirePriceItemMapper inquirePriceItemMapper;

    @Autowired
    private ProductCategoryService productCategoryService;

    @Override
    public Long createInquirePriceItem(InquirePriceItemSaveReqVO createReqVO) {
        // 插入
        InquirePriceItemDO inquirePriceItem = BeanUtils.toBean(createReqVO, InquirePriceItemDO.class);
        inquirePriceItemMapper.insert(inquirePriceItem);

        // 返回
        return inquirePriceItem.getId();
    }

    @Override
    public void updateInquirePriceItem(InquirePriceItemSaveReqVO updateReqVO) {
        // 校验存在
        validateInquirePriceItemExists(updateReqVO.getId());
        // 更新
        InquirePriceItemDO updateObj = BeanUtils.toBean(updateReqVO, InquirePriceItemDO.class);
        inquirePriceItemMapper.updateById(updateObj);
    }

    @Override
    public void deleteInquirePriceItem(Long id) {
        // 校验存在
        validateInquirePriceItemExists(id);
        // 删除
        inquirePriceItemMapper.deleteById(id);
    }

    @Override
        public void deleteInquirePriceItemListByIds(List<Long> ids) {
        // 删除
        inquirePriceItemMapper.deleteByIds(ids);
        }


    private void validateInquirePriceItemExists(Long id) {
        if (inquirePriceItemMapper.selectById(id) == null) {
            throw exception(INQUIRE_PRICE_ITEM_NOT_EXISTS);
        }
    }

    @Override
    public InquirePriceItemDO getInquirePriceItem(Long id) {
        return inquirePriceItemMapper.selectById(id);
    }

    @Override
    public PageResult<InquirePriceItemDO> getInquirePriceItemPage(InquirePriceItemPageReqVO pageReqVO) {
        return inquirePriceItemMapper.selectPage(pageReqVO);
    }

    @Override
    public void addOrUpdateBatch(Long inquireId, List<InquirePriceItemSaveReqVO> items, boolean isUpdate) {
        if (CommonUtil.isEmpty(items)) {
            return ;
        }
        if (isUpdate) {
            // 删除差集数据
            List<InquirePriceItemDO> oriItems = inquirePriceItemMapper.selectList(InquirePriceItemDO::getInquireId, inquireId);
            if (CommonUtil.isNotEmpty(oriItems)) {
                Set<Long> dbItems = oriItems.stream().map(InquirePriceItemDO::getId).collect(Collectors.toSet());
                Set<Long> newItems = items.stream().map(InquirePriceItemSaveReqVO::getId).collect(Collectors.toSet());

                dbItems.removeAll(newItems);

                if (CommonUtil.isNotEmpty(dbItems)) {
                    inquirePriceItemMapper.delete(Wrappers.<InquirePriceItemDO>lambdaQuery()
                            .in(InquirePriceItemDO::getId, dbItems));
                }
            }
        }
        for (InquirePriceItemSaveReqVO item : items) {
            item.setInquireId(inquireId);
            // 重新计算下浮后价格
            item.setFloatingPrice(this.calculateFloatingPrice(item.getMarketPrice(), item.getFloatingRate()));
            item.setCategoryName(productCategoryService.queryNameById(item.getCategoryId()));

            if (CommonUtil.isEmpty(item.getId())) {
                this.createInquirePriceItem(item);
            } else {
                this.updateInquirePriceItem(item);
            }
        }
    }

    @Override
    public List<InquirePriceItemDO> queryByInquireId(Long inquireId) {
        return inquirePriceItemMapper.selectList(InquirePriceItemDO::getInquireId, inquireId);
    }

    @Override
    public Long queryCountByInquirePriceId(Long inquirePriceId) {
        return inquirePriceItemMapper.selectCount(InquirePriceItemDO::getInquireId, inquirePriceId);
    }

    @Override
    public List<InquirePriceItemDO> queryByIds(Collection<Long> collection) {
        if (CommonUtil.isEmpty(collection)) {
            return Lists.newArrayList();
        }
        return inquirePriceItemMapper.selectByIds(collection);
    }

    @Override
    public List<AppInquireSupplierPushDetailsRespVO.Items> queryListWithSupplierQuote(Long inquirePriceId, Long supplierId) {
        MPJLambdaWrapper<InquirePriceItemDO> wrapper = new MPJLambdaWrapper<>();
        wrapper.selectAll(InquirePriceItemDO.class);
        wrapper.selectAs(InquireSupplierPushDO::getSupplierQuote, "supplierQuote");
        wrapper.selectAs(ProductSpuDO::getName, "productName");
        wrapper.innerJoin(InquireSupplierPushDO.class, InquireSupplierPushDO::getInquirePriceItemId, InquirePriceItemDO::getId);
        wrapper.leftJoin(ProductSpuDO.class, ProductSpuDO::getId, InquireSupplierPushDO::getProductId);
        wrapper.eq(InquireSupplierPushDO::getSupplierId, supplierId);
        wrapper.eq(InquirePriceItemDO::getInquireId, inquirePriceId);
        wrapper.orderByDesc(InquirePriceItemDO::getId);
        return inquirePriceItemMapper.selectJoinList(AppInquireSupplierPushDetailsRespVO.Items.class, wrapper);
    }


    // 计算下浮后价格的方法 - 仅对最终结果进行四舍五入
    private Integer calculateFloatingPrice(Integer marketPrice, BigDecimal floatingRate) {
        // 检查市场价是否为null或负数
        if (marketPrice == null || marketPrice < 0) {
            throw exception("市场价必须为非负整数");
        }

        // 如果下浮率为null，默认为0%
        BigDecimal rate = (floatingRate == null) ? BigDecimal.ZERO : floatingRate;

        // 检查下浮率是否为负数
        if (rate.compareTo(BigDecimal.ZERO) < 0) {
            throw exception("下浮率不能为负数");
        }

        // 计算下浮后价格：市场价 × (1 - 下浮率 ÷ 100)
        BigDecimal marketPriceBig = new BigDecimal(marketPrice);
        // 计算比例时保持高精度，不进行四舍五入
        BigDecimal multiplier = BigDecimal.ONE.subtract(rate.divide(new BigDecimal(100), 10, RoundingMode.HALF_UP));
        // 计算中间结果时保持高精度
        BigDecimal intermediateResult = marketPriceBig.multiply(multiplier);
        // 仅在转换为最终结果时进行四舍五入，确保是整数
        BigDecimal finalResult = intermediateResult.setScale(0, RoundingMode.HALF_UP);

        // 转换为整数并赋值
        return finalResult.intValue();
    }

}