package com.wecloud.im.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.entity.ImRtcRecord;
import com.wecloud.im.mapper.ImRtcRecordMapper;
import com.wecloud.im.param.rtc.CreateRtcChannelParam;
import com.wecloud.im.param.rtc.SingleRtcRecordParam;
import com.wecloud.im.sdk.enums.RtcStateEnum;
import com.wecloud.im.sdk.enums.SingleRtcOperateTypeEnum;
import com.wecloud.im.service.ImClientService;
import com.wecloud.im.service.ImRtcRecordService;
import com.wecloud.im.vo.MissedRtcRecordVO;
import com.wecloud.utils.SnowflakeUtil;
import io.geekidea.springbootplus.framework.common.exception.BusinessException;
import io.geekidea.springbootplus.framework.common.service.impl.BaseServiceImpl;
import io.geekidea.springbootplus.framework.shiro.util.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;


/**
 * @Author Future
 * @Date 2022/5/22 23:50
 * @Description 单人音视频记录服务实现
 */
@Slf4j
@Service
public class ImRtcRecordServiceImpl extends BaseServiceImpl<ImRtcRecordMapper, ImRtcRecord> implements ImRtcRecordService {

    @Autowired
    private ImClientService imClientService;

    @Async
    @Override
    public void createRtcRecord(CreateRtcChannelParam param, Long channelId, ImClient currentClient) {
        try {
            ImRtcRecord rtcRecord = new ImRtcRecord();
            rtcRecord.setId(SnowflakeUtil.getId());
            rtcRecord.setFkAppid(currentClient.getFkAppid());
            rtcRecord.setChannelId(channelId);
            rtcRecord.setFromClientId(currentClient.getClientId());
            rtcRecord.setToClientId(param.getToClient());
            rtcRecord.setCallType(param.getCallType());
            rtcRecord.setState(RtcStateEnum.CREATED.getCode());
            rtcRecord.setCreateTime(new Date());
            this.save(rtcRecord);
        } catch (Exception e) {
            log.info("创建rtc通话记录异常 param {} channelId {} 异常 ", JSON.toJSONString(param), channelId, e);
        }
    }

    /**
     * 更新音视频记录
     *
     * @param channelId
     * @param type      1-同意进入频道  2-拒接进入频道  3-主动挂断(离开频道)
     */
    @Async
    @Override
    public void updateRtcRecord(Long channelId, Integer type) {
        try {
            ImRtcRecord rtcRecord = this.getOne(new QueryWrapper<ImRtcRecord>().lambda()
                    .eq(ImRtcRecord::getChannelId, channelId));
            if (rtcRecord == null) {
                return;
            }
            if (SingleRtcOperateTypeEnum.JOIN.getCode().equals(type)) {
                // 同意进入频道
                rtcRecord.setState(RtcStateEnum.ING.getCode());
                rtcRecord.setStartTime(new Date());
            } else if (SingleRtcOperateTypeEnum.REJECT.getCode().equals(type)) {
                // 拒接进入频道
                rtcRecord.setState(RtcStateEnum.END.getCode());
            } else if (SingleRtcOperateTypeEnum.LEAVE.getCode().equals(type)) {
                // 主动挂断(离开频道)
                rtcRecord.setState(RtcStateEnum.END.getCode());
                rtcRecord.setEndTime(new Date());
            } else if (SingleRtcOperateTypeEnum.ABNORMAL_DISCONNECT.getCode().equals(type)) {
                // 异常原因（客户端已不在线）
                rtcRecord.setState(RtcStateEnum.END.getCode());
                rtcRecord.setEndTime(new Date());
            }
            this.updateById(rtcRecord);
        } catch (Exception e) {
            log.info("更新rtc通话记录异常, channelId {}, type {} 异常 ", channelId, type, e);
        }
    }

    @Override
    public Page<ImRtcRecord> getPageImRtcRecords(SingleRtcRecordParam param) {
        if (param.getPageNum() == null) {
            throw new BusinessException("页码不可为空");
        }
        if (param.getPageSize() == null) {
            throw new BusinessException("每页数量不可为空");
        }
        Long appId = SecurityUtils.getCurrentAppId();
        LambdaQueryWrapper<ImRtcRecord> rtcRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
        rtcRecordLambdaQueryWrapper.eq(ImRtcRecord::getFkAppid, appId);
        rtcRecordLambdaQueryWrapper.eq(param.getFromClientId() != null, ImRtcRecord::getFromClientId, param.getFromClientId());
        rtcRecordLambdaQueryWrapper.eq(param.getToClientId() != null, ImRtcRecord::getToClientId, param.getToClientId());
        rtcRecordLambdaQueryWrapper.eq(param.getChannelId() != null, ImRtcRecord::getChannelId, param.getChannelId());
        rtcRecordLambdaQueryWrapper.eq(param.getCallType() != null, ImRtcRecord::getCallType, param.getCallType());
        rtcRecordLambdaQueryWrapper.lt(param.getCreateTimeEnd() != null, ImRtcRecord::getCreateTime, param.getCreateTimeEnd());
        rtcRecordLambdaQueryWrapper.gt(param.getCreateTimeStart() != null, ImRtcRecord::getCreateTime, param.getCreateTimeStart());
        rtcRecordLambdaQueryWrapper.orderByDesc(ImRtcRecord::getCreateTime);
        Page<ImRtcRecord> pageParam = new Page<>(param.getPageNum(), param.getPageSize());
        Page<ImRtcRecord> page = this.page(pageParam, rtcRecordLambdaQueryWrapper);
        return page;
    }

    @Override
    public MissedRtcRecordVO getMissedRtcRecord(String userId) {
        ImClient currentClient = imClientService.getCacheImClient(SecurityUtils.getCurrentAppId(), userId);
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - 1);
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        ImRtcRecord missRtcRecord = this.getOne(new LambdaQueryWrapper<ImRtcRecord>()
                .eq(ImRtcRecord::getFkAppid, currentClient.getFkAppid())
                .in(ImRtcRecord::getState, Lists.newArrayList(RtcStateEnum.CREATED.getCode(), RtcStateEnum.ING.getCode()))
                .eq(ImRtcRecord::getToClientId, currentClient.getClientId())
                .between(ImRtcRecord::getCreateTime, df.format(calendar.getTime()), df.format(new Date()))
        );
        if (missRtcRecord != null) {
            MissedRtcRecordVO missedRtcRecordVo = new MissedRtcRecordVO();
            missedRtcRecordVo.setState(missRtcRecord.getState());
            missedRtcRecordVo.setCallType(missRtcRecord.getCallType());
            missedRtcRecordVo.setFromClientId(missRtcRecord.getFromClientId());
            missedRtcRecordVo.setChannelId(missRtcRecord.getChannelId());
            return missedRtcRecordVo;
        } else {
            return null;
        }
    }

}
