package com.ruoyi.cai.ws.job;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.cai.domain.UserCall;
import com.ruoyi.cai.service.UserCallService;
import com.ruoyi.yunxin.data.ImDataRes;
import com.ruoyi.yunxin.data.ImMsgGen;
import com.ruoyi.cai.ws.bean.Room;
import com.ruoyi.cai.ws.bean.UserData;
import com.ruoyi.cai.ws.cache.RoomCtxCache;
import com.ruoyi.cai.ws.constant.HangUpEnums;
import com.ruoyi.cai.ws.constant.RoomStatusEnums;
import com.ruoyi.cai.ws.dto.WsR;
import com.ruoyi.cai.ws.dto.WsRMsgGen;
import com.ruoyi.cai.ws.service.RoomService;
import com.ruoyi.cai.ws.service.SettleResp;
import com.ruoyi.cai.ws.service.SettleService;
import com.ruoyi.cai.ws.util.RoomWebSocketUtil;
import com.ruoyi.yunxin.Yunxin;
import com.ruoyi.yunxin.enums.CallNoticeEnum;
import com.ruoyi.yunxin.service.YunxinWsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class RoomCheckJobService {

    @Autowired
    private RoomService roomService;
    @Autowired
    private UserCallService userCallService;
    @Autowired
    private Yunxin yunxin;
    @Autowired
    private SettleService settleService;
    @Autowired
    private RoomCtxCache roomCtxCache;

    public JobResp checkRoom(Long roomId){
        Room room = roomService.load(roomId);
        if(room == null){
            return JobResp.builder().nextCreateJob(false).build();
        }
        // 检查是否三分钟没有接听
        JobResp resp = this.checkRoomCallerTimeOut(room);
        if(!resp.isNextCreateJob()){
            return resp;
        }
        // 检查心跳
        JobResp heartbeat = checkRoomHeartbeat(room);
        if(!heartbeat.isNextCreateJob()){
            return heartbeat;
        }
        this.checkCanCallTime(room);
        // 尝试结算一下
        SettleResp settleResp = settleService.processOn(roomId);
        return JobResp.builder().nextCreateJob(settleResp.isNextRun()).build();
    }


    private void checkCanCallTime(Room room){
        Long time = roomService.canCallTime(room);
        if(time < 150 && time > 60){ // 提示余额不足
            String sessionKey = roomCtxCache.getSessionKeyCallerByRoomId(room.getRoomId());
            RoomWebSocketUtil.sendSendMessage(sessionKey,  WsRMsgGen.rechargeNotice("您的余额不足，点此充值"));
        }
    }

    private JobResp checkRoomHeartbeat(Room room){
        if(!room.isCanCall()){
            return JobResp.builder().nextCreateJob(true).build();
        }
        Long roomId = room.getRoomId();
        UserData callUserData = room.getCallUserData();
        UserData receiverUserData = room.getReceiverUserData();
        boolean timeOut = false;
        WsR hangup = null;
        if(isHeartTimeout(callUserData)){
            timeOut = true;
            hangup = WsRMsgGen.hangup("呼叫方连接中断", roomId, HangUpEnums.FROM.getCode());
        }else if(isHeartTimeout(receiverUserData)){
            timeOut = true;
            hangup = WsRMsgGen.hangup("接听方连接中断", roomId, HangUpEnums.TO.getCode());
        }
        if(timeOut){
            boolean nextCreateJob = false;
            if(roomService.hangUp(roomId)){
                userCallService.update(Wrappers.lambdaUpdate(UserCall.class)
                        .eq(UserCall::getId,roomId)
                        .set(UserCall::getStatus, RoomStatusEnums.STATUS_TIMEOUT_CANCEL.getCode()));
                SettleResp settleResp = settleService.processOn(roomId);
                nextCreateJob = settleResp.isNextRun();
            }
            List<String> keys = roomCtxCache.getSessionKeysByRoomId(roomId);
            RoomWebSocketUtil.sendSendMessage(keys,  hangup);
            roomService.closeAllFd(roomId);
            return JobResp.builder().nextCreateJob(nextCreateJob).build();
        }
        return JobResp.builder().nextCreateJob(true).build();
    }


    // 检测是不是3分钟没有接听
    private JobResp checkRoomCallerTimeOut(Room room){
        if(RoomStatusEnums.STATUS_CALLER_CONNECT.getCode().equals(room.getStatus())
                && RoomStatusEnums.STATUS_RECEIVER_CONNECT.getCode().equals(room.getStatus())) {
            return JobResp.builder().nextCreateJob(true).build();
        }
        UserData callUserData = room.getCallUserData();
        UserData receiverUserData = room.getReceiverUserData();
        Long connectTimeCaller = callUserData.getConnectTime();
        Long connectTimeReceiver = receiverUserData.getConnectTime();
        boolean timeOut = false;
        if(connectTimeCaller != null && DateUtil.currentSeconds() - connectTimeCaller > 180){
            timeOut = true;
        }else if(connectTimeReceiver != null && DateUtil.currentSeconds() - connectTimeReceiver > 180){
            timeOut = true;
        }
        if(timeOut){
            Long roomId = room.getRoomId();
            boolean nextCreateJob = false;
            if(roomService.hangUp(roomId)){
                userCallService.update(Wrappers.lambdaUpdate(UserCall.class)
                        .eq(UserCall::getId,roomId)
                        .set(UserCall::getStatus, RoomStatusEnums.STATUS_TIMEOUT_CANCEL.getCode()));
                SettleResp settleResp = settleService.processOn(roomId);
                nextCreateJob = settleResp.isNextRun();
            }
            roomService.closeAllFd(roomId);
            yunxinWsService.sendToCallNotifyAsync(callUserData.getId(),receiverUserData.getId(), CallNoticeEnum.TIMEOUT,0L);
            return JobResp.builder().nextCreateJob(nextCreateJob).build();
        }
        return JobResp.builder().nextCreateJob(true).build();
    }

    @Autowired
    private YunxinWsService yunxinWsService;


    /**
     * 是否心跳超时
     * @param userData
     * @return
     */
    private boolean isHeartTimeout(UserData userData){
        if(userData.getConnectTime() == null){
            return false;
        }
        if(DateUtil.currentSeconds() - userData.getHeartTime() < 117){
            return false;
        }
        return true;
    }





}
