package com.wecloud.im.service.impl;

import io.geekidea.springbootplus.framework.common.exception.BusinessException;
import io.geekidea.springbootplus.framework.shiro.signature.SignUtils;

import java.util.Date;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.id.NanoId;

import com.wecloud.im.entity.ImApplication;
import com.wecloud.im.param.ClientOnlineStatusChangeDto;
import com.wecloud.im.service.ImApplicationService;
import com.wecloud.im.service.ImCallbackService;

/**
 * 回调服务实现类
 * @Author luozh
 * @Date 2022年04月22日 09:11
 * @Version 1.0
 */
@Service
public class ImCallbackServiceImpl implements ImCallbackService {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private ImApplicationService applicationService;

    /**
     * 全量消息路由
     * @Author luozh
     * @Date 2022年04月22日 09:35:24
     * @param
     * @Return
     */
    @Override
    public Boolean fullMessageRouting() {
        return null;
    }

    /**
     * 用户在线状态
     * @Author luozh
     * @Date 2022年04月22日 09:35:47
     * @param applicationId  应用id
     * @param clientId  客户端id
     * @param status 状态：0：online 上线、1：offline 离线、2：logout 登出
     * @param deviceType 设备类型
     * @param time 发生时间
     * @param clientIp 用户当前的 IP 地址及端口
     * @Return
     */
    @Override
    public Boolean clientOnlineStatusChange(Long applicationId, String clientId, Integer status,
                                            Integer deviceType, Long time, String clientIp) {

        ImApplication application = applicationService.getById(applicationId);
        if (application == null) {
            throw new BusinessException("application not exist");
        }

        String subscribeUrl = application.getOnlineStatusSubscribeUrl();
        if (StringUtils.isNotBlank(subscribeUrl)) {
            String appKey = application.getAppKey();
            String appSecret = application.getAppSecret();
            String callbackUrl = buildCallbackUrl(subscribeUrl, appKey, appSecret);

            ClientOnlineStatusChangeDto body = ClientOnlineStatusChangeDto.builder()
                    .userId(clientId)
                    .status(status)
                    .os("")
                    .time(time)
                    .clientIp(clientIp)
                    .build();

            ResponseEntity<Object> response = restTemplate.postForEntity(callbackUrl, body, Object.class);
            // 同步在线状态时需要接收服务提供应答，只要有 HTTP 应答码 200 即认为状态已经同步
            if (response.getStatusCode().equals(HttpStatus.OK)) {
                // do nothing
            } else {
                // 如果应答超时 5 秒，会再尝试推送 2 次，如果仍然失败，将不再同步此条状态。如短时间内有大面积超时，将暂停推送，1 分钟后会继续推送。
            }
        }
        return true;
    }

    /**
     * 构建回调请求
     * @Author luozh
     * @Date 2022年04月22日 10:58:42
     * @param
     * @Return
     */
    private String buildCallbackUrl(String subscribeUrl, String appKey, String appSecret) {
        // 计算 Signature (数据签名)
        String nonce = NanoId.randomNanoId();
        String date = DateUtil.formatHttpDate(new Date());
        String signature = SignUtils.buildSignature(appKey, appSecret, nonce, date);
        String finalUrl =
                subscribeUrl + "?appKey=" + appKey + "&nonce=" + nonce + "&date=" + date + "&signature=" + signature;
        return finalUrl;
    }
}
