package com.njzscloud.dispose.cst.order.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njzscloud.common.core.ex.Exceptions;
import com.njzscloud.common.mp.support.PageParam;
import com.njzscloud.common.mp.support.PageResult;
import com.njzscloud.dispose.cst.order.mapper.OrderEvaluateMapper;
import com.njzscloud.dispose.cst.order.pojo.entity.OrderEvaluateEntity;
import com.njzscloud.dispose.cst.order.pojo.param.CreateOrderEvaluateParam;
import com.njzscloud.dispose.cst.order.pojo.param.OrderEvaluateQueryParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;

/**
 * 订单评价表
 *
 * @author ljw
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class OrderEvaluateService extends ServiceImpl<OrderEvaluateMapper, OrderEvaluateEntity> {

    private final OrderEvaluateMapper orderEvaluateMapper;

    /**
     * 新增订单评价
     *
     * @param param 新增参数
     */
    @Transactional(rollbackFor = Exception.class)
    public void add(CreateOrderEvaluateParam param) {
        Assert.notNull(param, () -> Exceptions.clierr("请填写参数"));
        Assert.notNull(param.getEfficiencyScore(), () -> Exceptions.clierr("服务效率分不可为空"));
        Assert.notNull(param.getFeeScore(), () -> Exceptions.clierr("费用透明分不可为空"));
        Assert.notNull(param.getAttitudeScore(), () -> Exceptions.clierr("服务态度分不可为空"));

        // 校验分数范围
        this.validateScore(param.getEfficiencyScore());
        this.validateScore(param.getFeeScore());
        this.validateScore(param.getAttitudeScore());

        // 计算综合评分 = (费用透明分 + 服务效率分 + 服务态度分) / 3
        // 结果只能是0、0.5、1、1.5、2、2.5、3、3.5、4、4.5、5，有其他值时，向上取值
        BigDecimal overallScore = this.calculateOverallScore(param.getEfficiencyScore(), param.getFeeScore(), param.getAttitudeScore());

        OrderEvaluateEntity entity = BeanUtil.copyProperties(param, OrderEvaluateEntity.class)
            .setOverallScore(overallScore);
        orderEvaluateMapper.insert(entity);
    }

    /**
     * 修改订单评价
     *
     * @param orderEvaluateEntity 订单评价实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void modify(OrderEvaluateEntity orderEvaluateEntity) {
        Assert.notNull(orderEvaluateEntity.getId(), () -> Exceptions.clierr("ID不可为空"));

        OrderEvaluateEntity existEntity = this.getById(orderEvaluateEntity.getId());
        Assert.notNull(existEntity, () -> Exceptions.clierr("评价记录不存在"));

        // 如果有评分字段更新，需要重新计算综合评分
        if (orderEvaluateEntity.getEfficiencyScore() != null || orderEvaluateEntity.getFeeScore() != null || orderEvaluateEntity.getAttitudeScore() != null) {
            BigDecimal efficiencyScore = orderEvaluateEntity.getEfficiencyScore() != null ? orderEvaluateEntity.getEfficiencyScore() : existEntity.getEfficiencyScore();
            BigDecimal feeScore = orderEvaluateEntity.getFeeScore() != null ? orderEvaluateEntity.getFeeScore() : existEntity.getFeeScore();
            BigDecimal attitudeScore = orderEvaluateEntity.getAttitudeScore() != null ? orderEvaluateEntity.getAttitudeScore() : existEntity.getAttitudeScore();

            // 校验分数范围
            this.validateScore(efficiencyScore);
            this.validateScore(feeScore);
            this.validateScore(attitudeScore);

            // 重新计算综合评分
            BigDecimal overallScore = this.calculateOverallScore(efficiencyScore, feeScore, attitudeScore);
            orderEvaluateEntity.setOverallScore(overallScore);
        }

        orderEvaluateMapper.updateById(orderEvaluateEntity);
    }

    /**
     * 删除订单评价
     *
     * @param ids id集合
     */
    @Transactional(rollbackFor = Exception.class)
    public void del(List<Long> ids) {
        Assert.notEmpty(ids, () -> Exceptions.clierr("ID集合不可为空"));
        this.removeBatchByIds(ids);
    }

    /**
     * 查询订单评价详情
     *
     * @param id id
     * @return 订单评价实体
     */
    public OrderEvaluateEntity detail(Long id) {
        Assert.notNull(id, () -> Exceptions.clierr("ID不可为空"));
        return this.getById(id);
    }

    /**
     * 分页查询订单评价
     *
     * @param pageParam 分页参数
     * @param queryParam 查询参数
     * @return 分页结果
     */
    public PageResult<OrderEvaluateEntity> paging(PageParam pageParam, OrderEvaluateQueryParam queryParam) {
        return PageResult.of(this.page(pageParam.toPage(), Wrappers.<OrderEvaluateEntity>lambdaQuery()
            .eq(queryParam.getOrderId() != null, OrderEvaluateEntity::getOrderId, queryParam.getOrderId())
            .like(queryParam.getSn() != null, OrderEvaluateEntity::getSn, queryParam.getSn())
            .eq(queryParam.getUserId() != null, OrderEvaluateEntity::getUserId, queryParam.getUserId())
            .eq(queryParam.getCustomerId() != null, OrderEvaluateEntity::getCustomerId, queryParam.getCustomerId())
            .eq(queryParam.getTransOrgId() != null, OrderEvaluateEntity::getTransOrgId, queryParam.getTransOrgId())
            .eq(queryParam.getTransCustomerId() != null, OrderEvaluateEntity::getTransCustomerId, queryParam.getTransCustomerId())
        ));
    }

    /**
     * 根据订单ID查询评价
     *
     * @param orderId 订单ID
     * @return 订单评价
     */
    public OrderEvaluateEntity getByOrderId(Long orderId) {
        Assert.notNull(orderId, () -> Exceptions.clierr("订单ID不可为空"));
        return this.getOne(Wrappers.<OrderEvaluateEntity>lambdaQuery()
            .eq(OrderEvaluateEntity::getOrderId, orderId)
            .eq(OrderEvaluateEntity::getDeleted, Boolean.FALSE));
    }

    /**
     * 校验分数范围
     *
     * @param score 分数
     */
    private void validateScore(BigDecimal score) {
        Assert.notNull(score, () -> Exceptions.clierr("分数不可为空"));
        Assert.isTrue(score.compareTo(BigDecimal.ZERO) >= 0 && score.compareTo(new BigDecimal("5")) <= 0, () -> Exceptions.clierr("分数必须在0-5之间"));
    }

    /**
     * 计算综合评分
     * 综合评分 = (费用透明分 + 服务效率分 + 服务态度分) / 3
     * 结果只能是0、0.5、1、1.5、2、2.5、3、3.5、4、4.5、5，有其他值时，向上取值
     *
     * @param efficiencyScore 服务效率分
     * @param feeScore         费用透明分
     * @param attitudeScore    服务态度分
     * @return 综合评分
     */
    private BigDecimal calculateOverallScore(BigDecimal efficiencyScore, BigDecimal feeScore, BigDecimal attitudeScore) {
        // 计算平均分（乘以2后向上取整，再除以2，实现0.5为步长的向上取整）
        BigDecimal sum = efficiencyScore.add(feeScore).add(attitudeScore);
        BigDecimal avgScore = sum.divide(new BigDecimal("3"), 2, RoundingMode.HALF_UP);
        // 向上取值到最近的0.5倍数
        return avgScore.multiply(new BigDecimal("2")).setScale(0, RoundingMode.CEILING).divide(new BigDecimal("2"), 1, RoundingMode.UNNECESSARY);
    }
}
