import * as crypto from 'crypto';

export interface TencentCloudSignOptions {
  secretId: string;
  secretKey: string;
  service: string;
  host: string;
  region?: string;
  action: string;
  version: string;
  payload?: any;
  timestamp?: number;
}

/**
 * 腾讯云 API 签名 v3
 * 文档：https://cloud.tencent.com/document/api/213/30654
 */
export class TencentCloudSigner {
  private static readonly ALGORITHM = 'TC3-HMAC-SHA256';
  private static readonly SIGNED_HEADERS = 'content-type;host;x-tc-action';

  /**
   * 生成签名和请求头
   */
  static sign(options: TencentCloudSignOptions): Record<string, string> {
    const timestamp = options.timestamp || Math.floor(Date.now() / 1000);
    const date = new Date(timestamp * 1000)
      .toISOString()
      .substr(0, 10);

    // 1. 拼接规范请求串
    const payload = options.payload ? JSON.stringify(options.payload) : '';
    const hashedRequestPayload = this.sha256Hex(payload);
    const canonicalRequest = [
      'POST',
      '/',
      '',
      `content-type:application/json`,
      `host:${options.host}`,
      `x-tc-action:${options.action.toLowerCase()}`,
      '',
      this.SIGNED_HEADERS,
      hashedRequestPayload,
    ].join('\n');

    // 2. 拼接待签名字符串
    const hashedCanonicalRequest = this.sha256Hex(canonicalRequest);
    const credentialScope = `${date}/${options.service}/tc3_request`;
    const stringToSign = [
      this.ALGORITHM,
      timestamp.toString(),
      credentialScope,
      hashedCanonicalRequest,
    ].join('\n');

    // 3. 计算签名
    const secretDate = this.hmacSha256(
      `TC3${options.secretKey}`,
      date,
    );
    const secretService = this.hmacSha256(secretDate, options.service);
    const secretSigning = this.hmacSha256(secretService, 'tc3_request');
    const signature = this.hmacSha256Hex(secretSigning, stringToSign);

    // 4. 拼接 Authorization
    const authorization = `${this.ALGORITHM} Credential=${options.secretId}/${credentialScope}, SignedHeaders=${this.SIGNED_HEADERS}, Signature=${signature}`;

    // 5. 返回请求头
    return {
      'Content-Type': 'application/json',
      'Host': options.host,
      'X-TC-Action': options.action,
      'X-TC-Version': options.version,
      'X-TC-Timestamp': timestamp.toString(),
      'X-TC-Region': options.region || 'ap-guangzhou',
      'Authorization': authorization,
    };
  }

  /**
   * SHA256 哈希（十六进制）
   */
  private static sha256Hex(data: string): string {
    return crypto.createHash('sha256').update(data, 'utf8').digest('hex');
  }

  /**
   * HMAC-SHA256（Buffer）
   */
  private static hmacSha256(key: string | Buffer, data: string): Buffer {
    return crypto.createHmac('sha256', key).update(data, 'utf8').digest();
  }

  /**
   * HMAC-SHA256（十六进制）
   */
  private static hmacSha256Hex(key: Buffer, data: string): string {
    return crypto.createHmac('sha256', key).update(data, 'utf8').digest('hex');
  }
}
