package com.wecloud.multimeet.service.impl;

import java.util.Date;
import java.util.List;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.entity.ImConversationMembers;
import com.wecloud.im.entity.ImMultiRtcRoom;
import com.wecloud.im.entity.ImMultiRtcRoomMember;
import com.wecloud.im.enums.MultiRtcMemberStateEnum;
import com.wecloud.im.enums.MultiRtcRoomStateEnum;
import com.wecloud.im.param.AgreeToMultiMeetParam;
import com.wecloud.im.param.InviteToMultiMeetParam;
import com.wecloud.im.param.LeaveFromMultiMeetParam;
import com.wecloud.im.param.RejectToMultiMeetParam;
import com.wecloud.im.param.rtc.CreateRtcChannelResult;
import com.wecloud.im.service.ImClientService;
import com.wecloud.im.service.ImMultiRtcRoomMemberService;
import com.wecloud.im.service.ImMultiRtcRoomService;
import com.wecloud.im.ws.cache.UserStateCacheManager;
import com.wecloud.multimeet.entity.dto.RoomMemberDto;
import com.wecloud.multimeet.entity.response.MultiMeetAgreeResponse;
import com.wecloud.multimeet.entity.response.MultiMeetInviteResponse;
import com.wecloud.multimeet.entity.response.MultiMeetLeaveResponse;
import com.wecloud.multimeet.entity.response.MultiMeetRejectResponse;
import com.wecloud.multimeet.service.MultiMeetService;
import com.wecloud.multimeet.service.WsMultiMeetWrite;
import com.wecloud.utils.SnowflakeUtil;
import io.geekidea.springbootplus.framework.common.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @Author wenzhida
 * @Date 2022/3/7 18:43
 * @Description 多人音视频接口实现
 */
@Slf4j
@Service
public class MultiMeetServiceImpl implements MultiMeetService {

    @Autowired
    private WsMultiMeetWrite wsMultiMeetWrite;

    @Autowired
    private ImClientService imClientService;

    @Autowired
    private UserStateCacheManager userStateCacheManager;

    @Autowired
    private ImMultiRtcRoomService imMultiRtcRoomService;

    @Autowired
    private ImMultiRtcRoomMemberService imMultiRtcRoomMemberService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void invite(InviteToMultiMeetParam param) {
        ImClient currentClient = imClientService.getCurrentClient();
        //  判断发起方必须在线
        boolean onlineStatus = userStateCacheManager.isOnline(currentClient.getId());
        if (!onlineStatus) {
            log.info("发起方必须在线" + currentClient.getFkAppid() + currentClient.getClientId());
            throw new BusinessException("发起方必须在线");
        }
        List<RoomMemberDto> members = Lists.newArrayList();
        ImMultiRtcRoom rtcRoom = imMultiRtcRoomService.getOne(new QueryWrapper<ImMultiRtcRoom>().lambda()
                .eq(ImMultiRtcRoom::getFkAppid, currentClient.getFkAppid())
                .eq(ImMultiRtcRoom::getRoomId, param.getRoomId()));
        if (rtcRoom == null) {
            rtcRoom = new ImMultiRtcRoom();
            rtcRoom.setId(SnowflakeUtil.getId());
            rtcRoom.setFkAppid(currentClient.getFkAppid());
            rtcRoom.setRoomId(param.getRoomId());
            rtcRoom.setState(MultiRtcRoomStateEnum.CREATED.getCode());
            rtcRoom.setCreateTime(new Date());
            rtcRoom.setUpdateTime(new Date());
            imMultiRtcRoomService.save(rtcRoom);
        } else {
            List<ImMultiRtcRoomMember> rtcRoomMemberList = imMultiRtcRoomMemberService.list(
                    new QueryWrapper<ImMultiRtcRoomMember>().lambda()
                            .eq(ImMultiRtcRoomMember::getFkRtcRoomId, rtcRoom.getId())
                            .ne(ImMultiRtcRoomMember::getClientId, currentClient.getClientId())
            );
            for (ImMultiRtcRoomMember imMultiRtcRoomMember : rtcRoomMemberList) {
                RoomMemberDto roomMemberDto = new RoomMemberDto();
                roomMemberDto.setFkClientId(imMultiRtcRoomMember.getFkClientId());
                roomMemberDto.setClientId(imMultiRtcRoomMember.getClientId());
                roomMemberDto.setState(imMultiRtcRoomMember.getState());
                members.add(roomMemberDto);
            }
        }
        List<ImMultiRtcRoomMember> roomMembersToSave = Lists.newArrayList();
        for (String toClientId : param.getToClients()) {
            ImClient toClient = imClientService.getCacheImClient(currentClient.getFkAppid(), toClientId);
            if (toClient == null) {
                log.info("查无接收人信息 {}", toClientId);
                continue;
            }
            ImMultiRtcRoomMember roomMember = new ImMultiRtcRoomMember();
            roomMember.setId(SnowflakeUtil.getId());
            roomMember.setFkRtcRoomId(rtcRoom.getId());
            roomMember.setFkClientId(toClient.getId());
            roomMember.setClientId(toClient.getClientId());
            roomMember.setState(MultiRtcMemberStateEnum.CALLING.getCode());
            roomMember.setCreateTime(new Date());
            roomMember.setUpdateTime(new Date());
            roomMembersToSave.add(roomMember);

            RoomMemberDto roomMemberDto = new RoomMemberDto();
            roomMemberDto.setFkClientId(toClient.getId());
            roomMemberDto.setClientId(toClient.getClientId());
            roomMemberDto.setState(MultiRtcMemberStateEnum.CALLING.getCode());
            members.add(roomMemberDto);
        }
        imMultiRtcRoomMemberService.saveBatch(roomMembersToSave);
        for (RoomMemberDto member : members) {
            // ws向接收方发送通知
            MultiMeetInviteResponse multiMeetInviteResponse = new MultiMeetInviteResponse();
            multiMeetInviteResponse.setConversationId(param.getConversationId());
            multiMeetInviteResponse.setRoomId(param.getRoomId());
            multiMeetInviteResponse.setClientId(currentClient.getClientId());
            multiMeetInviteResponse.setTimestamp(System.currentTimeMillis());
            multiMeetInviteResponse.setMemberDtoList(members);
            wsMultiMeetWrite.invite(multiMeetInviteResponse, member.getFkClientId());

            // TODO 待开发 下发安卓和ios系统推送
        }
    }

    @Override
    public void reject(RejectToMultiMeetParam param) {
        ImClient currentClient = imClientService.getCurrentClient();
        // ws向接收方发送通知
        MultiMeetRejectResponse multiMeetRejectResponse = new MultiMeetRejectResponse();
        multiMeetRejectResponse.setConversationId(param.getConversationId());
        multiMeetRejectResponse.setRoomId(param.getRoomId());

        multiMeetRejectResponse.setClientId(currentClient.getClientId());
        multiMeetRejectResponse.setTimestamp(System.currentTimeMillis());
        ImClient receiver = imClientService.getCacheImClient(currentClient.getFkAppid(), param.getInviterClientId());
        if (receiver == null) {
            log.info("查无接收人信息 {}", param.getInviterClientId());
            throw new BusinessException("查无发起会议人信息");
        }
        wsMultiMeetWrite.reject(multiMeetRejectResponse, receiver.getId());
    }

    @Override
    public void agree(AgreeToMultiMeetParam param) {
        ImClient currentClient = imClientService.getCurrentClient();
        // ws向接收方发送通知
        MultiMeetAgreeResponse multiMeetAgreeResponse = new MultiMeetAgreeResponse();
        multiMeetAgreeResponse.setConversationId(param.getConversationId());
        multiMeetAgreeResponse.setRoomId(param.getRoomId());

        multiMeetAgreeResponse.setClientId(currentClient.getClientId());
        multiMeetAgreeResponse.setTimestamp(System.currentTimeMillis());
        ImClient receiver = imClientService.getCacheImClient(currentClient.getFkAppid(), param.getInviterClientId());
        if (receiver == null) {
            log.info("查无接收人信息 {}", param.getInviterClientId());
            throw new BusinessException("查无发起会议人信息");
        }
        wsMultiMeetWrite.agree(multiMeetAgreeResponse, receiver.getId());

    }

    @Override
    public void leave(LeaveFromMultiMeetParam param) {
        ImClient currentClient = imClientService.getCurrentClient();
        // ws向接收方发送通知
        MultiMeetLeaveResponse multiMeetLeaveResponse = new MultiMeetLeaveResponse();
        multiMeetLeaveResponse.setConversationId(param.getConversationId());
        multiMeetLeaveResponse.setRoomId(param.getRoomId());

        multiMeetLeaveResponse.setClientId(currentClient.getClientId());
        multiMeetLeaveResponse.setTimestamp(System.currentTimeMillis());
        ImClient receiver = imClientService.getCacheImClient(currentClient.getFkAppid(), param.getInviterClientId());
        if (receiver == null) {
            log.info("查无接收人信息 {}", param.getInviterClientId());
            throw new BusinessException("查无发起会议人信息");
        }
        wsMultiMeetWrite.leave(multiMeetLeaveResponse, receiver.getId());
    }

}
