# coding:utf-8
"""
Copyright (year) Beijing Volcano Engine Technology Ltd.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""

import datetime
import hashlib
import hmac
import json
from urllib.parse import quote

import requests

# 以下参数视服务不同而不同，一个服务内通常是一致的
Service = "rtc"  # 服务名称
Version = "2024-12-01"  # UpdateVoiceChat API版本
Region = "cn-north-1"
Host = "rtc.volcengineapi.com"
ContentType = "application/json"

# 请求的凭证，从IAM或者STS服务中获取
AK = "AKLTMGZmMGIxNTU4MjBlNDU2OWE0M2VmMmY2MjBlODkxNzQ"
SK = "WldJeU9XSXlNVFprWWpNd05HTmtNVGczTkdNMll6QXpNakEwTm1JM05qSQ=="
# 当使用临时凭证时，需要使用到SessionToken传入Header，并计算进SignedHeader中，请自行在header参数中添加X-Security-Token头
# SessionToken = ""


def norm_query(params):
    query = ""
    for key in sorted(params.keys()):
        if type(params[key]) == list:
            for k in params[key]:
                query = (
                        query + quote(key, safe="-_.~") + "=" + quote(k, safe="-_.~") + "&"
                )
        else:
            query = (query + quote(key, safe="-_.~") + "=" + quote(params[key], safe="-_.~") + "&")
    query = query[:-1]
    return query.replace("+", "%20")


# 第一步：准备辅助函数。
# sha256 非对称加密
def hmac_sha256(key: bytes, content: str):
    return hmac.new(key, content.encode("utf-8"), hashlib.sha256).digest()


# sha256 hash算法
def hash_sha256(content: str):
    return hashlib.sha256(content.encode("utf-8")).hexdigest()


# 第二步：签名请求函数
def request(method, date, query, header, ak, sk, action, body):
    # 第三步：创建身份证明。其中的 Service 和 Region 字段是固定的。ak 和 sk 分别代表
    # AccessKeyID 和 SecretAccessKey。同时需要初始化签名结构体。一些签名计算时需要的属性也在这里处理。
    # 初始化身份证明结构体
    credential = {
        "access_key_id": ak,
        "secret_access_key": sk,
        "service": Service,
        "region": Region,
    }
    # 初始化签名结构体
    request_param = {
        "body": body,
        "host": Host,
        "path": "/",
        "method": method,
        "content_type": ContentType,
        "date": date,
        "query": {"Action": action, "Version": Version, **query},
    }
    if body is None:
        request_param["body"] = ""
    # 第四步：接下来开始计算签名。在计算签名前，先准备好用于接收签算结果的 signResult 变量，并设置一些参数。
    # 初始化签名结果的结构体
    x_date = request_param["date"].strftime("%Y%m%dT%H%M%SZ")
    short_x_date = x_date[:8]
    x_content_sha256 = hash_sha256(request_param["body"])
    sign_result = {
        "Host": request_param["host"],
        "X-Content-Sha256": x_content_sha256,
        "X-Date": x_date,
        "Content-Type": request_param["content_type"],
    }
    # 第五步：计算 Signature 签名。
    signed_headers_str = ";".join(
        ["content-type", "host", "x-content-sha256", "x-date"]
    )
    # signed_headers_str = signed_headers_str + ";x-security-token"
    canonical_request_str = "\n".join(
        [request_param["method"].upper(),
         request_param["path"],
         norm_query(request_param["query"]),
         "\n".join(
             [
                 "content-type:" + request_param["content_type"],
                 "host:" + request_param["host"],
                 "x-content-sha256:" + x_content_sha256,
                 "x-date:" + x_date,
             ]
         ),
         "",
         signed_headers_str,
         x_content_sha256,
         ]
    )

    # 打印正规化的请求用于调试比对
    print(canonical_request_str)
    hashed_canonical_request = hash_sha256(canonical_request_str)

    # 打印hash值用于调试比对
    print(hashed_canonical_request)
    credential_scope = "/".join([short_x_date, credential["region"], credential["service"], "request"])
    string_to_sign = "\n".join(["HMAC-SHA256", x_date, credential_scope, hashed_canonical_request])

    # 打印最终计算的签名字符串用于调试比对
    print("------------------------------")
    print("string_to_sign:")
    print(string_to_sign)
    print("------------------------------")
    k_date = hmac_sha256(credential["secret_access_key"].encode("utf-8"), short_x_date)
    k_region = hmac_sha256(k_date, credential["region"])
    k_service = hmac_sha256(k_region, credential["service"])
    k_signing = hmac_sha256(k_service, "request")
    signature = hmac_sha256(k_signing, string_to_sign).hex()

    sign_result["Authorization"] = "HMAC-SHA256 Credential={}, SignedHeaders={}, Signature={}".format(
        credential["access_key_id"] + "/" + credential_scope,
        signed_headers_str,
        signature,
    )
    header = {**header, **sign_result}
    print("------------------------------")
    print(header)
    print("------------------------------")
    # header = {**header, **{"X-Security-Token": SessionToken}}
    # 第六步：将 Signature 签名写入 HTTP Header 中，并发送 HTTP 请求。
    r = requests.request(method=method,
                         url="https://{}{}".format(request_param["host"], request_param["path"]),
                         headers=header,
                         params=request_param["query"],
                         data=request_param["body"],
                         )
    return r.json()


if __name__ == "__main__":
    # response_body = request("Get", datetime.datetime.utcnow(), {}, {}, AK, SK, "ListUsers", None)
    # print(response_body)

    now = datetime.datetime.utcnow()
    # now = datetime.datetime.strptime('20201230T081805Z', '%Y%m%dT%H%M%SZ')
    # Body的格式需要配合Content-Type，API使用的类型请阅读具体的官方文档，如:json格式需要json.dumps(obj)
    # response_body = request("GET", now, {"Limit": "2"}, {}, AK, SK, "ListUsers", None)
    # print(response_body)

    # response_body = request("POST", now, {"Limit": "10"}, {}, AK, SK, "ListUsers", "UnUseParam=ASDF")
    # print(response_body)

    # UpdateVoiceChat API调用示例
    # 构造请求体
    body = {
        "AppId": "67b59a4586198401ec980bf9",  # 替换为你的AppId
        "RoomId": "Room888",
        "TaskId": "e5b1c872-3c4c-48be-8d6e-4ab80e561b6b",
        # "UserId": "User1",
        "Command": "function",
        "Message": json.dumps({
            "ToolCallID": "call_oidylcvnjcd6676oq2wn01fg",
            "Content": "下中雨"
        })
    }
    
    # 发送请求
    response_body = request(
        method="POST",
        date=now,
        query={},  # Query参数在URL中已包含Action和Version
        header={},
        ak=AK,
        sk=SK,
        action="UpdateVoiceChat",
        body=json.dumps(body)  # 将body转换为JSON字符串
    )
    print("\nUpdateVoiceChat Response:")
    print(json.dumps(response_body, indent=2, ensure_ascii=False))
    
    # # 打断智能体示例
    # interrupt_body = {
    #     "AppId": "661e****543cf",  # 替换为你的AppId
    #     "RoomId": "Room1",
    #     "UserId": "User1",
    #     "Command": "interrupt"
    # }
    
    # response_body = request(
    #     method="POST",
    #     date=now,
    #     query={},
    #     header={},
    #     ak=AK,
    #     sk=SK,
    #     action="UpdateVoiceChat",
    #     body=json.dumps(interrupt_body)
    # )
    # print("\nInterrupt Bot Response:")
    # print(json.dumps(response_body, indent=2, ensure_ascii=False))