package com.sikey.wa04.business.application.service.user;

import com.sikey.wa04.business.application.converter.MessageConverter;
import com.sikey.wa04.business.application.service.BaseService;
import com.sikey.wa04.business.domain.adapter.DeviceConfigAdapter;
import com.sikey.wa04.business.domain.adapter.MessageAdapter;
import com.sikey.wa04.business.domain.entity.message.Message;
import com.sikey.wa04.business.infrastructure.adapter.RabbitMQMessaging;
import com.sikey.wa04.business.infrastructure.adapter.RedisMessageIdIncrementingAdapter;
import com.sikey.wa04.business.infrastructure.dto.model.ChildAlarmClockModel;
import com.sikey.wa04.business.infrastructure.dto.request.alarmclock.CreateAlarmClockRequest;
import com.sikey.wa04.business.infrastructure.dto.request.alarmclock.DeleteAlarmClockRequest;
import com.sikey.wa04.business.infrastructure.dto.request.alarmclock.GetallAlarmClockRequest;
import com.sikey.wa04.business.infrastructure.dto.request.alarmclock.UpdateAlarmClockRequest;
import com.sikey.wa04.business.infrastructure.dto.response.alarmclock.GetallAlarmClockResponse;
import com.sikey.wa04.business.infrastructure.repository.ChildAlarmClockRepository;
import com.sikey.wa04.common.dto.header.GenericManufacturerHeader;
import com.sikey.wa04.common.dto.message.AlarmClockChangeNoticeMessage;
import com.sikey.wa04.common.enums.MessageType;
import com.sikey.wa04.common.interceptor.CurrentRequestUser;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;

/**
 * 闹钟
 *
 * @author luoyangwei
 * @date 2024年10月16日18:06:32
 */
@Slf4j
@Service
public class AlarmClockService extends BaseService {

    @Resource
    private ChildAlarmClockRepository childAlarmClockRepository;

    @Resource
    private DeviceConfigAdapter deviceConfigAdapter;

    @Qualifier("myTaskExecutor")
    @Autowired
    private ThreadPoolTaskExecutor myTaskExecutor;

    @Resource
    private RedisMessageIdIncrementingAdapter redisMessageIdIncrementingAdapter;

    @Resource
    private MessageAdapter messageAdapter;

    @Resource
    private RabbitMQMessaging rabbitMQMessaging;

    /**
     * 创建闹钟
     *
     * @param request 请求
     */
    @Transactional(rollbackFor = Exception.class)
    public void create(CreateAlarmClockRequest request, GenericManufacturerHeader genericManufacturerHeader) {
        ChildAlarmClockModel model = new ChildAlarmClockModel();
        model.setChildId(request.cid());
        model.setLabel(request.label());
        model.setRepeats(request.repeats());
        model.setTime(request.time());
        model.setOnceTime(request.onceTime());
        model.setStatus(request.status());
        childAlarmClockRepository.save(model);

        // 发送mq闹钟消息
        handleAlarmClockChangeNoticeMessage(model.getId(), request.cid(), request.label(), request.repeats(), request.time(), request.onceTime(), request.status(), genericManufacturerHeader);
    }

    /**
     * 闹钟变动
     *
     * @param id       小孩闹钟id
     * @param cid      小孩ID
     * @param label    标签
     * @param repeats  重复次数
     * @param time     闹钟时间
     * @param onceTime 仅一次时间戳
     * @param status   状态
     * @param header   请求header
     * @return
     */
    private void handleAlarmClockChangeNoticeMessage(Long id, String cid, String label, String repeats, String time, Long onceTime, Boolean status, GenericManufacturerHeader header) {
        // 发送mq闹钟消息
        AlarmClockChangeNoticeMessage noticeMessage = new AlarmClockChangeNoticeMessage();
        noticeMessage.setMsgType(MessageType.ALARM_CLOCK_CHANGE_NOTICE_MESSAGE)
                .setMsgId(redisMessageIdIncrementingAdapter.incr())
                .setSendTime(Instant.now().toEpochMilli())
                .setSendId(CurrentRequestUser.get().getId())
                .setRecvId(cid);

        AlarmClockChangeNoticeMessage.AlarmClockChangeNoticeMessageContent content = new AlarmClockChangeNoticeMessage.AlarmClockChangeNoticeMessageContent();
        content.setAcid(id);
        content.setCid(cid);
        content.setLabel(label);
        content.setRepeats(repeats);
        content.setTime(time);
        content.setOnceTime(onceTime);
        content.setStatus(status);
        noticeMessage.setContent(content);

        Message message = MessageConverter.formMessaging(noticeMessage);
        messageAdapter.save(message);

        myTaskExecutor.execute(() -> {
            Object messagingObject = MessageConverter.toMessaging(message);
            rabbitMQMessaging.publish(header, messagingObject);
        });
    }

    /**
     * 更新闹钟
     *
     * @param request 请求
     * @return 返回
     */
    @Transactional(rollbackFor = Exception.class)
    public void update(UpdateAlarmClockRequest request, GenericManufacturerHeader genericManufacturerHeader) {
        Optional<ChildAlarmClockModel> optional = childAlarmClockRepository.findById(request.acid());
        ChildAlarmClockModel model = optional.orElseThrow(() -> new RuntimeException("Not found alarm clock"));
        model.setLabel(request.label());
        model.setRepeats(request.repeats());
        model.setTime(request.time());
        model.setOnceTime(request.onceTime());
        model.setStatus(request.status());
        childAlarmClockRepository.save(model);

        // 发送mq闹钟消息
        handleAlarmClockChangeNoticeMessage(model.getId(), model.getChildId(), request.label(), request.repeats(), request.time(), request.onceTime(), request.status(), genericManufacturerHeader);
    }


    /**
     * 删除闹钟
     *
     * @param request 请求
     */
    @Transactional(rollbackFor = Exception.class)
    public void delete(DeleteAlarmClockRequest request, GenericManufacturerHeader genericManufacturerHeader) {
        Optional<ChildAlarmClockModel> optional = childAlarmClockRepository.findById(request.acid());
        ChildAlarmClockModel model = optional.orElseThrow(() -> new RuntimeException("Not found alarm clock"));
        childAlarmClockRepository.delete(model);

        // 发送mq闹钟消息
        handleAlarmClockChangeNoticeMessage(model.getId(), model.getChildId(), model.getLabel(), model.getRepeats(), model.getTime(), model.getOnceTime(), model.getStatus(), genericManufacturerHeader);
    }

    /**
     * 获取所有闹钟
     *
     * @return 返回
     */
    public GetallAlarmClockResponse getall(GetallAlarmClockRequest request, GenericManufacturerHeader genericManufacturerHeader, boolean isWristwatch) {
        List<ChildAlarmClockModel> models = childAlarmClockRepository.findByChildId(request.cid());

        // 按 time 字段正序排序（从小到大）
        models.sort(Comparator.comparing(ChildAlarmClockModel::getTime));

        List<GetallAlarmClockResponse.GetallAlarmClock> alarmClocks = new ArrayList<>();
        for (ChildAlarmClockModel model : models) {
            GetallAlarmClockResponse.GetallAlarmClock alarmClock = new GetallAlarmClockResponse.GetallAlarmClock()
                    .setCid(model.getChildId())
                    .setLabel(model.getLabel())
                    .setRepeats(model.getRepeats())
                    .setTime(model.getTime())
                    .setOnceTime(model.getOnceTime())
                    .setAcid(model.getId())
                    .setStatus(model.getStatus());
            alarmClocks.add(alarmClock);
        }

        if(isWristwatch){
            myTaskExecutor.execute(() -> {
                // 设备配置
                deviceConfigAdapter.deviceConfigMessageCenter(request.cid(), genericManufacturerHeader);
            });
        }


        return new GetallAlarmClockResponse()
                .setAlarmClocks(alarmClocks);
    }
}
