/**
 * 分享链接加密/解密工具
 * 使用 Web Crypto API 实现 JWT 风格的 HMAC-SHA256 签名
 * 包含过期时间验证，token 有效期 7 天
 */

// JWT 头部 (Base64URL)
const JWT_HEADER = btoa(JSON.stringify({ alg: 'HS256', typ: 'JWT' }))
  .replace(/=/g, '')
  .replace(/\+/g, '-')
  .replace(/\//g, '_');

// 从环境变量或配置中获取密钥，默认使用固定密钥
const SECRET_KEY = 'procurement-plan-share-key-2026';

// Token 有效期：1 天（毫秒）
const TOKEN_EXPIRY = 1 * 24 * 60 * 60 * 1000;

/**
 * 将字符串转换为 Uint8Array
 */
function stringToUint8Array(str: string): Uint8Array {
  return new TextEncoder().encode(str) as Uint8Array;
}

/**
 * 将 Uint8Array 转换为 Base64URL 字符串
 */
function arrayBufferToBase64URL(buffer: ArrayBuffer): string {
  const bytes = new Uint8Array(buffer);
  let binary = '';
  for (let i = 0; i < bytes.byteLength; i++) {
    binary += String.fromCharCode(bytes[i]);
  }
  return btoa(binary)
    .replace(/=/g, '')
    .replace(/\+/g, '-')
    .replace(/\//g, '_');
}

/**
 * 导入 HMAC 密钥
 */
async function importKey(): Promise<CryptoKey> {
  const keyData = stringToUint8Array(SECRET_KEY);
  return await crypto.subtle.importKey(
    'raw',
    keyData.buffer as ArrayBuffer,
    { name: 'HMAC', hash: 'SHA-256' },
    false,
    ['sign', 'verify']
  );
}

/**
 * 创建 HMAC-SHA256 签名
 */
async function createSignature(message: string): Promise<string> {
  const key = await importKey();
  const messageData = stringToUint8Array(message);
  const signature = await crypto.subtle.sign(
    'HMAC',
    key,
    messageData.buffer as ArrayBuffer
  );
  return arrayBufferToBase64URL(signature);
}

/**
 * 验证 HMAC-SHA256 签名
 */
async function verifySignature(message: string, signature: string): Promise<boolean> {
  try {
    const key = await importKey();
    const signatureBytes = Uint8Array.from(
      atob(signature.replace(/-/g, '+').replace(/_/g, '/'))
        .split('')
        .map(c => c.charCodeAt(0))
    );
    const messageData = stringToUint8Array(message);
    return await crypto.subtle.verify(
      'HMAC',
      key,
      signatureBytes.buffer as ArrayBuffer,
      messageData.buffer as ArrayBuffer
    );
  } catch {
    return false;
  }
}

/**
 * 加密分享链接参数（JWT 风格）
 * @param planId 计划ID
 * @param factoryType 工厂类型
 * @returns 签名后的 token 字符串
 */
export async function encryptShareParams(planId: string, factoryType: string, hideSensitive: boolean = false): Promise<string> {
  const payload = {
    planId,
    factoryType,
    hideSensitive,
    exp: Date.now() + TOKEN_EXPIRY, // 过期时间
    iat: Date.now() // 签发时间
  };

  // Base64URL 编码 payload
  const payloadBase64 = btoa(JSON.stringify(payload))
    .replace(/=/g, '')
    .replace(/\+/g, '-')
    .replace(/\//g, '_');

  // 创建签名
  const message = `${JWT_HEADER}.${payloadBase64}`;
  const signature = await createSignature(message);

  // 返回完整 JWT: header.payload.signature
  return `${message}.${signature}`;
}

/**
 * 解密分享链接参数
 * @param token JWT 格式的 token 字符串
 * @returns 解密后的 { planId, factoryType } 或 null（解密失败或已过期）
 */
export async function decryptShareParams(token: string): Promise<{ planId: string; factoryType: string; hideSensitive: boolean } | null> {
  try {
    const parts = token.split('.');
    if (parts.length !== 3) return null;

    const [header, payloadBase64, signature] = parts;

    // 验证头部
    if (header !== JWT_HEADER) return null;

    // 验证签名
    const message = `${header}.${payloadBase64}`;
    const isValid = await verifySignature(message, signature);
    if (!isValid) return null;

    // 解码 payload
    const payloadJson = atob(payloadBase64.replace(/-/g, '+').replace(/_/g, '/'));
    const payload = JSON.parse(payloadJson);

    // 验证必需字段
    if (!payload.planId || !payload.factoryType) return null;

    // 验证过期时间
    if (payload.exp && Date.now() > payload.exp) {
      console.warn('Share link has expired');
      return null;
    }

    return {
      planId: payload.planId,
      factoryType: payload.factoryType,
      hideSensitive: payload.hideSensitive || false
    };
  } catch (error) {
    console.error('Failed to decrypt share params:', error);
    return null;
  }
}

/**
 * 同步版本（用于兼容旧代码，内部使用 async）
 * 注意：实际使用时建议改用 async/await 版本
 */
export function encryptShareParamsSync(planId: string, factoryType: string, hideSensitive: boolean = false): string {
  // 生成同步 token（简化版本，无签名验证）
  const payload = {
    planId,
    factoryType,
    hideSensitive,
    exp: Date.now() + TOKEN_EXPIRY,
    iat: Date.now()
  };
  return btoa(JSON.stringify(payload))
    .replace(/=/g, '')
    .replace(/\+/g, '-')
    .replace(/\//g, '_');
}

/**
 * 同步解密（用于兼容旧代码）
 */
export function decryptShareParamsSync(token: string): { planId: string; factoryType: string; hideSensitive: boolean } | null {
  try {
    const payloadJson = atob(token.replace(/-/g, '+').replace(/_/g, '/'));
    const payload = JSON.parse(payloadJson);

    if (!payload.planId || !payload.factoryType) return null;

    // 验证过期时间
    if (payload.exp && Date.now() > payload.exp) {
      console.warn('Share link has expired');
      return null;
    }

    return {
      planId: payload.planId,
      factoryType: payload.factoryType,
      hideSensitive: payload.hideSensitive || false
    };
  } catch {
    return null;
  }
}
