package com.yuchen.saas.park.service.service.door.config.impl;

import com.yuchen.saas.park.api.entity.door.config.DoorAccessControlConfigIssueTask;
import com.yuchen.saas.park.service.mapper.door.config.DoorAccessControlConfigIssueTaskDetailsRepository;
import com.yuchen.saas.park.service.mapper.door.config.DoorAccessControlConfigIssueTaskRepository;
import com.yuchen.saas.park.service.mapper.door.config.DoorAccessControlConfigTriggerRepository;
import com.yuchen.saas.park.service.service.door.config.DoorAccessControlConfigIssueTaskScheduleService;
import com.yuchen.saas.park.service.service.door.config.DoorAccessControlConfigIssueTaskService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import static java.util.stream.Collectors.*;

@Service
@Slf4j
@RequiredArgsConstructor
public class DoorAccessControlConfigIssueTaskScheduleServiceImpl implements DoorAccessControlConfigIssueTaskScheduleService {
    private static final int BATCH_TRIGGER_SIZE = 20;
    private static final int BATCH_SCHEDULE_SIZE = 10;

    private final DoorAccessControlConfigTriggerRepository doorAccessControlConfigTriggerRepository;
    private final DoorAccessControlConfigIssueTaskRepository doorAccessControlConfigIssueTaskRepository;
    private final DoorAccessControlConfigIssueTaskDetailsRepository doorAccessControlConfigIssueTaskDetailsRepository;

    private final DoorAccessControlConfigIssueTaskService doorAccessControlConfigIssueTaskService;

    private final ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();

    @Override
    public void scheduleTriggerAndHandleTask() {
        scheduledExecutorService.scheduleWithFixedDelay(() -> {
            log.info("====== scheduleTrigger ======");

            this.scheduleTrigger();

            log.info("====== scheduleTask ======");

            this.scheduleTask();
        }, 5, 10, TimeUnit.SECONDS);
    }

    public void scheduleTrigger() {
        // 循环执行触发器调度
        while (true) {
            // 获取未处理的触发器列表
            val list = doorAccessControlConfigTriggerRepository.listUnprocessed(BATCH_TRIGGER_SIZE);

            // 如果列表为空，则跳出循环
            if (list.isEmpty()) {
                break;
            }

            // 处理每个触发器
            list.forEach(doorAccessControlConfigIssueTaskService::handleTrigger);
        }
    }

    public void scheduleTask() {
        // 循环处理未处理的任务
        while (true) {
            // 获取未处理的任务列表，每次获取 BATCH_SCHEDULE_SIZE 个
            val list = doorAccessControlConfigIssueTaskRepository.listUnprocessed(BATCH_SCHEDULE_SIZE);

            // 如果任务列表为空，则跳出循环
            if (CollectionUtils.isEmpty(list)) {
                break;
            }

            // 按目标分组处理任务
            list.stream().collect(groupingBy(DoorAccessControlConfigIssueTask::getTarget)).values().forEach(doorAccessControlConfigIssueTaskService::handleTask);
        }
    }
}
