package com.wzj.soopin.goods.business;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wzj.soopin.goods.convert.ProductConvert;
import com.wzj.soopin.goods.convert.SkuConvert;
import com.wzj.soopin.goods.domain.bo.ProductBo;
import com.wzj.soopin.goods.domain.bo.SkuBo;
import com.wzj.soopin.goods.domain.entity.Product;
import com.wzj.soopin.goods.domain.entity.ProductSnapshot;
import com.wzj.soopin.goods.domain.entity.Sku;
import com.wzj.soopin.goods.domain.entity.SkuSnapshot;
import com.wzj.soopin.goods.domain.vo.ProductVO;
import com.wzj.soopin.goods.enums.ProductAuthFlag;
import com.wzj.soopin.goods.service.ProductService;
import com.wzj.soopin.goods.service.ProductSnapshotService;
import com.wzj.soopin.goods.service.SkuService;
import com.wzj.soopin.goods.service.SkuSnapshotService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.event.Constants;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.tenant.helper.TenantHelper;
import org.dromara.common.web.core.BusinessImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@Slf4j
@AllArgsConstructor
public class ProductBusinessImpl extends BusinessImpl<ProductService, ProductConvert, ProductVO, ProductBo, Product> implements IProductBusiness {

    private final ProductService productService;
    private final SkuService skuService;
    private final SkuConvert skuConvert;
    private final ProductSnapshotService productSnapshotService;
    private final SkuSnapshotService skuSnapshotService;


    @Override
    public Page<ProductVO> page(ProductBo bo) {
        Page<Product> page = new Page<>();
        page.setCurrent(bo.getCurrent());
        page.setSize(bo.getSize());
        return productService.getList(bo, page);
    }

    /**
     * 查询商品信息
     *
     * @param id 商品信息主键
     * @return 商品信息
     */
    @Override
    public ProductVO info(Long id) {
        return productService.selectById(id);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean save(ProductBo bo) {
        boolean result;
        Product product = converter.toPo(bo);
        product.setType(1);
        product.setSales("0");
        product.setTenantId(TenantHelper.getTenantId());
        if (bo.getId() == null) {
            product.setAuthFlag(ProductAuthFlag.WAIT_AUDIT.getCode());
            product.setPublishStatus(Constants.PublishStatus.UNDERCARRIAGE);
            result = productService.save(product);
        } else {
            Product po = productService.getById(bo.getId());
            Assert.notNull(po, () -> new ServiceException("商品信息不存在"));
            Assert.isTrue(po.getPublishStatus().equals(Constants.PublishStatus.UNDERCARRIAGE)
                    && (po.getAuthFlag().equals(ProductAuthFlag.WAIT_AUDIT.getCode()) || po.getAuthFlag().equals(ProductAuthFlag.AUDIT_REJECT.getCode()))
                , () -> new ServiceException("仅下架且未审核通过的商品可编辑"));
            result = productService.updateById(product);
        }
        // 新增则直接保存sku信息
        if (bo.getId() == null) {
            List<Sku> skus = bo.getSkuList().stream().map(skuBO -> {
                Sku sku = skuConvert.toPo(skuBO);
                sku.setProductId(product.getId());
                sku.setTenantId(TenantHelper.getTenantId());
                return sku;
            }).collect(Collectors.toList());
            result = skuService.insertBatch(skus);
        } else {
            // 更新需按照新sku信息和旧sku信息对比，id一致的数据更新，新sku信息中id缺失的要删除，没有id的要新增
            List<SkuBo> skuList = bo.getSkuList();
            List<Sku> oldSkus = skuService.getByProductId(bo.getId());

            // 分离需要更新、新增和删除的SKU
            List<Sku> skusToUpdate = skuList.stream()
                .filter(skuBo -> skuBo.getId() != null)
                .map(skuBO -> {
                    Sku sku = skuConvert.toPo(skuBO);
                    sku.setId(skuBO.getId());
                    sku.setProductId(product.getId());
                    sku.setTenantId(TenantHelper.getTenantId());
                    return sku;
                })
                .collect(Collectors.toList());

            List<Sku> skusToSave = skuList.stream()
                .filter(skuBo -> skuBo.getId() == null)
                .map(skuBO -> {
                    Sku sku = skuConvert.toPo(skuBO);
                    sku.setProductId(product.getId());
                    sku.setTenantId(TenantHelper.getTenantId());
                    return sku;
                })
                .collect(Collectors.toList());

            // 获取旧SKU ID列表和当前提交的SKU ID列表
            List<Long> oldSkuIds = oldSkus.stream()
                .map(Sku::getId)
                .collect(Collectors.toList());
            List<Long> currentSkuIds = skuList.stream()
                .map(SkuBo::getId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

            // 找出需要删除的SKU ID（在旧列表中但不在当前列表中的）
            List<Long> skusToDelete = oldSkuIds.stream()
                .filter(id -> !currentSkuIds.contains(id))
                .collect(Collectors.toList());

            // 执行更新操作
            if (CollectionUtils.isNotEmpty(skusToUpdate)) {
                result = skuService.updateBatchById(skusToUpdate) && result;
            }

            // 执行新增操作
            if (CollectionUtils.isNotEmpty(skusToSave)) {
                result = skuService.insertBatch(skusToSave) && result;
            }

            // 执行删除操作
            if (CollectionUtils.isNotEmpty(skusToDelete)) {
                result = skuService.removeByIds(skusToDelete) && result;
            }
        }
        return result;
    }


    @Override
    public boolean audit(Long id, Integer authFlag, String reasons) {
        Product productToUpdate = productService.getById(id);
        if (productToUpdate == null) {
            throw new RuntimeException("商品不存在");
        }
        Assert.isTrue(!productToUpdate.getPublishStatus().equals(Constants.PublishStatus.GROUNDING), () -> new ServiceException("上架中的商品不可审核"));
        productToUpdate.setAuthFlag(authFlag);
        productToUpdate.setReasons(reasons);
        productService.updateById(productToUpdate);
        return true;
    }

    @Override
    @Transactional
    public boolean publish(Long id, Integer publishStatus) {
        Product product = productService.getById(id);
        if (product == null) {
            throw new RuntimeException("商品不存在");
        }
        Assert.isTrue(product.getAuthFlag().equals(ProductAuthFlag.AUDIT_PASS.getCode()), () -> new ServiceException("商品未通过审核"));
        product.setPublishStatus(publishStatus);
        // 发布上架的商品及sku，创建商品和sku快照
        if(Constants.PublishStatus.GROUNDING.equals(publishStatus)){
            List<Sku> skuList = skuService.getByProductId(id);
            ProductSnapshot productSnapshot = BeanUtil.copyProperties(product, ProductSnapshot.class, "id");
            productSnapshot.setProductId(product.getId());
            productSnapshotService.save(productSnapshot);
            product.setProductSnapshotId(productSnapshot.getId());
            List<SkuSnapshot> skuSnapshotList = skuList.stream().map(sku -> {
                SkuSnapshot skuSnapshot = BeanUtil.copyProperties(sku, SkuSnapshot.class, "id");
                skuSnapshot.setSkuId(sku.getId());
                skuSnapshot.setProductSnapshotId(productSnapshot.getId());
                return skuSnapshot;
            }).toList();
            skuSnapshotService.insertBatch(skuSnapshotList);
        }else{
            product.setAuthFlag(ProductAuthFlag.WAIT_AUDIT.getCode());
        }
        return productService.updateById(product);
    }

    @Override
    public IPage<ProductVO> getRecommendPage(Page<Product> page) {
        return productService.getRecommendPage(page);
    }
}
