package org.dromara.mall.trade.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.mall.coupon.domain.vo.MallCouponVo;
import org.dromara.mall.coupon.service.MallCouponService;
import org.dromara.mall.coupon.service.MallCouponUserService;
import org.dromara.mall.trade.domain.MallOrderCoupon;
import org.dromara.mall.trade.domain.bo.MallOrderCouponBo;
import org.dromara.mall.trade.domain.vo.MallOrderCouponVo;
import org.dromara.mall.trade.mapper.MallOrderCouponMapper;
import org.dromara.mall.trade.service.MallOrderCouponService;
import org.dromara.mall.trade.utils.CouponCalculator;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.Date;
import java.util.List;

/**
 * 订单优惠券使用记录Service业务层处理
 *
 * @author pengles
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class MallOrderCouponServiceImpl implements MallOrderCouponService {

    private final MallOrderCouponMapper baseMapper;
    private final MallCouponService couponService;
    private final MallCouponUserService couponUserService;

    /**
     * 查询订单优惠券使用记录
     */
    @Override
    public MallOrderCouponVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 根据订单ID查询订单优惠券使用记录列表
     */
    @Override
    public List<MallOrderCouponVo> queryListByOrderId(Long orderId) {
        LambdaQueryWrapper<MallOrderCoupon> lqw = new LambdaQueryWrapper<>();
        lqw.eq(MallOrderCoupon::getOrderId, orderId);
        return baseMapper.selectVoList(lqw);
    }

    /**
     * 根据订单号查询订单优惠券使用记录列表
     */
    @Override
    public List<MallOrderCouponVo> queryListByOrderNo(String orderNo) {
        LambdaQueryWrapper<MallOrderCoupon> lqw = new LambdaQueryWrapper<>();
        lqw.eq(MallOrderCoupon::getOrderNo, orderNo);
        return baseMapper.selectVoList(lqw);
    }

    /**
     * 新增订单优惠券使用记录
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByBo(MallOrderCouponBo bo) {
        MallOrderCoupon add = MapstructUtils.convert(bo, MallOrderCoupon.class);
        validEntityBeforeSave(add);

        // 设置使用时间
        if (add.getCreateTime() == null) {
            add.setCreateTime(new Date());
        }

        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(MallOrderCoupon entity) {
        // 可以添加业务校验逻辑
    }

    /**
     * 批量删除订单优惠券使用记录信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            // 可以添加业务校验逻辑
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 计算并使用优惠券（订单创建时调用）
     * 计算优惠券折扣金额，创建订单优惠券使用记录，并标记用户优惠券为已使用
     *
     * @param couponUserId 用户优惠券ID
     * @param orderId 订单ID
     * @param orderNo 订单号
     * @param orderAmount 订单金额（单位：分）
     * @return 优惠金额（单位：分）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long calculateAndUseCoupon(Long couponUserId, Long orderId, String orderNo, Long orderAmount) {
        if (couponUserId == null) {
            throw new ServiceException("用户优惠券ID不能为空");
        }
        if (orderId == null) {
            throw new ServiceException("订单ID不能为空");
        }
        if (orderNo == null || orderNo.trim().isEmpty()) {
            throw new ServiceException("订单号不能为空");
        }
        if (orderAmount == null || orderAmount <= 0) {
            throw new ServiceException("订单金额必须大于0");
        }

        // 查询用户优惠券信息
        org.dromara.mall.coupon.domain.vo.MallCouponUserVo couponUser = couponUserService.queryById(couponUserId);
        if (couponUser == null) {
            throw new ServiceException("用户优惠券不存在");
        }
        if (couponUser.getStatus() != 0) {
            throw new ServiceException("优惠券已使用或已过期");
        }

        // 查询优惠券信息
        MallCouponVo coupon = couponService.queryById(couponUser.getCouponId());
        if (coupon == null) {
            throw new ServiceException("优惠券不存在");
        }

        // 计算优惠金额
        Long discountAmount = CouponCalculator.calculateDiscountAmount(coupon, orderAmount);
        if (discountAmount <= 0) {
            throw new ServiceException("订单金额不满足优惠券使用门槛");
        }

        // 标记用户优惠券为已使用（调用优惠券服务的useCoupon方法）
        couponUserService.useCoupon(couponUserId, orderId);

        // 创建订单优惠券使用记录
        MallOrderCouponBo orderCouponBo = new MallOrderCouponBo();
        orderCouponBo.setOrderId(orderId);
        orderCouponBo.setOrderNo(orderNo);
        orderCouponBo.setCouponId(coupon.getId());
        orderCouponBo.setCouponUserId(couponUserId);
        orderCouponBo.setDiscountAmount(discountAmount.intValue());

        boolean flag = insertByBo(orderCouponBo);
        if (!flag) {
            throw new ServiceException("创建订单优惠券使用记录失败");
        }

        log.info("优惠券使用成功 - 用户优惠券ID: {}, 订单ID: {}, 订单号: {}, 优惠金额: {}", 
                couponUserId, orderId, orderNo, discountAmount);
        return discountAmount;
    }

    /**
     * 根据订单ID统计优惠金额
     *
     * @param orderId 订单ID
     * @return 优惠金额总和（单位：分）
     */
    @Override
    public Long sumDiscountAmountByOrderId(Long orderId) {
        if (orderId == null) {
            return 0L;
        }
        List<MallOrderCouponVo> list = queryListByOrderId(orderId);
        return list.stream()
                .mapToLong(vo -> vo.getDiscountAmount() != null ? vo.getDiscountAmount().longValue() : 0L)
                .sum();
    }

    /**
     * 根据订单号统计优惠金额
     *
     * @param orderNo 订单号
     * @return 优惠金额总和（单位：分）
     */
    @Override
    public Long sumDiscountAmountByOrderNo(String orderNo) {
        if (orderNo == null || orderNo.trim().isEmpty()) {
            return 0L;
        }
        List<MallOrderCouponVo> list = queryListByOrderNo(orderNo);
        return list.stream()
                .mapToLong(vo -> vo.getDiscountAmount() != null ? vo.getDiscountAmount().longValue() : 0L)
                .sum();
    }

    /**
     * 根据优惠券ID统计核销金额
     *
     * @param couponId 优惠券ID
     * @return 核销金额总和（单位：分）
     */
    @Override
    public Long sumDiscountAmountByCouponId(Long couponId) {
        if (couponId == null) {
            return 0L;
        }
        LambdaQueryWrapper<MallOrderCoupon> lqw = new LambdaQueryWrapper<>();
        lqw.eq(MallOrderCoupon::getCouponId, couponId);
        List<MallOrderCouponVo> list = baseMapper.selectVoList(lqw);
        return list.stream()
                .mapToLong(vo -> vo.getDiscountAmount() != null ? vo.getDiscountAmount().longValue() : 0L)
                .sum();
    }

}
