package cn.sikey.tools.service.hisi;

import cn.sikey.framework.common.exception.ServiceException;
import cn.sikey.tools.controller.app.hisi.vo.AssistedPositioningReqVO;
import cn.sikey.tools.util.HisiUtils;
import cn.sikey.tools.util.OkHttpUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Response;
import okhttp3.ResponseBody;
import org.apache.http.HttpStatus;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.Base64;
import java.util.TreeMap;

/**
 * @Author: qin
 * @Date: 2025/3/25
 * @Description: 辅助定位
 */
@Service
@Slf4j
public class HisiServiceImpl implements HisiService {

    @Value("${hisi.appId}")
    private String appId;

    @Value("${hisi.appSecret}")
    private String appSecret;

    @Value("${hisi.url}")
    private String url;

    @Resource
    private OkHttpUtil okHttpUtil;

    private static final String HMAC_SHA256 = "HmacSHA256";

    private static final String HIGEO_V1_XGNSS_AGNSS = "/higeo/v1/xgnss/agnss";

    /**
     * 辅助定位
     *
     * @param assistedPositioning 参数
     * @param response            返回数据
     * @return
     */
    @Override
    public void agnss(AssistedPositioningReqVO assistedPositioning, HttpServletResponse response) throws Exception {
        log.info("[辅助定位]参数：{}", assistedPositioning);
        String signature = generateAgnssSignature(assistedPositioning);
        String header = "HMAC-SHA256 appid=" + appId + "," + "timestamp=" + assistedPositioning.getTimestamp() + "," + "signature=" + signature;

        InputStream inputStream;
        try {
            Response res = okHttpUtil.get(assistedPositioning.getDeviceId(), url + HIGEO_V1_XGNSS_AGNSS, paramsMap(assistedPositioning), header);
            int status = res.code();
            String message = res.message();
            ResponseBody body = res.body();
            if (!res.isSuccessful() || status != HttpStatus.SC_OK || body == null) {
                response.sendError(status, message);
                log.warn("[辅助定位]获取结果失败: {}", res);
                return;
            }

            // 设置响应头
            // response.setContentType("application/octet-stream");

            // 返回数据
            long totalBytes = 0;
            inputStream = body.byteStream();
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                response.getOutputStream().write(buffer, 0, bytesRead);
                totalBytes += bytesRead;
            }
            log.info("[辅助定位]设备端接收数据完成，大小: {}", totalBytes);
        } catch (IOException e) {
            log.error("[辅助定位]失败：{0}", e);
            response.sendError(HttpStatus.SC_INTERNAL_SERVER_ERROR, "辅助定位失败");
        }
    }

    /**
     * 参数
     *
     * @param assistedPositioning
     * @return
     */
    private TreeMap<String, Object> paramsMap(AssistedPositioningReqVO assistedPositioning) {
        TreeMap<String, Object> paramsMap = new TreeMap<>();
        paramsMap.put("constellation", assistedPositioning.getConstellation());
        paramsMap.put("datatype", assistedPositioning.getDatatype());
        return paramsMap;
    }

    /**
     * agnss
     *
     * @param assistedPositioning
     * @return
     */
    private String generateAgnssSignature(AssistedPositioningReqVO assistedPositioning) {
        // 构造规范化请求参数
        TreeMap<String, Object> paramsMap = paramsMap(assistedPositioning);

        long timestamp = Instant.now().toEpochMilli();
        assistedPositioning.setTimestamp(timestamp);

        // 构建待签名字符串
        // HTTP 方法
        String stringToSign = "GET" + "&" +
                // 规范化URI（需URL编码）
                HIGEO_V1_XGNSS_AGNSS + "&" +
                // 规范化查询字符串
                HisiUtils.toQueryString(paramsMap) + "&&" +
                // 其他固定参数
                "appid=" + appId + "&timestamp=" + timestamp;
        return generateSignature(stringToSign);
    }

    private String generateSignature(String query) {
        try {
            SecretKeySpec signingKey = new SecretKeySpec(appSecret.getBytes(StandardCharsets.UTF_8), HMAC_SHA256);
            Mac mac = Mac.getInstance(HMAC_SHA256);
            mac.init(signingKey);
            byte[] rawHmac = mac.doFinal(query.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(rawHmac);
        } catch (Exception e) {
            throw new ServiceException(HttpStatus.SC_INTERNAL_SERVER_ERROR, "签名生成失败");
        }
    }

}
