package com.jeesharp.business.modules.coupon.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jeesharp.business.modules.coupon.entity.MemberCoupon;
import com.jeesharp.business.modules.coupon.enums.MemberCouponUseStatusEnum;
import com.jeesharp.business.modules.coupon.mapper.MemberCouponMapper;
import com.jeesharp.business.modules.coupon.service.MemberCouponService;
import com.jeesharp.business.modules.coupon.vo.MemberCouponQueryVO;
import com.jeesharp.framework.mybatis.core.service.CrudService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

/**
 * 会员优惠券领域服务实现。
 *
 * @author jeesharp
 * @since 2026-05-07
 */
@Service
@Transactional(readOnly = true)
public class MemberCouponServiceImpl extends CrudService<MemberCouponMapper, MemberCoupon, MemberCouponQueryVO>
        implements MemberCouponService {

    @Override
    public long countByMemberAndTemplate(String memberId, String templateId) {
        return baseMapper.selectCount(
                new LambdaQueryWrapper<MemberCoupon>()
                        .eq(MemberCoupon::getMemberId, memberId)
                        .eq(MemberCoupon::getTemplateId, templateId)
                        .eq(MemberCoupon::getDelFlag, "0")
                        .ne(MemberCoupon::getStatus, MemberCouponUseStatusEnum.VOID.getValue()));
    }

    @Override
    public MemberCoupon findLatestByMemberAndTemplate(String memberId, String templateId) {
        if (memberId == null || memberId.isBlank() || templateId == null || templateId.isBlank()) {
            return null;
        }
        return baseMapper.selectOne(
                new LambdaQueryWrapper<MemberCoupon>()
                        .eq(MemberCoupon::getMemberId, memberId.trim())
                        .eq(MemberCoupon::getTemplateId, templateId.trim())
                        .eq(MemberCoupon::getDelFlag, "0")
                        .ne(MemberCoupon::getStatus, MemberCouponUseStatusEnum.VOID.getValue())
                        .orderByDesc(MemberCoupon::getGetDate)
                        .orderByDesc(MemberCoupon::getCreateDate)
                        .last("LIMIT 1"));
    }

    /**
     * 将已过期但仍标记未使用的券批量置为过期。
     * <p>须独立写事务：Application 层查询方法多为 {@code readOnly=true}，若沿用外层只读连接会触发 UPDATE 失败。</p>
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = false)
    public void markExpiredIfPastEnd(String memberId) {
        LocalDateTime now = LocalDateTime.now();
        baseMapper.markExpiredIfPastEnd(
                memberId,
                now,
                MemberCouponUseStatusEnum.UNUSED.getValue(),
                MemberCouponUseStatusEnum.EXPIRED.getValue());
    }

    @Override
    public MemberCoupon findByFreezeOrderId(String orderId) {
        if (orderId == null || orderId.isBlank()) {
            return null;
        }
        return baseMapper.selectOne(
                new LambdaQueryWrapper<MemberCoupon>()
                        .eq(MemberCoupon::getFreezeOrderId, orderId.trim())
                        .eq(MemberCoupon::getDelFlag, "0")
                        .last("LIMIT 1"));
    }

    @Override
    public MemberCoupon findUsedByOrderId(String orderId) {
        if (orderId == null || orderId.isBlank()) {
            return null;
        }
        return baseMapper.selectOne(
                new LambdaQueryWrapper<MemberCoupon>()
                        .eq(MemberCoupon::getUseOrderId, orderId.trim())
                        .eq(MemberCoupon::getStatus, MemberCouponUseStatusEnum.USED.getValue())
                        .eq(MemberCoupon::getDelFlag, "0")
                        .last("LIMIT 1"));
    }
}
