package com.zcloud.zcGbsServicer.service;

import cn.hutool.core.util.StrUtil;
import com.alibaba.cola.exception.BizException;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriUtils;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Component
@RequiredArgsConstructor
@SuppressWarnings("unchecked")
public class HstVideoPlatformClient {

    private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    private final HstVideoPlatformProperties properties;

    public String generateToken() {
        validateConfig();
        long timestamp = System.currentTimeMillis();
        String headerJson = "{\"alg\":\"" + StrUtil.blankToDefault(properties.getAlgorithm(), "SHA256") + "\"}";
        String payloadJson = "{\"key\":\"" + properties.getAuthKey() + "\",\"timestamp\":" + timestamp + "}";
        String header = Base64.getEncoder().encodeToString(headerJson.getBytes(StandardCharsets.UTF_8));
        String payload = Base64.getEncoder().encodeToString(payloadJson.getBytes(StandardCharsets.UTF_8));
        String signature = sha256Hex(header + payload + properties.getAuthSecret());
        return header + "." + payload + "." + signature;
    }

    public String formatExpireTime() {
        return TIME_FORMATTER.format(LocalDateTime.now().plusMinutes(10));
    }

    public Map<String, Object> createInstant(Map<String, Object> body) {
        return post("/api/v1/room/createInstant", body);
    }

    public Map<String, Object> authUser(Map<String, Object> body) {
        return post("/api/v1/room/authUser", body);
    }

    public Map<String, Object> authRoom(Map<String, Object> body) {
        return post("/api/v1/room/authRoom", body);
    }

    public Map<String, Object> addRoomInfo(Map<String, Object> body) {
        return post("/api/v1/room/addRoomInfo", body);
    }

    public Map<String, Object> onlineRoom(Map<String, Object> body) {
        return post("/api/v1/room/onlineRoom", body);
    }

    public Map<String, Object> departmentList(Map<String, Object> body) {
        return post("/api/v1/department/list", body);
    }

    public Map<String, Object> userList(Map<String, Object> body) {
        return post("/api/v1/user/list", body);
    }

    public Map<String, Object> addUser(Map<String, Object> body) {
        return post("/api/v1/user/add", body);
    }

    public Map<String, Object> deleteUser(Map<String, Object> body) {
        return post("/api/v1/user/del", body);
    }

    public Map<String, Object> participant(Map<String, Object> body) {
        return post("/api/v1/room/participant", body);
    }

    public Map<String, Object> roomLog(Map<String, Object> body) {
        return post("/api/v1/room/roomLog", body);
    }

    public Map<String, Object> userInRoom(Map<String, Object> body) {
        return post("/api/v1/room/userInRoom", body);
    }

    public List<Map<String, Object>> userOnline(String userName) {
        if (StrUtil.isBlank(userName)) {
            return Collections.emptyList();
        }
        Map<String, Object> response = get("/api/v1/user/online/"
                + UriUtils.encodePathSegment(userName.trim(), StandardCharsets.UTF_8));
        ensureSuccess(response, "获取用户在线状态");
        Object data = response.get("data");
        if (!(data instanceof List)) {
            return Collections.emptyList();
        }
        return (List<Map<String, Object>>) data;
    }

    public Map<String, Object> loginAddr() {
        return get("/api/v1/room/loginAddr");
    }

    public void ensureSuccess(Map<String, Object> response, String actionName) {
        String code = response == null ? null : asText(response.get("code"));
        if (StrUtil.isBlank(code) || "0".equals(code) || "200".equals(code)) {
            return;
        }
        String msg = response == null ? null : asText(response.get("msg"));
        throw new BizException(actionName + "失败" + (StrUtil.isBlank(msg) ? "" : "：" + msg));
    }

    private Map<String, Object> post(String path, Map<String, Object> body) {
        return request(path, HttpMethod.POST, body == null ? Collections.emptyMap() : body);
    }

    private Map<String, Object> get(String path) {
        return request(path, HttpMethod.GET, null);
    }

    private Map<String, Object> request(String path, HttpMethod method, Object body) {
        validateConfig();
        RestTemplate restTemplate = createRestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("Authorization", generateToken());
        HttpEntity<?> requestEntity = new HttpEntity<>(body, headers);
        try {
            ResponseEntity<Map> response = restTemplate.exchange(buildUrl(path), method, requestEntity, Map.class);
            return response.getBody() == null ? new LinkedHashMap<>() : response.getBody();
        }
        catch (HttpStatusCodeException ex) {
            throw new BizException("调用视频平台失败：" + ex.getResponseBodyAsString());
        }
        catch (Exception ex) {
            throw new BizException("调用视频平台失败：" + ex.getMessage());
        }
    }

    private RestTemplate createRestTemplate() {
        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
        requestFactory.setConnectTimeout(properties.getConnectTimeoutMs() == null ? 10000 : properties.getConnectTimeoutMs());
        requestFactory.setReadTimeout(properties.getReadTimeoutMs() == null ? 15000 : properties.getReadTimeoutMs());
        return new RestTemplate(requestFactory);
    }

    private String buildUrl(String path) {
        String baseUrl = StrUtil.blankToDefault(properties.getApiBaseUrl(), properties.getWebBaseUrl());
        if (StrUtil.isBlank(baseUrl)) {
            throw new BizException("视频平台地址未配置");
        }
        return StrUtil.removeSuffix(baseUrl.trim(), "/") + path;
    }

    private void validateConfig() {
        if (StrUtil.isBlank(properties.getAuthKey())) {
            throw new BizException("视频平台 HTTP API key 未配置");
        }
        if (StrUtil.isBlank(properties.getAuthSecret())) {
            throw new BizException("视频平台 HTTP API secret 未配置");
        }
    }

    private String sha256Hex(String source) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] bytes = digest.digest(source.getBytes(StandardCharsets.UTF_8));
            StringBuilder builder = new StringBuilder();
            for (byte item : bytes) {
                String hex = Integer.toHexString(item & 0xFF);
                if (hex.length() == 1) {
                    builder.append('0');
                }
                builder.append(hex);
            }
            return builder.toString();
        }
        catch (Exception ex) {
            throw new BizException("生成视频平台令牌失败：" + ex.getMessage());
        }
    }

    private String asText(Object value) {
        return value == null ? null : String.valueOf(value);
    }
}
