package shop.alien.store.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import shop.alien.entity.result.R;
import shop.alien.entity.store.*;
import shop.alien.entity.store.dto.LifeDiscountCouponStoreFriendDto;
import shop.alien.entity.store.vo.LifeCouponStatusVo;
import shop.alien.mapper.*;
import shop.alien.store.config.BaseRedisService;
import shop.alien.store.service.LifeCouponService;
import shop.alien.store.service.LifeDiscountCouponStoreFriendService;
import shop.alien.util.common.UniqueRandomNumGenerator;
import shop.alien.util.common.constant.OrderStatusEnum;

import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.TextStyle;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 优惠券
 *
 * @author ssk
 * @version 1.0
 * @date 2024/12/23 15:08
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class LifeCouponServiceImpl extends ServiceImpl<LifeCouponMapper, LifeCoupon> implements LifeCouponService {

    private final LifeCouponMapper lifeCouponMapper;

    private final LifeUserOrderMapper lifeUserOrderMapper;

    private final StoreIncomeDetailsRecordMapper storeIncomeDetailsRecordMapper;

    private final StoreDictionaryMapper storeDictionaryMapper;

    private final LifeDiscountCouponStoreFriendService lifeDiscountCouponStoreFriendService;

    private final EssentialHolidayComparisonMapper essentialHolidayComparisonMapper;

    private final StoreUserMapper storeUserMapper;

    private final OrderCouponMiddleMapper orderCouponMiddleMapper;

    private final LifeGroupBuyMainMapper lifeGroupBuyMainMapper;

    private final StoreInfoMapper storeInfoMapper;

    private final BaseRedisService baseRedisService;
    private final LifeDiscountCouponMapper lifeDiscountCouponMapper;

    @Override
    public LifeCoupon addOrUpdateCoupon(LifeCoupon lifeCoupon) {//状态：0草稿/1待审核/2未开始/3审核拒绝/4已售罄/5进行中/6已下架/7已结束/8=2+手动下架
        // 添加优惠tag
        //获取经营板块id
//        Integer businessSection = lifeCoupon.getBusinessSection();
        //查询经营板块名称
        StoreDictionary youhuiName = storeDictionaryMapper.selectOne(new LambdaQueryWrapper<StoreDictionary>().eq(StoreDictionary::getDictId, "180").eq(StoreDictionary::getTypeName, "youhui"));
        //查询经营种类
        List<String> discountTypes = lifeCoupon.getTempDiscountTag();
        List<String> businessTypeNames = new ArrayList<>();
        //获取经营种类名称
        if (!CollectionUtils.isEmpty(discountTypes)) {
            for (String businessType : discountTypes) {
                StoreDictionary storeDictionary =
                        storeDictionaryMapper
                                .selectOne(
                                        new LambdaQueryWrapper<StoreDictionary>()
                                                .eq(StoreDictionary::getDictId, businessType).eq(StoreDictionary::getParentId, youhuiName.getId()));
                businessTypeNames.add(storeDictionary.getDictDetail());
            }
            lifeCoupon.setDiscountTag(String.join(",", discountTypes));
            lifeCoupon.setDiscountTagName(String.join(",", businessTypeNames));
        }
        // 根据开始/结束日期自动设置：当前早于开始日→2未开始，在有效期内→5进行中，晚于结束日→7已结束
        Date now = new Date();
        Date startDate = lifeCoupon.getStartDate();
        Date endDate = lifeCoupon.getEndDate();
       if (lifeCoupon.getSingleQty()!=null && lifeCoupon.getSingleQty() ==0){
           lifeCoupon.setStatus(4);
       }else {
           if (startDate != null) {
               if (now.before(startDate)) {
                   lifeCoupon.setStatus(2);   // 未开始：当前日期早于开始日
               } else if (endDate != null && now.after(endDate)) {
                   lifeCoupon.setStatus(7);   // 已结束：当前日期晚于结束日
               } else {
                   lifeCoupon.setStatus(5);   // 进行中：在有效期内（开始日当天～结束日当天）
               }
           }
       }
        if (StringUtils.isEmpty(lifeCoupon.getId())) {
            lifeCoupon.setType(1);
            lifeCoupon.setCouponCode(UniqueRandomNumGenerator.generateUniqueCode(12));
            this.save(lifeCoupon);
        } else {
            this.updateById(lifeCoupon);
        }
        return lifeCoupon;
    }

    /**
     * 修改库存数量
     *
     * @param id        主键
     * @param singleQty 库存数量
     * @return boolean
     */
    @Override
    public boolean updateCouponSingleQty(Integer id, Integer singleQty) {
        //判断库存数为0 增加库存数修改状态为进行中
        LambdaQueryWrapper<LifeCoupon> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(LifeCoupon :: getId, id);
        LifeCoupon lifeCoupon = lifeCouponMapper.selectOne(lambdaQueryWrapper);

        if(lifeCoupon.getSingleQty() == 0){
        LambdaUpdateWrapper<LifeCoupon> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(LifeCoupon :: getId, id);
        lambdaUpdateWrapper.set(LifeCoupon :: getSingleQty,singleQty);
        lambdaUpdateWrapper.set(LifeCoupon :: getStatus, 5);
        lifeCouponMapper.update(null, lambdaUpdateWrapper);
        }
        else{
            LambdaUpdateWrapper<LifeCoupon> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            lambdaUpdateWrapper.eq(LifeCoupon :: getId, id);
            lambdaUpdateWrapper.set(LifeCoupon :: getSingleQty,singleQty);
            lifeCouponMapper.update(null, lambdaUpdateWrapper);
        }

        return true;
    }

    @Override
    public IPage<LifeCoupon> getCouponList(int page, int size, String storeId, String status, String name, Integer dataType) {
        LambdaUpdateWrapper<LifeCoupon> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(storeId != null && !storeId.isEmpty(), LifeCoupon::getStoreId, storeId);
        wrapper.eq(status != null && !status.isEmpty(), LifeCoupon::getStatus, status);
        wrapper.like(name != null && !name.isEmpty(), LifeCoupon::getName, name);
        wrapper.eq(LifeCoupon::getType, 1);
        wrapper.eq(LifeCoupon::getDataType, dataType);
//        修改排序 按照status(0草稿/1待审核/2未开始/3审核拒绝/4已售罄/5进行中/6已下架/7已结束/8=2+手动下架）   审核拒绝>待审核>进行中>已售罄，已下架，已结束(同等优先级的情况下，按照审核时间的倒序显示)
        wrapper.last("ORDER BY CASE " +
                "WHEN status = 3 THEN 0 " +  // 审核拒绝
                "WHEN status = 1 THEN 1 " +  // 待审核
                "WHEN status = 5 THEN 2 " +  // 进行中
                "WHEN status IN (4, 6, 7) THEN 3 " +  // 已售罄、已下架、已结束
                "ELSE 4 END ASC, " +
                "created_time DESC");
        IPage<LifeCoupon> lifeCouponIPage = new Page<>(page, size);
        return lifeCouponMapper.selectPage(lifeCouponIPage, wrapper);
    }

    @Override
    public int updateCoupon(String id, Integer status) {
        LifeCoupon coupon = lifeCouponMapper.selectById(id);
        if (null == coupon) {
            throw new RuntimeException("该券不存在");
        }
        // 已结束
        if (LocalDate.now().isAfter(coupon.getEndDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate())) {
            status = 7;
        }
        LifeCoupon lifeCoupon = new LifeCoupon();
        lifeCoupon.setId(id);
        lifeCoupon.setStatus(status);
        return lifeCouponMapper.updateById(lifeCoupon);
    }

    /**
     * 验券
     *
     * @param storeId
     * @param quanCode
     * @return
     */
    @Override
    public Map<String, String> couponVerify(String storeId, String quanCode) {
        LambdaUpdateWrapper<LifeUserOrder> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(LifeUserOrder::getQuanCode, quanCode);
        LifeUserOrder order = lifeUserOrderMapper.selectOne(wrapper);
        Map<String, String> resultMap = new HashMap<>();
        String errMessage = "";
        if (order == null) {
            errMessage = "没有这张券";
        } else {
            if (order.getStatus() == 5) {
                errMessage = "该券已核销";
            }
            if (order.getStatus() == 6) {
                errMessage = "该券已过期";
            }
            if (order.getStatus() == 7) {
                errMessage = "该券待退款";
            }
            if (order.getStatus() == 4) {
                errMessage = "该券已退款";
            }
            if (!order.getStoreId().equals(storeId)) {
                errMessage = "核销商家与券不一致";
            }
        }
        if (!StringUtils.isEmpty(errMessage)) {
            resultMap.put("code", "false");
            resultMap.put("message", errMessage);
            return resultMap;
        }

        order.setStatus(5);
        order.setUsedTime(new Date());
        lifeUserOrderMapper.updateById(order);

        LambdaUpdateWrapper<LifeCoupon> couponWrapper = new LambdaUpdateWrapper<>();
        couponWrapper.eq(LifeCoupon::getId, order.getQuanId());
        LifeCoupon coupon = lifeCouponMapper.selectOne(couponWrapper);
        // TODO 抽成比例应该从商户里取
        BigDecimal amounts = new BigDecimal(order.getFinalPrice()).multiply(new BigDecimal(100));
        BigDecimal commission = amounts.multiply(new BigDecimal(0.04)).setScale(0, RoundingMode.HALF_UP);
        BigDecimal money = amounts.subtract(commission);

        // 插入收入明细表数据
        StoreIncomeDetailsRecord record = new StoreIncomeDetailsRecord();
        record.setStoreId(Integer.parseInt(storeId));
        record.setUserOrderId(Integer.parseInt(order.getId()));
        record.setIncomeType(coupon.getType());
        record.setBusinessId(Integer.parseInt(order.getQuanId()));
        record.setCommission(commission.intValue());
        record.setMoney(money.intValue());
        storeIncomeDetailsRecordMapper.insert(record);
        // 店铺账户余额增加
        UpdateWrapper<StoreUser> updateWrapper = new UpdateWrapper();
        updateWrapper.eq("store_id", storeId);
        updateWrapper.eq("delete_flag", 0);
        updateWrapper.setSql("money = money + " + money);
        storeUserMapper.update(null, updateWrapper);
        //发放好友优惠券
        LifeDiscountCouponStoreFriendDto lifeDiscountCouponStoreFriendDto = new LifeDiscountCouponStoreFriendDto();
        lifeDiscountCouponStoreFriendDto.setOrderId(Integer.parseInt(order.getId()));
        lifeDiscountCouponStoreFriendService.issueFriendCoupon(lifeDiscountCouponStoreFriendDto);
        resultMap.put("code", "true");
        resultMap.put("message", "核销成功");
        return resultMap;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, String> newCouponVerify(String storeId, String quanCode) {
        Map<String, String> resultMap = new HashMap<>();
        String lockKey = "coupon:use:" + quanCode;
        if (baseRedisService.hasKey(lockKey)) {
            resultMap.put("code", "false");
            resultMap.put("message", "请勿重复核销");
            return resultMap;
        }
        baseRedisService.setListRight(lockKey, quanCode);
        try {
            OrderCouponMiddle orderCouponMiddle = orderCouponMiddleMapper.selectOne(new LambdaQueryWrapper<OrderCouponMiddle>().eq(OrderCouponMiddle::getCouponCode, quanCode).in(OrderCouponMiddle::getStatus, OrderStatusEnum.WAIT_USE.getStatus(), OrderStatusEnum.REFUND_FAILED.getStatus()));
            if (!StringUtils.isEmpty(orderCouponMiddle)) {
                // 查询总订单
                LifeUserOrder lifeUserOrder = lifeUserOrderMapper.selectOne(new LambdaQueryWrapper<LifeUserOrder>().eq(LifeUserOrder::getId, orderCouponMiddle.getOrderId()));
                orderCouponMiddle.setStatus(OrderStatusEnum.USED.getStatus());
                orderCouponMiddle.setUsedTime(new Date());
                orderCouponMiddleMapper.updateById(orderCouponMiddle);
                // 查看是否使用优惠券
                Boolean platFormCoupon = false;
                String quanId = lifeUserOrder.getQuanId();
                if (org.apache.commons.lang3.StringUtils.isNotEmpty(quanId)) {
                    LifeDiscountCoupon lifeDiscountCoupon = lifeDiscountCouponMapper.selectById(quanId);
                    if (org.apache.commons.lang3.ObjectUtils.isNotEmpty(lifeDiscountCoupon)) {
                        if (3 == lifeDiscountCoupon.getType()) {
                            platFormCoupon = true;
                        }
                    }
                }


                //通过订单id查询中间表 如果该订单下所有劵都为已核销状态更改订单表状态为已核销
                List<OrderCouponMiddle> couponMiddleList = orderCouponMiddleMapper.selectList(new LambdaQueryWrapper<OrderCouponMiddle>()
                        .eq(OrderCouponMiddle::getOrderId, lifeUserOrder.getId()));
                // 排除要核销的券的 所以券状态
                boolean isExist = couponMiddleList.stream().allMatch(str -> str.getStatus() == OrderStatusEnum.USED.getStatus());
                // 订单状态 -> 已完成 筛选出未完成的状态
                List<OrderCouponMiddle> collect = couponMiddleList.stream().filter(x -> x.getStatus() == OrderStatusEnum.WAIT_USE.getStatus() || x.getStatus() == OrderStatusEnum.REFUND_FAILED.getStatus())
                        .collect(Collectors.toList());
                if (isExist) {
                    lifeUserOrder.setStatus(OrderStatusEnum.COMPLETE.getStatus());
                    lifeUserOrder.setFinishTime(new Date());
                    lifeUserOrder.setCreatedTime(new Date());
                    lifeUserOrderMapper.updateById(lifeUserOrder);

                    //发放好友优惠券
                    LifeDiscountCouponStoreFriendDto lifeDiscountCouponStoreFriendDto = new LifeDiscountCouponStoreFriendDto();
                    lifeDiscountCouponStoreFriendDto.setOrderId(Integer.parseInt(lifeUserOrder.getId()));
                    lifeDiscountCouponStoreFriendService.issueFriendCoupon(lifeDiscountCouponStoreFriendDto);
                } else if (collect.size() == 0) {
                    lifeUserOrder.setStatus(OrderStatusEnum.COMPLETE.getStatus());
                    lifeUserOrder.setFinishTime(new Date());
                    lifeUserOrder.setCreatedTime(new Date());
                    lifeUserOrderMapper.updateById(lifeUserOrder);

                    //发放好友优惠券
                    LifeDiscountCouponStoreFriendDto lifeDiscountCouponStoreFriendDto = new LifeDiscountCouponStoreFriendDto();
                    lifeDiscountCouponStoreFriendDto.setOrderId(Integer.parseInt(lifeUserOrder.getId()));
                    lifeDiscountCouponStoreFriendService.issueFriendCoupon(lifeDiscountCouponStoreFriendDto);
                }
                // 计算总退款金额(orderCouponMiddle金额按实际的存)
//            BigDecimal refundAmount = couponMiddleList.stream().filter(x -> x.getStatus() == OrderStatusEnum.REFUND.getStatus()).map(x -> x.getPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
                StoreInfo storeInfo = storeInfoMapper.selectOne(new LambdaQueryWrapper<StoreInfo>().eq(StoreInfo::getId, lifeUserOrder.getStoreId()));
                // 先将抽成比例转换为BigDecimal，再除以100
                BigDecimal commissionRate = new BigDecimal(storeInfo.getCommissionRate())
                        .divide(new BigDecimal("100"));
                // 感觉有问题。HALF_UP有问题。 price 正常存储
                BigDecimal commission = orderCouponMiddle.getPrice().multiply(new BigDecimal("100").multiply(commissionRate)).setScale(2, RoundingMode.HALF_UP);
                // 如果使用了平台优惠券则需要加上平均优惠券价格
                BigDecimal money = BigDecimal.ZERO;
                if (platFormCoupon) {
                    money = orderCouponMiddle.getPrice().add(orderCouponMiddle.getAvgDiscountCouponPrice()).multiply(new BigDecimal("100")).subtract(commission);
                } else {
                    money = orderCouponMiddle.getPrice().multiply(new BigDecimal("100")).subtract(commission);
                }
                // 插入收入明细表数据
                StoreIncomeDetailsRecord record = new StoreIncomeDetailsRecord();
                record.setStoreId(Integer.parseInt(storeId));
                record.setUserOrderId(orderCouponMiddle.getId());
                record.setIncomeType(lifeUserOrder.getCouponType());
                record.setBusinessId(orderCouponMiddle.getCouponId());
                record.setCommission(commission.intValue());
                record.setMoney(money.intValue());
                storeIncomeDetailsRecordMapper.insert(record);

                // 店铺账户余额增加
                UpdateWrapper<StoreUser> updateWrapper = new UpdateWrapper();
                updateWrapper.eq("store_id", storeId);
                updateWrapper.eq("delete_flag", 0);
                updateWrapper.setSql("money = money + " + money);
                storeUserMapper.update(null, updateWrapper);

                resultMap.put("code", "true");
                resultMap.put("message", "核销成功");
            } else {
                resultMap.put("code", "false");
                resultMap.put("message", "核销失败");
            }
        } finally {
            baseRedisService.delete(lockKey);
        }
        return resultMap;
    }

    /**
     * <p>
     * 获取代金券状态
     * </p>
     *
     * @author zhangchen
     * @since 2025-07-14
     */
    @Override
    public LifeCouponStatusVo getCouponStatus(String couponId) {
        if (couponId == null || couponId.isEmpty()) {
            log.error("获取代金券状态失败：couponId为空");
            throw new IllegalArgumentException("couponId不能为空");
        }
        try {
            LifeCoupon coupon = lifeCouponMapper.selectById(couponId);
            LifeCouponStatusVo lifeCouponStatusVo = new LifeCouponStatusVo();
            if (coupon != null) {
                lifeCouponStatusVo.setCouponId(couponId);
                lifeCouponStatusVo.setSingleQty(coupon.getSingleQty());
                lifeCouponStatusVo.setBuyLimit(coupon.getBuyLimit());
            } else {
                // 可选：设置默认值或标记状态为无效
                lifeCouponStatusVo.setSingleQty(0); // 或其他默认逻辑
            }
            return lifeCouponStatusVo;
        } catch (Exception e) {
            log.error("获取代金券状态失败: {}", e);
            throw new RuntimeException("获取代金券状态失败", e); // 或者根据项目规范处理
        }
    }

    @Override
    public IPage<EssentialHolidayComparison> getHolidayList(int page, int size, String year, String openFlag, String holidayName) {
        if (StringUtils.isEmpty(year)) {
            LambdaQueryWrapper<EssentialHolidayComparison> essentialHolidayComparisonLambdaQueryWrapper = new LambdaQueryWrapper<>();
            essentialHolidayComparisonLambdaQueryWrapper.eq(EssentialHolidayComparison::getDelFlag, 0).groupBy(EssentialHolidayComparison::getParticularYear).orderByDesc(EssentialHolidayComparison::getParticularYear);
            IPage<EssentialHolidayComparison> essentialHolidayComparisonIPage = new Page<>(page, size);
            return essentialHolidayComparisonMapper.selectPage(essentialHolidayComparisonIPage, essentialHolidayComparisonLambdaQueryWrapper);
        } else {
            LambdaQueryWrapper<EssentialHolidayComparison> essentialHolidayComparisonLambdaQueryWrapper = new LambdaQueryWrapper<>();
            essentialHolidayComparisonLambdaQueryWrapper.eq(EssentialHolidayComparison::getDelFlag, 0)
                    .eq(com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotEmpty(year), EssentialHolidayComparison::getParticularYear, year)
                    .eq(com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotEmpty(openFlag), EssentialHolidayComparison::getOpenFlag, openFlag)
                    .like(com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotEmpty(holidayName), EssentialHolidayComparison::getFestivalName, holidayName)
                    .orderByAsc(EssentialHolidayComparison::getStartTime);
            IPage<EssentialHolidayComparison> essentialHolidayComparisonIPage = new Page<>(page, size);
            return essentialHolidayComparisonMapper.selectPage(essentialHolidayComparisonIPage, essentialHolidayComparisonLambdaQueryWrapper);
        }
    }

    @Override
    public boolean saveHoliday(EssentialHolidayComparison essentialHolidayComparison) {
        if (ObjectUtils.isNotEmpty(essentialHolidayComparison.getId())) {
            if (ObjectUtils.isNotEmpty(essentialHolidayComparison.getStartTime())) {
                essentialHolidayComparison.setFestivalDate(essentialHolidayComparison.getStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
            }
            essentialHolidayComparisonMapper.updateById(essentialHolidayComparison);
            return true;
        } else {
            if (ObjectUtils.isNotEmpty(essentialHolidayComparison.getStartTime())) {
                essentialHolidayComparison.setFestivalDate(essentialHolidayComparison.getStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
            }
            essentialHolidayComparisonMapper.insert(essentialHolidayComparison);
            return true;
        }
    }

    @Override
    public boolean delHoliday(String id) {
        essentialHolidayComparisonMapper.update(null, new LambdaUpdateWrapper<EssentialHolidayComparison>().eq(EssentialHolidayComparison::getId, id).set(EssentialHolidayComparison::getDelFlag, 1));
        return true;
    }

    @Override
    public boolean delHolidayByYear(String year) {
        essentialHolidayComparisonMapper.update(null, new LambdaUpdateWrapper<EssentialHolidayComparison>().eq(EssentialHolidayComparison::getParticularYear, year).set(EssentialHolidayComparison::getDelFlag, 1));
        return true;
    }

    @Override
    public boolean openCloseHoliday(String id) {
        EssentialHolidayComparison essentialHolidayComparison = essentialHolidayComparisonMapper.selectById(id);
        if (essentialHolidayComparison.getOpenFlag() == 0) {
            essentialHolidayComparisonMapper.update(null, new LambdaUpdateWrapper<EssentialHolidayComparison>().eq(EssentialHolidayComparison::getId, id).set(EssentialHolidayComparison::getOpenFlag, 1));
        } else {
            essentialHolidayComparisonMapper.update(null, new LambdaUpdateWrapper<EssentialHolidayComparison>().eq(EssentialHolidayComparison::getId, id).set(EssentialHolidayComparison::getOpenFlag, 0));
        }
        return true;
    }

    /**
     * 核销订单前效验
     *
     * @param orderCode
     * @return
     */
    @Override
    public R<String> orderVerify(String orderCode) {
        OrderCouponMiddle orderCouponMiddle = orderCouponMiddleMapper.selectOne(new LambdaQueryWrapper<OrderCouponMiddle>().eq(OrderCouponMiddle::getCouponCode, orderCode));
        if (!StringUtils.isEmpty(orderCouponMiddle) && orderCouponMiddle.getStatus() == 1) {
            LifeUserOrder lifeUserOrder = lifeUserOrderMapper.selectOne(new LambdaQueryWrapper<LifeUserOrder>().eq(LifeUserOrder::getId, orderCouponMiddle.getOrderId()));
            //类型为:1 代金券订单
            if (lifeUserOrder.getCouponType() == 1) {
                return couponVerification(orderCouponMiddle);
            } else if (lifeUserOrder.getCouponType() == 2) {//类型为:2 团购订单
                return groupVerification(orderCouponMiddle);
            }
        }
        return R.fail("该劵不是待使用状态");
    }

    public static boolean isCurrentDateInAnyRange(String[] dateRanges) {
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        // 定义日期格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        // 遍历数组中的每一对日期范围
        for (String range : dateRanges) {
            // 分割每一对日期（开始日期和结束日期）
            String[] dates = range.split(",");
            if (dates.length != 2) {
                // 格式不正确，跳过这一对
                continue;
            }
            try {
                // 解析开始日期和结束日期
                LocalDate startDate = LocalDate.parse(dates[0], formatter);
                LocalDate endDate = LocalDate.parse(dates[1], formatter);

                // 检查当前日期是否在范围内（包括开始和结束日期）
                if (!currentDate.isBefore(startDate) &&
                        !currentDate.isAfter(endDate)) {
                    return true;
                }
            } catch (Exception e) {
                // 日期解析错误，跳过这一对
                continue;
            }
        }
        // 没有任何一对日期范围包含当前日期
        return false;
    }

    public R<String> groupVerification(OrderCouponMiddle orderCouponMiddle) {
        LifeGroupBuyMain lifeGroupBuyMain = lifeGroupBuyMainMapper.selectOne(new LambdaQueryWrapper<LifeGroupBuyMain>().eq(LifeGroupBuyMain::getId, orderCouponMiddle.getCouponId()));
        //团购有效期类型为:0 指定天数
        if (lifeGroupBuyMain.getEffectiveDateType() == 0) {
            //订单支付时间加上指定天数 为团购劵有效期
            LifeUserOrder lifeUserOrder = lifeUserOrderMapper.selectOne(new LambdaQueryWrapper<LifeUserOrder>().eq(LifeUserOrder::getId, orderCouponMiddle.getOrderId()));
            LocalDate localDate = lifeUserOrder.getPayTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            LocalDate validityPeriod = localDate.plusDays(Long.parseLong(lifeGroupBuyMain.getEffectiveDateValue()));
            LocalDate nowDate = LocalDate.now(); // 获取当前时间
            if (nowDate.isAfter(validityPeriod)) {
                return R.fail("该劵不在有效期内");
            }
        } else if (lifeGroupBuyMain.getEffectiveDateType() == 1) {//类型为:1 指定时间段
            String[] strings = lifeGroupBuyMain.getEffectiveDateValue().split(",");
            String startDate = strings[0];
            String endDate = strings[1];
            LocalDate localStartDate = LocalDate.parse(startDate);
            LocalDate localEndDate = LocalDate.parse(endDate);
            LocalDate nowDate = LocalDate.now(); // 获取当前时间
            if (nowDate.isAfter(localEndDate) || nowDate.isBefore(localStartDate)) {
                return R.fail("该劵不在有效期内");
            }
        }
        //判断订单是否在不可用日期内
        //判断当前日期是否在不可用星期
        if (lifeGroupBuyMain.getDisableDateType() == 1) {//限制日期: 1234567;节日id
            LocalDate nowDate = LocalDate.now(); // 获取当前时间
            DayOfWeek dayOfWeek = nowDate.getDayOfWeek();
            String week = dayOfWeek.getDisplayName(TextStyle.FULL, Locale.CHINA);
            String beforeSemicolon = lifeGroupBuyMain.getDisableDateValue().split(";")[0];
            if (!StringUtils.isEmpty(beforeSemicolon)) {
                List<String> collectUnavailableDate = Arrays.stream(beforeSemicolon.split(",")).map(String::trim).collect(Collectors.toList());
                boolean isExist = collectUnavailableDate.stream().anyMatch(s -> s.equals(week));
                if (isExist) {
                    return R.fail("该劵在不可用日期内");
                }
            }
            //判断当前日期是否在不可用节日
            String[] strings = lifeGroupBuyMain.getDisableDateValue().split(";");
            if (strings.length > 1) {
                String afterSemicolon = lifeGroupBuyMain.getDisableDateValue().split(";")[1];
                List<String> collectUnavailableDate = Arrays.stream(afterSemicolon.split(",")).map(String::trim).collect(Collectors.toList());
                List<EssentialHolidayComparison> essentialHolidayComparisons = essentialHolidayComparisonMapper.
                        selectList(new LambdaQueryWrapper<EssentialHolidayComparison>().in(EssentialHolidayComparison::getId, collectUnavailableDate));
                boolean isExist = essentialHolidayComparisons.stream().anyMatch(s -> !nowDate.isBefore(s.getStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate())
                        && !nowDate.isAfter(s.getEndTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate()));
                if (isExist) {
                    return R.fail("该劵在不可用日期内");
                }
            }
        }
        //判断当前日期是否在自定义不可用日期内
        if (lifeGroupBuyMain.getDisableDateType() == 2) {
            String[] customDate = lifeGroupBuyMain.getDisableDateValue().split(";");
            boolean isExist = isCurrentDateInAnyRange(customDate);
            if (isExist) {
                return R.fail("该劵在不可用日期内");
            }
        }
        return R.success("效验通过");
    }

    public R<String> couponVerification(OrderCouponMiddle orderCouponMiddle) {
        LifeCoupon lifeCoupon = lifeCouponMapper.selectOne(new LambdaQueryWrapper<LifeCoupon>().eq(LifeCoupon::getId, orderCouponMiddle.getCouponId()));
        //代金券有效期类型为:1 指定天数
        if (lifeCoupon.getExpirationType().equals("1")) {
            //订单支付时间加上指定天数 为团购劵有效期
            LifeUserOrder lifeUserOrder = lifeUserOrderMapper.selectOne(new LambdaQueryWrapper<LifeUserOrder>().eq(LifeUserOrder::getId, orderCouponMiddle.getOrderId()));
            LocalDate localDate = lifeUserOrder.getPayTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            LocalDate validityPeriod = localDate.plusDays(lifeCoupon.getExpirationDate());
            LocalDate nowDate = LocalDate.now(); // 获取当前时间
            if (nowDate.isAfter(validityPeriod)) {
                return R.fail("该劵不在有效期内");
            }
        } else if (lifeCoupon.getExpirationType().equals("2")) {//类型为:2 指定时间段
            String[] strings = lifeCoupon.getValidityPeriod().split(",");
            long start = Long.parseLong(strings[0]);
            long end = Long.parseLong(strings[1]);
            LocalDate startDate = Instant.ofEpochMilli(start)
                    .atZone(ZoneId.systemDefault())
                    .toLocalDate();
            LocalDate endDate = Instant.ofEpochMilli(end)
                    .atZone(ZoneId.systemDefault())
                    .toLocalDate();
            LocalDate nowDate = LocalDate.now(); // 获取当前时间
            if (nowDate.isAfter(endDate) || nowDate.isBefore(startDate)) {
                return R.fail("该劵不在有效期内");
            }
        }

        //判断代金券订单是否在不可用日期内
        //判断当前日期是否在不可用星期
        if (lifeCoupon.getUnusedType().equals("2")) {//限制日期: 1234567;节日id
            LocalDate nowDate = LocalDate.now(); // 获取当前时间
            DayOfWeek dayOfWeek = nowDate.getDayOfWeek();
            String week = dayOfWeek.getDisplayName(TextStyle.FULL, Locale.CHINA);
            String beforeSemicolon = lifeCoupon.getUnavaiLableDate().split(";")[0];
            if (!StringUtils.isEmpty(beforeSemicolon)) {
                List<String> collectUnavailableDate = Arrays.stream(beforeSemicolon.split(",")).map(String::trim).collect(Collectors.toList());
                boolean isExist = collectUnavailableDate.stream().anyMatch(s -> s.equals(week));
                if (isExist) {
                    return R.fail("该劵在不可用日期内");
                }
            }

            //判断当前日期是否在不可用节日
            String[] strings = lifeCoupon.getUnavaiLableDate().split(";");
            if (strings.length > 1) {
                String afterSemicolon = lifeCoupon.getUnavaiLableDate().split(";")[1];
                List<String> collectUnavailableDate = Arrays.stream(afterSemicolon.split(",")).map(String::trim).collect(Collectors.toList());
                List<EssentialHolidayComparison> essentialHolidayComparisons = essentialHolidayComparisonMapper.
                        selectList(new LambdaQueryWrapper<EssentialHolidayComparison>().in(EssentialHolidayComparison::getId, collectUnavailableDate));
                boolean isExist = essentialHolidayComparisons.stream().anyMatch(s -> !nowDate.isBefore(s.getStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate())
                        && !nowDate.isAfter(s.getEndTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate()));
                if (isExist) {
                    return R.fail("该劵在不可用日期内");
                }
            }
        }
        //判断当前日期是否在自定义不可用日期内
        if (lifeCoupon.getUnusedType().equals("3")) {
            String[] customDate = lifeCoupon.getUnavaiLableDate().split(";");
            boolean isExist = isCurrentDateInAnyRange(customDate);
            if (isExist) {
                return R.fail("该劵在不可用日期内");
            }
        }
    /*    //有效期到
        Date date = DateUtils.calcDays(orderCouponMiddle.getCreatedTime(), lifeCoupon.getExpirationDate());
        //开始时间段
        int beginUseTime = Integer.parseInt(lifeCoupon.getBuyUseStartTime());
        //结束时间段
        int endUseTime = Integer.parseInt(lifeCoupon.getBuyUseEndTime());
        if (new Date().after(date)) {
            return R.fail("该劵已过期");
        }
        if (endUseTime < beginUseTime) {
            if (!(LocalDateTime.now().getHour() >= beginUseTime || LocalDateTime.now().getHour() < endUseTime)) {
                return R.fail("该劵未到使用时间");
            }
        } else if (endUseTime > beginUseTime) {
            if (LocalDateTime.now().getHour() < beginUseTime || LocalDateTime.now().getHour() >= endUseTime) {
                return R.fail("该劵未到使用时间");
            }
        }*/
        // 判断是否在使用时间内
        Integer buyUseStartTime = Integer.parseInt(lifeCoupon.getBuyUseStartTime());
        Integer buyUseEndTime = Integer.parseInt(lifeCoupon.getBuyUseEndTime());
        // 获取当前小时
        LocalTime now = LocalTime.now();
        int currentHour = now.getHour();
        // 验证输入的小时是否有效
        if (buyUseStartTime < 0 || buyUseStartTime > 24 || buyUseEndTime < 0 || buyUseEndTime > 24) {
            return R.fail("小时必须在0-23之间");
        }
        // 处理跨天的情况，例如22点到次日3点
        if (buyUseStartTime >= buyUseEndTime) {
            if (currentHour < buyUseStartTime && currentHour > buyUseEndTime) {
                return R.fail("该劵不在有效期内");
            }

        } else {
            if (!(currentHour >= buyUseStartTime && currentHour <= buyUseEndTime)) {
                return R.fail("该劵不在有效期内");
            }
        }

        // 获取当天开始时间（00:00:00）
        LocalDateTime todayStart = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
        // 获取当天结束时间（23:59:59.999）
        LocalDateTime todayEnd = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
        if(!lifeCoupon.getSingleCanUse().equals("0")){
            Integer orderNum = orderCouponMiddleMapper.selectCount(new LambdaQueryWrapper<OrderCouponMiddle>()
                    .eq(OrderCouponMiddle :: getOrderId, orderCouponMiddle.getOrderId())
                    .between(OrderCouponMiddle :: getUsedTime,todayStart,todayEnd)
                    .eq(OrderCouponMiddle ::getStatus, 2)
            );
            if(orderNum >= Integer.parseInt(lifeCoupon.getSingleCanUse())){
                return R.fail("该订单已经超过今日单次核销数量");
            }
        }
        return R.success("效验通过");
    }

    @Override
    public shop.alien.entity.store.vo.LifeCouponVo getNewCouponDetail(String id) {
        return lifeCouponMapper.getNewCouponDetail(id);
    }

    @Override
    public R<String> importHolidayFromExcel(MultipartFile file) {
        log.info("LifeCouponServiceImpl.importHolidayFromExcel fileName={}", file.getOriginalFilename());

        if (file == null || file.isEmpty()) {
            return R.fail("上传文件为空");
        }

        String fileName = file.getOriginalFilename();
        if (fileName == null || (!fileName.endsWith(".xlsx") && !fileName.endsWith(".xls"))) {
            return R.fail("文件格式不正确，请上传Excel文件");
        }

        List<String> errorMessages = new ArrayList<>();
        int successCount = 0;
        int totalCount = 0;

        try (InputStream inputStream = file.getInputStream();
             XSSFWorkbook workbook = new XSSFWorkbook(inputStream)) {
            Sheet sheet = workbook.getSheetAt(0);

            // 获取表头（第6行，索引为5）
            Row headerRow = sheet.getRow(5);
            if (headerRow == null) {
                return R.fail("Excel文件格式不正确，缺少表头");
            }

            // 构建字段映射（表头名称 -> 列索引）
            Map<String, Integer> headerMap = new HashMap<>();
            for (int i = 0; i < headerRow.getLastCellNum(); i++) {
                Cell cell = headerRow.getCell(i);
                if (cell != null) {
                    String headerName = getCellValueAsString(cell);
                    if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotEmpty(headerName)) {
                        headerMap.put(headerName.trim(), i);
                    }
                }
            }

            // 验证表头
            if (!headerMap.containsKey("年份") || !headerMap.containsKey("节日名称") 
                    || !headerMap.containsKey("开始时间") || !headerMap.containsKey("结束时间")) {
                return R.fail("Excel文件格式不正确，缺少必要的表头字段（年份、节日名称、开始时间、结束时间）");
            }

            // 读取数据行（从第7行开始，索引为6）
            for (int rowIndex = 6; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
                Row row = sheet.getRow(rowIndex);
                if (row == null) {
                    continue;
                }

                // 检查是否为空行
                boolean isEmptyRow = true;
                for (int i = 0; i < row.getLastCellNum(); i++) {
                    Cell cell = row.getCell(i);
                    if (cell != null && cell.getCellType() != CellType.BLANK) {
                        String cellValue = getCellValueAsString(cell);
                        if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotEmpty(cellValue)) {
                            isEmptyRow = false;
                            break;
                        }
                    }
                }
                if (isEmptyRow) {
                    continue;
                }

                totalCount++;
                EssentialHolidayComparison holiday = new EssentialHolidayComparison();

                try {
                    // 读取年份（必填）
                    Integer yearColIndex = headerMap.get("年份");
                    if (yearColIndex == null) {
                        throw new RuntimeException("缺少年份字段");
                    }
                    Cell yearCell = row.getCell(yearColIndex);
                    String yearValue = getCellValueAsString(yearCell);
                    if (StringUtils.isEmpty(yearValue)) {
                        throw new RuntimeException("年份不能为空");
                    }
                    // 处理年份可能是数字的情况
                    if (yearCell != null && yearCell.getCellType() == CellType.NUMERIC) {
                        double numericValue = yearCell.getNumericCellValue();
                        yearValue = String.valueOf((long) numericValue);
                    }
                    holiday.setParticularYear(yearValue.trim());

                    // 读取节日名称（必填）
                    Integer nameColIndex = headerMap.get("节日名称");
                    if (nameColIndex == null) {
                        throw new RuntimeException("缺少节日名称字段");
                    }
                    Cell nameCell = row.getCell(nameColIndex);
                    String nameValue = getCellValueAsString(nameCell);
                    if (StringUtils.isEmpty(nameValue)) {
                        throw new RuntimeException("节日名称不能为空");
                    }
                    holiday.setFestivalName(nameValue.trim());

                    // 读取开始时间（必填，格式：2026-01-01）
                    Integer startTimeColIndex = headerMap.get("开始时间");
                    if (startTimeColIndex == null) {
                        throw new RuntimeException("缺少开始时间字段");
                    }
                    Cell startTimeCell = row.getCell(startTimeColIndex);
                    String startTimeValue = getCellValueAsString(startTimeCell);
                    if (StringUtils.isEmpty(startTimeValue)) {
                        throw new RuntimeException("开始时间不能为空");
                    }
                    Date startTime = parseDate(startTimeValue.trim(), rowIndex + 1);
                    holiday.setStartTime(startTime);

                    // 读取结束时间（必填，格式：2026-01-01）
                    Integer endTimeColIndex = headerMap.get("结束时间");
                    if (endTimeColIndex == null) {
                        throw new RuntimeException("缺少结束时间字段");
                    }
                    Cell endTimeCell = row.getCell(endTimeColIndex);
                    String endTimeValue = getCellValueAsString(endTimeCell);
                    if (StringUtils.isEmpty(endTimeValue)) {
                        throw new RuntimeException("结束时间不能为空");
                    }
                    Date endTime = parseDate(endTimeValue.trim(), rowIndex + 1);
                    holiday.setEndTime(endTime);

                    // 验证结束时间必须大于等于开始时间
                    if (endTime.before(startTime)) {
                        throw new RuntimeException("结束时间必须大于等于开始时间");
                    }

                    // 读取状态（可选，默认启用）
                    Integer statusColIndex = headerMap.get("状态");
                    int openFlag = 1; // 默认启用
                    if (statusColIndex != null) {
                        Cell statusCell = row.getCell(statusColIndex);
                        String statusValue = getCellValueAsString(statusCell);
                        if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotEmpty(statusValue)) {
                            String status = statusValue.trim();
                            if ("启用".equals(status) || "1".equals(status)) {
                                openFlag = 1;
                            } else if ("禁用".equals(status) || "0".equals(status)) {
                                openFlag = 0;
                            } else {
                                throw new RuntimeException("状态格式错误，请输入'启用'或'禁用'");
                            }
                        }
                    }
                    holiday.setOpenFlag(openFlag);
                    holiday.setDelFlag(0);

                    // 设置节日日期为开始时间
                    LocalDate startLocalDate = startTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                    holiday.setFestivalDate(startLocalDate);

                    // 保存数据
                    essentialHolidayComparisonMapper.insert(holiday);
                    successCount++;
                } catch (Exception e) {
                    errorMessages.add(String.format("第%d行：%s", rowIndex + 1, e.getMessage()));
                    log.error("导入第{}行数据失败", rowIndex + 1, e);
                }
            }
        } catch (Exception e) {
            log.error("导入Excel失败", e);
            return R.fail("导入失败：" + e.getMessage());
        }

        // 构建返回消息
        StringBuilder message = new StringBuilder();
        message.append(String.format("导入完成：成功%d条，失败%d条", successCount, totalCount - successCount));
        if (!errorMessages.isEmpty()) {
            message.append("\n失败详情：\n");
            for (int i = 0; i < Math.min(errorMessages.size(), 10); i++) {
                message.append(errorMessages.get(i)).append("\n");
            }
            if (errorMessages.size() > 10) {
                message.append("...还有").append(errorMessages.size() - 10).append("条错误信息");
            }
        }

        return R.success(message.toString());
    }

    @Override
    public boolean deleteCoupon(Integer id) {
        LambdaUpdateWrapper<LifeCoupon> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(LifeCoupon :: getId, id);
        lambdaUpdateWrapper.set(LifeCoupon :: getDeleteFlag, 1);
        lifeCouponMapper.update(null, lambdaUpdateWrapper);
        return true;
    }

    /**
     * 解析日期字符串
     */
    private Date parseDate(String dateStr, int rowNum) {
        try {
            // 尝试多种日期格式
            SimpleDateFormat[] formats = {
                new SimpleDateFormat("yyyy-MM-dd"),
                new SimpleDateFormat("yyyy/MM/dd"),
                new SimpleDateFormat("yyyy年MM月dd日")
            };

            for (SimpleDateFormat format : formats) {
                try {
                    return format.parse(dateStr);
                } catch (Exception e) {
                    // 继续尝试下一个格式
                }
            }

            // 如果都失败，尝试解析数字日期（Excel日期格式）
            try {
                double numericValue = Double.parseDouble(dateStr);
                return org.apache.poi.ss.usermodel.DateUtil.getJavaDate(numericValue);
            } catch (Exception e) {
                // 忽略
            }

            throw new RuntimeException("日期格式错误，请使用格式：2026-01-01");
        } catch (Exception e) {
            throw new RuntimeException("日期格式错误，请使用格式：2026-01-01");
        }
    }

    /**
     * 获取单元格值（字符串格式）
     */
    private String getCellValueAsString(Cell cell) {
        if (cell == null) {
            return null;
        }

        switch (cell.getCellType()) {
            case STRING:
                return cell.getStringCellValue();
            case NUMERIC:
                if (org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell)) {
                    // 日期格式
                    Date date = cell.getDateCellValue();
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                    return sdf.format(date);
                } else {
                    // 处理数字，避免科学计数法
                    double numericValue = cell.getNumericCellValue();
                    if (numericValue == (long) numericValue) {
                        return String.valueOf((long) numericValue);
                    } else {
                        return String.valueOf(numericValue);
                    }
                }
            case BOOLEAN:
                return String.valueOf(cell.getBooleanCellValue());
            case FORMULA:
                try {
                    return cell.getStringCellValue();
                } catch (Exception e) {
                    return String.valueOf(cell.getNumericCellValue());
                }
            default:
                return null;
        }
    }

}
