#!/usr/bin/env python3
"""TC3-signed JSON request. Python standard library only; no automatic retries.
Usage: python3 tencent-api.py mps CreateAigcImageTask request.json
Set TENCENT_SECRET_ID and TENCENT_SECRET_KEY in the environment.
"""
import argparse
import datetime
import hashlib
import hmac
import json
import os
import sys
import time
import urllib.error
import urllib.request

SERVICES = {
    "mps": ("mps.intl.tencentcloudapi.com", "2019-06-12"),
    "vod": ("vod.intl.tencentcloudapi.com", "2018-07-17"),
}

def signed_request(service, action, payload, secret_id, secret_key, region, timestamp=None):
    host, version = SERVICES[service]
    timestamp = int(time.time()) if timestamp is None else timestamp
    date = datetime.datetime.fromtimestamp(timestamp, datetime.timezone.utc).strftime("%Y-%m-%d")
    body = json.dumps(payload, ensure_ascii=False, separators=(",", ":")).encode("utf-8")
    sha256 = lambda value: hashlib.sha256(value).hexdigest()
    content_type = "application/json; charset=utf-8"
    signed_headers = "content-type;host;x-tc-action"
    headers = f"content-type:{content_type}\nhost:{host}\nx-tc-action:{action.lower()}\n"
    canonical = "POST\n/\n\n" + headers + "\n" + signed_headers + "\n" + sha256(body)
    scope = f"{date}/{service}/tc3_request"
    string_to_sign = f"TC3-HMAC-SHA256\n{timestamp}\n{scope}\n{sha256(canonical.encode())}"
    sign = lambda key, value: hmac.new(key, value.encode(), hashlib.sha256).digest()
    key = sign(sign(sign(("TC3" + secret_key).encode(), date), service), "tc3_request")
    signature = hmac.new(key, string_to_sign.encode(), hashlib.sha256).hexdigest()
    authorization = f"TC3-HMAC-SHA256 Credential={secret_id}/{scope}, SignedHeaders={signed_headers}, Signature={signature}"
    result = {"Content-Type": content_type, "Host": host, "X-TC-Action": action,
              "X-TC-Version": version, "X-TC-Timestamp": str(timestamp),
              "X-TC-Region": region, "Authorization": authorization}
    if os.environ.get("TENCENT_TOKEN"):
        result["X-TC-Token"] = os.environ["TENCENT_TOKEN"]
    return urllib.request.Request(f"https://{host}/", data=body, headers=result, method="POST")

def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("service", choices=SERVICES)
    parser.add_argument("action")
    parser.add_argument("json_file", help="Request JSON file, or - for standard input")
    parser.add_argument("--region", default=os.environ.get("TENCENT_REGION", "ap-singapore"))
    args = parser.parse_args()
    sid, key = os.environ.get("TENCENT_SECRET_ID"), os.environ.get("TENCENT_SECRET_KEY")
    if not sid or not key:
        parser.error("Set TENCENT_SECRET_ID and TENCENT_SECRET_KEY in your environment.")
    try:
        if args.json_file == "-":
            payload = json.load(sys.stdin)
        else:
            with open(args.json_file, encoding="utf-8") as source:
                payload = json.load(source)
        if not isinstance(payload, dict):
            parser.error("The request JSON must be an object.")
        request = signed_request(args.service, args.action, payload, sid, key, args.region)
        with urllib.request.urlopen(request, timeout=60) as response:
            data = json.load(response)
        print(json.dumps(data, ensure_ascii=False, indent=2))
        return 1 if data.get("Response", {}).get("Error") else 0
    except urllib.error.HTTPError as error:
        print(f"HTTP {error.code}: {error.read().decode('utf-8', errors='replace')}", file=sys.stderr)
    except (OSError, ValueError, urllib.error.URLError) as error:
        print(str(error), file=sys.stderr)
    return 1

if __name__ == "__main__":
    sys.exit(main())
