package com.czg.service.market.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.czg.account.service.ShopInfoService;
import com.czg.config.RabbitPublisher;
import com.czg.config.RedisCst;
import com.czg.exception.CzgException;
import com.czg.market.dto.SmsPushEventDTO;
import com.czg.market.entity.SmsPushEvent;
import com.czg.market.entity.SmsPushEventUser;
import com.czg.market.service.MkShopCouponRecordService;
import com.czg.market.service.SmsPushEventService;
import com.czg.service.RedisService;
import com.czg.service.market.mapper.SmsPushEventMapper;
import com.czg.service.market.mapper.SmsPushEventUserMapper;
import com.czg.utils.AssertUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

/**
 * 营销推送发送记录 服务层实现。
 *
 * @author ww
 * @since 2025-10-14
 */
@Slf4j
@Service
public class SmsPushEventServiceImpl extends ServiceImpl<SmsPushEventMapper, SmsPushEvent> implements SmsPushEventService {

    @Resource
    private SmsPushEventUserMapper eventUserMapper;
    @DubboReference
    private ShopInfoService shopInfoService;
    @Resource
    private MkShopCouponRecordService couponRecordService;
    @Resource
    private RabbitPublisher rabbitPublisher;
    @Resource
    private RedisService redisService;

    @Override
    public Page<SmsPushEventDTO> getPushEventPage(Integer page, Integer size, Long shopId, Integer status, Long id) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq(SmsPushEvent::getShopId, shopId)
                .eq(SmsPushEvent::getId, id)
                .eq(SmsPushEvent::getStatus, status)
                .eq(SmsPushEvent::getIsDel, 0)
                .orderBy(SmsPushEvent::getCreateTime).desc();
        Page<SmsPushEventDTO> page1 = pageAs(new Page<>(page, size), queryWrapper, SmsPushEventDTO.class);
        for (SmsPushEventDTO record : page1.getRecords()) {
            if (record.getUserType() != 2) {
                continue;
            }
            SmsPushEventUser eventUser = eventUserMapper.selectOneByQuery(
                    new QueryWrapper()
                            .eq(SmsPushEventUser::getType, "sms")
                            .eq(SmsPushEventUser::getEventId, record.getId())
            );
            record.setSmsPushEventUser(eventUser);
        }
        return page1;
    }

    @Override
    @Transactional
    public void addPushEvent(SmsPushEventDTO param) {
        AssertUtil.isNull(param.getUserType(), "请选择用户范围后进行推送");
        if (param.getUserType() == 2 && param.getSmsPushEventUser() == null) {
            throw new CzgException("范围推送时，必须指定用户范围");
        } else if (param.getUserType() == 3 && param.getUserId() == null) {
            throw new CzgException("指定推送时，必须指定用户");
        }
        AssertUtil.isNull(param.getPushEventId(), "请选择模板后进行推送");
        AssertUtil.isNull(param.getContent(), "消息内容不能为空");
        if (param.getSendType() == 2) {
            AssertUtil.isNull(param.getSendTime(), "定时发送时，必须指定发送时间");
        } else {
            param.setSendTime(LocalDateTime.now());
        }
        SmsPushEvent pushEvent = BeanUtil.toBean(param, SmsPushEvent.class);
        save(pushEvent);
        if (param.getUserType() == 2) {
            SmsPushEventUser eventUser = param.getSmsPushEventUser();
            eventUser.setType("sms");
            eventUser.setShopId(param.getShopId());
            eventUser.setEventId(pushEvent.getId());
            eventUserMapper.insert(eventUser);
        }
        param.setId(pushEvent.getId());
        Long mainShopId = shopInfoService.getMainIdByShopId(param.getShopId());
        // 推送消息 进行 消息发送
        rabbitPublisher.sendApplySmsMsg(mainShopId + "," + pushEvent.getId(), "sendMarkSms");
        if (param.getSendType() == 1 && StrUtil.isNotBlank(param.getCoupon())) {
            couponRecordService.smsGrantCoupon(param);
        }
    }

    @Override
    @Transactional
    public void upPushEvent(SmsPushEventDTO param) {
        AssertUtil.isNull(param.getUserType(), "请选择用户范围后进行推送");
        if (param.getUserType() == 2 && param.getSmsPushEventUser() == null) {
            throw new CzgException("范围推送时，必须指定用户范围");
        } else if (param.getUserType() == 3 && param.getUserId() == null) {
            throw new CzgException("指定推送时，必须指定用户");
        }
        AssertUtil.isNull(param.getPushEventId(), "请选择模板后进行推送");
        AssertUtil.isNull(param.getContent(), "消息内容不能为空");
        if (param.getSendType() == 2) {
            AssertUtil.isNull(param.getSendTime(), "定时发送时，必须指定发送时间");
        } else {
            param.setSendTime(LocalDateTime.now());
        }
        SmsPushEvent pushEvent = BeanUtil.toBean(param, SmsPushEvent.class);
        updateById(pushEvent);
        eventUserMapper.deleteByQuery(new QueryWrapper().eq(SmsPushEventUser::getEventId, pushEvent.getId()));
        if (param.getUserType() == 2) {
            SmsPushEventUser eventUser = param.getSmsPushEventUser();
            eventUser.setType("sms");
            eventUser.setShopId(param.getShopId());
            eventUser.setEventId(pushEvent.getId());
            eventUserMapper.insert(eventUser);
        }
        Long mainShopId = shopInfoService.getMainIdByShopId(param.getShopId());
        // 推送消息 进行 消息发送
        rabbitPublisher.sendApplySmsMsg(mainShopId + "," + pushEvent.getId(), "sendMarkSms");
        if (param.getSendType() == 1 && StrUtil.isNotBlank(param.getCoupon())) {
            couponRecordService.smsGrantCoupon(param);
        }
    }

    @Override
    public void sendPushEventCoupon(String eventId) {
        SmsPushEvent smsPushEvent = getOne(new QueryWrapper().eq(SmsPushEvent::getId, eventId));
        AssertUtil.isNull(smsPushEvent, "券发放失败，推送事件不存在");
        if (StrUtil.isNotBlank(smsPushEvent.getCoupon())) {
            SmsPushEventDTO pushEvent = BeanUtil.toBean(smsPushEvent, SmsPushEventDTO.class);
            SmsPushEventUser eventUser = eventUserMapper.selectOneByQuery(
                    new QueryWrapper()
                            .eq(SmsPushEventUser::getType, "sms")
                            .eq(SmsPushEventUser::getEventId, eventId)
            );
            pushEvent.setSmsPushEventUser(eventUser);
            couponRecordService.smsGrantCoupon(pushEvent);
        }
    }

    /**
     * 逻辑删除记录
     */
    @Override
    public void deletePushEvent(Long id) {
        SmsPushEvent pushEvent = getById(id);
        AssertUtil.isNull(pushEvent, "记录不存在");
        if (pushEvent.getStatus() == 2) {
            throw new CzgException("已发送的记录不能删除");
        }
        redisService.del(RedisCst.classKeyExpired.EXPIRED_SMS + id);
        pushEvent.setIsDel(1);
        updateById(pushEvent);
    }
}
