package com.ruoyi.system.service.impl;

import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.system.mapper.PromotionActivityMapper;
import com.ruoyi.system.mapper.PromotionActivityRuleMapper;
import com.ruoyi.system.domain.PromotionActivity;
import com.ruoyi.system.domain.PromotionActivityRule;
import com.ruoyi.system.service.IPromotionActivityService;

/**
 * 促销活动Service业务层处理
 *
 * @author ruoyi
 * @date 2024-05-30
 */
@Service
public class PromotionActivityServiceImpl extends ServiceImpl<BaseMapper<PromotionActivity>, PromotionActivity> implements IPromotionActivityService
{
    @Autowired
    private PromotionActivityMapper promotionActivityMapper;

    @Autowired
    private PromotionActivityRuleMapper ruleMapper;

    @Autowired
    private PromotionDiscountLimitChecker discountLimitChecker;

    /**
     * 创建促销活动（含规则）
     */
    @Override
    @Transactional
    public boolean createActivity(PromotionActivity activity, List<PromotionActivityRule> rules)
    {
        Date now = new Date();
        activity.setCreateTime(now);
        activity.setUpdateTime(now);
        // 根据开始时间设置状态：开始时间早于当前→进行中(1)，否则→未开始(0)
        if (activity.getStartTime() != null && activity.getStartTime().before(now))
        {
            activity.setStatus(1);
        }
        else
        {
            activity.setStatus(0);
        }
        // 校验：同一门店同一促销类型，同一时间段内只允许一个活动（时间段重叠即拒绝）
        checkTimeOverlap(activity, null);
        // 校验：优惠幅度限制（平台开关控制，满减档位/折扣率不超上限）
        discountLimitChecker.checkActivity(activity, rules);
        int rows = promotionActivityMapper.insert(activity);
        Long activityId = activity.getId();
        // 逐条插入规则
        for (PromotionActivityRule rule : rules)
        {
            rule.setActivityId(activityId);
            ruleMapper.insert(rule);
        }
        return rows > 0;
    }

    /**
     * 校验：同一门店同一促销类型，时间段不与其他活动重叠（排除 excludeId）。
     * 重叠判定：existing.start &le; newEnd 且 existing.end &ge; newStart（端点相接也视为重叠，禁止 06-16 当天两个活动都进行中）
     */
    private void checkTimeOverlap(PromotionActivity activity, Long excludeId)
    {
        LambdaQueryWrapper<PromotionActivity> w = new LambdaQueryWrapper<>();
        w.eq(PromotionActivity::getStoreId, activity.getStoreId())
                .eq(PromotionActivity::getType, activity.getType())
                .ne(PromotionActivity::getStatus, 2) // 排除已结束/已停止，允许在其原时段重新建促销
                .le(PromotionActivity::getStartTime, activity.getEndTime())
                .ge(PromotionActivity::getEndTime, activity.getStartTime());
        if (excludeId != null)
        {
            w.ne(PromotionActivity::getId, excludeId);
        }
        if (promotionActivityMapper.selectCount(w) > 0)
        {
            throw new ServiceException("该门店该类型活动在该时间段内已存在，请调整活动时间");
        }
    }

    /**
     * 查询活动详情（含规则）
     */
    @Override
    public PromotionActivity selectActivityWithRules(Long id)
    {
        PromotionActivity activity = promotionActivityMapper.selectById(id);
        if (activity != null)
        {
            List<PromotionActivityRule> rules = ruleMapper.selectRulesByActivityId(id);
            activity.setRules(rules);
        }
        return activity;
    }

    /**
     * 修改促销活动（仅未开始）
     */
    @Override
    @Transactional
    public boolean updateActivity(PromotionActivity activity, List<PromotionActivityRule> rules)
    {
        Long activityId = activity.getId();
        PromotionActivity existing = promotionActivityMapper.selectById(activityId);
        if (existing == null || existing.getStatus() != 0)
        {
            throw new ServiceException("只能修改未开始的活动");
        }
        Date now = new Date();
        activity.setUpdateTime(now);
        // 根据开始时间设置状态：开始时间早于当前→进行中(1)，否则→未开始(0)
        if (activity.getStartTime() != null && activity.getStartTime().before(now))
        {
            activity.setStatus(1);
        }
        else
        {
            activity.setStatus(0);
        }
        // 校验：同一门店同一促销类型，同一时间段内只允许一个活动（排除自身）
        checkTimeOverlap(activity, activityId);
        // 编辑入参可能不带 type，回填现有值供优惠幅度校验用（写回同值无副作用）
        if (activity.getType() == null)
        {
            activity.setType(existing.getType());
        }
        // 校验：优惠幅度限制（平台开关控制，满减档位/折扣率不超上限）
        discountLimitChecker.checkActivity(activity, rules);
        int rows = promotionActivityMapper.updateById(activity);
        // 删除旧规则
        ruleMapper.delete(new LambdaQueryWrapper<PromotionActivityRule>().eq(PromotionActivityRule::getActivityId, activityId));
        // 重新插入新规则
        for (PromotionActivityRule rule : rules)
        {
            rule.setActivityId(activityId);
            ruleMapper.insert(rule);
        }
        return rows > 0;
    }

    /**
     * 删除促销活动（仅未开始）
     */
    @Override
    @Transactional
    public boolean deleteActivity(Long id)
    {
        PromotionActivity existing = promotionActivityMapper.selectById(id);
        if (existing == null || existing.getStatus() != 0)
        {
            throw new ServiceException("只能删除未开始的活动");
        }
        // 删除规则
        ruleMapper.delete(new LambdaQueryWrapper<PromotionActivityRule>().eq(PromotionActivityRule::getActivityId, id));
        // 删除活动
        return promotionActivityMapper.deleteById(id) > 0;
    }

    /**
     * 结束活动（仅进行中）
     */
    @Override
    public boolean endActivity(Long id)
    {
        PromotionActivity existing = promotionActivityMapper.selectById(id);
        if (existing == null || existing.getStatus() != 1)
        {
            throw new ServiceException("只能结束进行中的活动");
        }
        PromotionActivity activity = new PromotionActivity();
        activity.setId(id);
        activity.setStatus(2);
        activity.setUpdateTime(new Date());
        return promotionActivityMapper.updateById(activity) > 0;
    }
}
