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

import com.yuchen.saas.park.api.commons.entity.SimpleEntity;
import com.yuchen.saas.park.api.commons.enums.DoorAccessControlConfigType;
import com.yuchen.saas.park.api.entity.door.config.DoorAccessControlConfigIssueTask;
import com.yuchen.saas.park.api.entity.door.config.DoorAccessControlConfigTrigger;
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.domain.task.TaskListContext;
import com.yuchen.saas.park.service.service.door.config.DoorAccessControlConfigIssueTaskComponent;
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.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotEmpty;
import java.util.List;
import java.util.Map;

import static com.yuchen.saas.park.api.commons.enums.DoorAccessControlConfigType.*;
import static java.util.Optional.ofNullable;
import static java.util.stream.Collectors.*;

@Service
@Slf4j
@RequiredArgsConstructor
public class DoorAccessControlConfigIssueTaskServiceImpl implements DoorAccessControlConfigIssueTaskService {
    private final DoorAccessControlConfigTriggerRepository doorAccessControlConfigTriggerRepository;
    private final DoorAccessControlConfigIssueTaskRepository doorAccessControlConfigIssueTaskRepository;
    private final DoorAccessControlConfigIssueTaskDetailsRepository doorAccessControlConfigIssueTaskDetailsRepository;

    private final DoorAccessControlConfigIssueTaskComponent doorAccessControlConfigIssueTaskComponent;

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @Override
    public void handleTrigger(DoorAccessControlConfigTrigger o) {
        // 如果对象已经处理过，则直接返回
        if (o.isProcessed()) {
            return;
        }

        // 获取目标对象
        val target = o.getTarget();

        // 根据目标对象获取相关的任务列表
        val list = doorAccessControlConfigIssueTaskRepository.listByTarget(target);

        // 根据对象的类型进行不同的操作
        switch (o.getType()) {
            case ALL:
                // 保存用户相关的任务
                doorAccessControlConfigIssueTaskComponent.saveUserSchedule(target, list);
                // 保存卡片相关的任务
                doorAccessControlConfigIssueTaskComponent.saveCardSchedule(target, list);
                // 保存面部识别相关的任务
                doorAccessControlConfigIssueTaskComponent.saveFacialSchedule(target, list);
                break;
            case USER:
                // 保存用户相关的任务
                doorAccessControlConfigIssueTaskComponent.saveUserSchedule(target, list);
                break;
            case CARD:
                // 保存卡片相关的任务
                doorAccessControlConfigIssueTaskComponent.saveCardSchedule(target, list);
                break;
            case FACIAL:
                // 保存面部识别相关的任务
                doorAccessControlConfigIssueTaskComponent.saveFacialSchedule(target, list);
                break;
            default:
                break;
        }

        // 更新对象的处理状态为已处理
        doorAccessControlConfigTriggerRepository.updateById(o.setProcessed(true));
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @Override
    public void handleTask(@NotEmpty List<DoorAccessControlConfigIssueTask> list) {
        // 将list中的每个元素通过getId方法获取ID，并将所有ID收集到Set集合中
        val ids = list.stream().map(SimpleEntity::getId).collect(toSet());

        // 根据未处理的parentId查询未处理的DoorAccessControlConfigIssueTaskDetails
        val details = doorAccessControlConfigIssueTaskDetailsRepository.listUnprocessedByParentIds(ids);

        // 将list中的元素按照类型进行分组，返回一个Map集合，其中key为DoorAccessControlConfigType，value为List集合，包含该类型的DoorAccessControlConfigIssueTask
        Map<DoorAccessControlConfigType, List<DoorAccessControlConfigIssueTask>> map = list.stream().collect(groupingBy(DoorAccessControlConfigIssueTask::getType));

        // 如果map中USER类型的元素不为空，则将该元素转换为TaskListContext对象，并调用handleUserTask方法处理
        ofNullable(map.get(USER)).filter(o -> !o.isEmpty()).map(o -> TaskListContext.from(o, details)).ifPresent(doorAccessControlConfigIssueTaskComponent::handleUserTask);

        // 如果map中CARD类型的元素不为空，则将该元素转换为TaskListContext对象，并调用handleCardTask方法处理
        ofNullable(map.get(CARD)).filter(o -> !o.isEmpty()).map(o -> TaskListContext.from(o, details)).ifPresent(doorAccessControlConfigIssueTaskComponent::handleCardTask);

        // 如果map中FACIAL类型的元素不为空，则将该元素转换为TaskListContext对象，并调用handleFacialTask方法处理
        ofNullable(map.get(FACIAL)).filter(o -> !o.isEmpty()).map(o -> TaskListContext.from(o, details)).ifPresent(doorAccessControlConfigIssueTaskComponent::handleFacialTask);

    }
}
