package com.bcxin.tenant.open.domains.utils;

import com.bcxin.tenant.open.document.domains.documents.RoomDocument;
import com.bcxin.tenant.open.document.domains.repositories.RoomDocumentRepository;
import com.bcxin.tenant.open.domains.BillPaymentRuleConfig;
import com.bcxin.tenant.open.domains.dtos.RoomCommunicatedGroupDTO;
import com.bcxin.tenant.open.domains.entities.RoomUserEntity;
import com.bcxin.tenant.open.domains.views.TencentCallbackLogView;
import com.bcxin.tenant.open.infrastructures.components.IdWorker;
import com.bcxin.tenant.open.infrastructures.components.JsonProvider;
import com.bcxin.tenant.open.infrastructures.enums.DeskType;
import com.bcxin.tenant.open.infrastructures.enums.DispatchReasonType;
import com.bcxin.tenant.open.infrastructures.exceptions.BadTenantException;
import com.redis.om.spring.search.stream.EntityStream;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;
import java.util.stream.Collectors;

public class RoomCommunicatedGroupUtils {
    private static final ThreadLocal<Collection<String>> _innerExceptionLocalStore = new InheritableThreadLocal<>();

    /**
     * 房间结束之后才开始进行通讯日志以及联动值的计算
     *
     * @param
     * @param roomIds
     * @return
     */
    public static Collection<RoomCommunicatedGroupDTO> build(
            RoomDocumentRepository roomDocumentRepository,
            JsonProvider jsonProvider,
            Collection<Long> roomIds,
            Collection<TencentCallbackLogView> roomRelatedData,
            Collection<RoomUserEntity> roomUsers,
            EntityStream entityStream,
            BillPaymentRuleConfig billPaymentRuleConfig) {
        _innerExceptionLocalStore.set(new ArrayList<>());
        if (CollectionUtils.isEmpty(roomIds)) {
            return Collections.EMPTY_LIST;
        }

        Collection<RoomCommunicatedGroupDTO> roomCommunicatedGroups =
                roomIds.stream().map(roomId -> {
                    try {
                        Collection<TencentCallbackLogView> matchedRoomLifeCycles
                                = roomRelatedData.stream().filter(ix -> ix.getRoomId().equalsIgnoreCase(String.valueOf(roomId)))
                                .collect(Collectors.toList());

                        Collection<TencentCallbackLogView> roomLifeCycles = matchedRoomLifeCycles
                                .stream().filter(ii -> TencentConstants.filterRoomLifecycle(ii.getEventType()))
                                .collect(Collectors.toList());

                        RoomDocument document =
                                roomDocumentRepository.findById(roomId).orElse(null);
                        DispatchReasonType referenceType = DispatchReasonType.Normal;
                        String referenceNumber = "#exception";
                        if (document != null) {
                            referenceNumber = document.getReferenceNumber();
                            referenceType = document.getReferenceType();
                        }

                        DeskType deskType = DeskType.Normal;
                        /**
                         * 针对部署的瞬间产生的调度记录; 历史记录还是默认当作指挥调度台
                         */
                        if(document.getDeskType()!=null) {
                            deskType = document.getDeskType();
                        }

                        RoomCommunicatedGroupDTO roomCommunicatedGroupDto =
                                RoomCommunicatedGroupDTO.create(
                                        jsonProvider,
                                        deskType,
                                        String.valueOf(roomId),referenceType,referenceNumber,
                                        roomLifeCycles, roomUsers,entityStream,
                                        billPaymentRuleConfig);
                        Optional<TencentCallbackLogView> startRoomOptional =
                                roomLifeCycles.stream().filter(ii -> TencentConstants.filterStartRoom(ii.getEventType())).findFirst();
                        if (!startRoomOptional.isPresent()) {
                            throw new BadTenantException(String.format("无效房间数据(%s), 无法找到开启房间的发起人信息", roomId));
                        }

                        /**
                         * 房间信息
                         */

                        Collection<TencentCallbackLogView> enterExitRoomLogs = matchedRoomLifeCycles.stream().filter(ii ->
                                        TencentConstants.filterEnterRoom(ii.getEventType()) ||
                                                TencentConstants.filterExitRoom(ii.getEventType()))
                                .collect(Collectors.toList());

                        /**
                         * 加入房间
                         */
                        roomCommunicatedGroupDto.joinRooms(
                                startRoomOptional.get(),
                                enterExitRoomLogs,
                                jsonProvider,
                                roomUsers);

                        /**
                         * 获取音视频的时长
                         */
                        Collection<TencentCallbackLogView> audioVideoLogs = matchedRoomLifeCycles.stream().filter(ii ->
                                        TencentConstants.filterStartVideoAudioAssit(ii.getEventType()) ||
                                                TencentConstants.filterStopVideoAudioAssit(ii.getEventType()))
                                .collect(Collectors.toList());

                        roomCommunicatedGroupDto.addAudioVideoLogs(audioVideoLogs, jsonProvider);

                        return roomCommunicatedGroupDto;
                    } catch (Exception ex) {
                        Collection<String> errors = _innerExceptionLocalStore.get();
                        if (errors == null) {
                            errors = new ArrayList<>();
                        }
                        errors.add(String.format("房间(%s) 处理发生异常:%s", roomId, ex.toString()));
                    }

                    return null;
                }).filter(ii -> ii != null).collect(Collectors.toList());

        return roomCommunicatedGroups;
    }

    public static void appendNoApplyRoomUsers(
            IdWorker idWorker,
            Collection<RoomCommunicatedGroupDTO> communicatedGroups,
            Collection<RoomUserEntity> roomUsers) {
        if (CollectionUtils.isEmpty(communicatedGroups) || CollectionUtils.isEmpty(roomUsers)) {
            return;
        }

        for (RoomCommunicatedGroupDTO group : communicatedGroups) {
            /**
             * 某一个房间的人员列表
             */
            Collection<RoomUserEntity> selectedRoomUsers
                    = roomUsers.stream()
                    .filter(ii -> ii.getRoomId() != null && String.valueOf(ii.getRoomId()).equalsIgnoreCase(group.getRoomId()))
                    .collect(Collectors.toList());

            Collection<RoomUserEntity> noAnswerRoomUsers =
                    selectedRoomUsers.stream().filter(ic -> {
                        /**
                         * 主持人不参与此计算
                         */
                        if (ic.isSponsor()) {
                            return false;
                        }

                        Collection<RoomCommunicatedGroupDTO.JoinRoomUserDto> joinRoomUsers = group.getJoinRoomUsers();
                        if (!CollectionUtils.isEmpty(joinRoomUsers)) {
                            return !joinRoomUsers.stream().anyMatch(ix -> ix.getInvitedUserRecordId() == ic.getId());
                        }

                        return true;
                    }).collect(Collectors.toList());

            group.addNoAnswerRoomUsers(idWorker, noAnswerRoomUsers);
        }
    }

    public static String getCurrentProcessError() {
        Collection<String> errors = _innerExceptionLocalStore.get();
        if (CollectionUtils.isEmpty(errors)) {
            return "";
        }

        return errors.stream().collect(Collectors.joining(";"));
    }
}
