package com.cf.imes.module.system.service.funds.products;

import com.alibaba.nacos.common.utils.StringUtils;
import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.Assert.AssertUtils;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.cf.imes.module.system.controller.admin.funds.products.vo.productDetails.ProductDetailsPageReqVO;
import com.cf.imes.module.system.controller.admin.funds.products.vo.productDetails.ProductDetailsSaveReqVO;
import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDO;
import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDetailDO;
import com.cf.imes.module.system.dal.mysql.funds.products.ProductsDetailMapper;
import com.cf.imes.module.system.dal.mysql.funds.products.ProductsMapper;
import com.cf.imes.module.system.enums.products.ProductStatusEnum;
import com.cf.imes.module.system.enums.products.ProductsPurchaseTypeEnum;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import jakarta.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;

import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.*;

/**
 * 产品明细 productsDetails Service 实现类
 *
 * @author 晨丰科技
 */
@Service
@Validated
public class ProductsDetailServiceImpl implements ProductsDetailService {

    @Resource
    private ProductsDetailMapper productDetailsMapper;

    @Resource
    private ProductsMapper productsMapper;

    @Override
    public Long create(ProductDetailsSaveReqVO createReqVO) {

        // 校验是否有这个产品
        validateProductExist(createReqVO.getProductId());

        if (ProductsPurchaseTypeEnum.DURATION.getStatus().equals(createReqVO.getPurchaseType())) {
            // 校验时长
            checkDuration(createReqVO.getDuration(), createReqVO.getDurationUnit());
            // 校验赠送时长
            String giftDuration = createReqVO.getGiftDuration();
            if (StringUtils.isNotEmpty(giftDuration)) {
                checkDuration(giftDuration, createReqVO.getGiftDurationUnit());
            }

            // 校验现价计算是否正确
            calculateDiscount(createReqVO.getOriginalPrice(), createReqVO.getCurrentPrice(), createReqVO.getDiscount());
            // 查询是否有重复的定价
            checkProductDetails(createReqVO);

        } else if (createReqVO.getPurchaseType().equals(ProductsPurchaseTypeEnum.OUTPUT.getStatus())) {
            // todo 暂不支持产量
            throw exception(PRODUCTS_OUTPUT_NOT_SUPPORT);
        }

        ProductsDetailDO productDetailsDO = BeanUtils.toBean(createReqVO, ProductsDetailDO.class);
        productDetailsMapper.insert(productDetailsDO);
        return productDetailsDO.getId();
    }


    @Override
    public void update(ProductDetailsSaveReqVO updateReqVO) {

        validateProductExist(updateReqVO.getProductId());

        validateProductDetailsExists(updateReqVO.getId());

        if (updateReqVO.getPurchaseType().equals(ProductsPurchaseTypeEnum.DURATION.getStatus())) {
            // 校验时长
            checkDuration(updateReqVO.getDuration(), updateReqVO.getDurationUnit());
            // 校验赠送时长
            String giftDuration = updateReqVO.getGiftDuration();
            if (StringUtils.isNotEmpty(giftDuration)) {
                checkDuration(giftDuration, updateReqVO.getGiftDurationUnit());
            }

            // 校验现价计算是否正确
            calculateDiscount(updateReqVO.getOriginalPrice(), updateReqVO.getCurrentPrice(), updateReqVO.getDiscount());
            // 校验同时长是否还有其他的定价规则
            checkProductDetails(updateReqVO);

        } else if (updateReqVO.getPurchaseType().equals(ProductsPurchaseTypeEnum.OUTPUT.getStatus())) {
            // todo 暂不支持产量
            throw exception(PRODUCTS_OUTPUT_NOT_SUPPORT);
        }

        productDetailsMapper.updateById(BeanUtils.toBean(updateReqVO, ProductsDetailDO.class));
    }

    @Override
    public void delete(Long id) {

        ProductsDetailDO productsDetailDO = validateProductDetailsExists(id);

        validateProductExist(productsDetailDO.getProductId());

        productDetailsMapper.deleteById(id);

    }

    @Override
    public ProductsDetailDO get(Long id) {
        return validateProductDetailsExists(id);
    }

    @Override
    public PageResult<ProductsDetailDO> getPage(ProductDetailsPageReqVO pageReqVO) {
        return productDetailsMapper.selectPage(pageReqVO);
    }


    @Override
    public ProductsDetailDO validateProductDetailsExists(Long id) {
        if (id == null) {
            throw exception(PRODUCTS_DETAIL_NO_EXIST);
        }

        ProductsDetailDO productsDetailDO = productDetailsMapper.selectOne(new LambdaQueryWrapperX<ProductsDetailDO>()
                .eq(ProductsDetailDO::getId, id)
                .eq(ProductsDetailDO::getDeleted, false));

        if (productsDetailDO == null) {
            throw exception(PRODUCTS_DETAIL_NO_EXIST);
        }

        return productsDetailDO;
    }


    /**
     * 校验时长
     *
     * @param duration
     * @param timeUnit
     * @return
     */
    private void checkDuration(String duration, Integer timeUnit) {
        AssertUtils.notEmpty(duration, PRODUCTS_DURATION_NOT_NULL);
        AssertUtils.notEmpty(timeUnit, PRODUCTS_DURATION_NOT_NULL);

        // 校验时长值
        if (!duration.matches("^\\d+$")) {
            throw exception(PRODUCTS_DURATION_INT_ERR);
        }

        int timeValue = Integer.parseInt(duration);
        if (timeValue <= 0) {
            throw exception(PRODUCTS_DURATION_INT_ERR);
        }
    }


    /**
     * 产品是否存在和时效性校验
     *
     * @param productId
     */
    @Override
    public ProductsDO validateProductExist(Long productId) {
        ProductsDO productsDO = productsMapper.selectOne(new LambdaQueryWrapperX<ProductsDO>()
                .eq(ProductsDO::getId, productId)
                .eq(ProductsDO::getDeleted, false));

        AssertUtils.notEmpty(productsDO, PRODUCTS_NO_EXIST);

        if (productsDO.getStatus().equals(ProductStatusEnum.PRODUCT_UPDATES.getStatus())) {
            throw exception(PRODUCTS_DETAIL_NO_UPDATE);
        }

        return productsDO;
    }


    /**
     * 检查产品下是否有相同时长的规则
     *
     * @param createReqVO
     */
    private void checkProductDetails(ProductDetailsSaveReqVO createReqVO) {
        int count;
        if (createReqVO.getPurchaseType() == 0) {
            String duration = createReqVO.getDuration();
            Integer durationUnit = createReqVO.getDurationUnit();
            // 时长去重
            count = productDetailsMapper.selectCountByDuration(createReqVO.getProductId(), createReqVO.getId(), duration, durationUnit);
            if (count > 0) {
                throw ServiceExceptionUtil.exception(PRODUCTS_DETAIL_DURATION_EXIST, duration, durationUnit);
            }
        } else if (createReqVO.getPurchaseType() == 1) {
            //产量去重
            count = productDetailsMapper.selectCountByOutput(createReqVO.getOutput(), createReqVO.getProductId());
            if (count > 0) {
                throw exception(PRODUCTS_DETAIL_OUTPUT_EXIST);
            }
        }
    }


    /**
     * 计算折扣是否正确
     *
     * @param originalPrice 原价
     * @param currentPrice  当前价格
     * @param discount      折扣（百分比）
     */
    private void calculateDiscount(BigDecimal originalPrice, BigDecimal currentPrice, BigDecimal discount) {
        // 校验当前价格是否正确
        // 计算期望现价 = 原价 * 折扣 /100（保留2位小数）
        BigDecimal expectedPrice = originalPrice.multiply(discount).divide(new BigDecimal(100)).setScale(2, RoundingMode.DOWN);

        if (currentPrice.compareTo(expectedPrice) != 0) {
            throw ServiceExceptionUtil.exception(PRODUCTS_DETAIL_CURRENTPRICE_CALCULATE_ERROR, expectedPrice);
        }
    }

}
