package cn.reghao.bnt.web.admin.service.notifier.ding;

import cn.reghao.bnt.web.admin.model.po.Webhook;
import cn.reghao.bnt.web.admin.db.repository.WebhookRepository;
import cn.reghao.bnt.web.admin.service.notifier.Notify;
import cn.reghao.jutil.jdk.http.WebRequest;
import cn.reghao.jutil.jdk.http.WebResponse;
import cn.reghao.jutil.jdk.serializer.JsonConverter;
import com.google.gson.JsonObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

/**
 * 钉钉通知
 *
 * @author reghao
 * @date 2020-05-07 01:31:03
 */
@Slf4j
@Service
public class DingNotify implements Notify<DingMsg> {
    private final WebRequest webRequest;
    private final WebhookRepository webhookRepository;

    public DingNotify(WebRequest webRequest, WebhookRepository webhookRepository) {
        this.webRequest = webRequest;
        this.webhookRepository = webhookRepository;
    }

    @Override
    public void send(String receiver, DingMsg msg) throws Exception {
        Webhook webhook = webhookRepository.findByUrl(receiver);
        if (webhook == null) {
            log.info("没有可用于发送通知的 webhook 配置");
            return;
        }

        String url = webhook.getUrl();
        String sign = webhook.getSign();
        if (sign != null) {
            url = getReceiver(url, sign);
        }

        WebResponse webResponse = webRequest.postJson(url, JsonConverter.objectToJson(msg));
        if (webResponse.getStatusCode() != 200) {
            throw new Exception(webResponse.getBody());
        }

        JsonObject jsonObject = JsonConverter.jsonToJsonElement(webResponse.getBody()).getAsJsonObject();
        int errcode = jsonObject.get("errcode").getAsInt();
        if (errcode != 0) {
            String errmsg = jsonObject.get("errmsg").getAsString();
            throw new Exception(errmsg);
        }
    }

    private String getReceiver(String url, String secret) throws InvalidKeyException, NoSuchAlgorithmException {
        long timestamp = System.currentTimeMillis();
        String sign = calcSign(timestamp, secret);
        return url + String.format("&timestamp=%s&sign=%s", timestamp, sign);
    }

    /**
     * 钉钉机器人计算签名
     *
     * @param
     * @return
     * @date 2021-06-24 下午3:47
     */
    private String calcSign(long timestamp, String secret) throws NoSuchAlgorithmException, InvalidKeyException {
        String stringToSign = timestamp + System.lineSeparator() + secret;
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
        byte[] signData = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
        return URLEncoder.encode(new String(Base64.getEncoder().encode(signData)), StandardCharsets.UTF_8);
    }
}
