import crypto from 'crypto';
import { config } from '../config/index.js';

const ALGORITHM = 'aes-256-gcm';
const IV_LENGTH = 16;
const TAG_LENGTH = 16;

/**
 * Cookie 加密管理
 */
export class CookieManager {
  private static key: Buffer = crypto.scryptSync(
    config.encryption.key,
    'salt',
    32
  );
  
  /**
   * 加密 Cookie
   */
  static encrypt(cookies: string): string {
    const iv = crypto.randomBytes(IV_LENGTH);
    const cipher = crypto.createCipheriv(ALGORITHM, this.key, iv);
    
    let encrypted = cipher.update(cookies, 'utf8', 'hex');
    encrypted += cipher.final('hex');
    
    const tag = cipher.getAuthTag();
    
    // 格式: iv:tag:encrypted
    return `${iv.toString('hex')}:${tag.toString('hex')}:${encrypted}`;
  }
  
  /**
   * 解密 Cookie
   */
  static decrypt(encryptedCookies: string): string {
    const [ivHex, tagHex, encrypted] = encryptedCookies.split(':');
    
    if (!ivHex || !tagHex || !encrypted) {
      throw new Error('Invalid encrypted cookie format');
    }
    
    const iv = Buffer.from(ivHex, 'hex');
    const tag = Buffer.from(tagHex, 'hex');
    
    const decipher = crypto.createDecipheriv(ALGORITHM, this.key, iv);
    decipher.setAuthTag(tag);
    
    let decrypted = decipher.update(encrypted, 'hex', 'utf8');
    decrypted += decipher.final('utf8');
    
    return decrypted;
  }
  
  /**
   * 解析 Cookie 字符串为对象数组
   */
  static parseCookieString(cookieString: string, domain: string): Array<{
    name: string;
    value: string;
    domain: string;
    path: string;
  }> {
    return cookieString.split(';').map(cookie => {
      const [name, ...valueParts] = cookie.trim().split('=');
      return {
        name: name.trim(),
        value: valueParts.join('=').trim(),
        domain,
        path: '/',
      };
    }).filter(c => c.name && c.value);
  }
  
  /**
   * 检查 Cookie 是否过期
   */
  static isExpired(cookies: string): boolean {
    try {
      const cookieList = JSON.parse(cookies);
      const now = Date.now() / 1000;
      
      // 检查是否有关键 cookie 已过期
      return cookieList.some((cookie: { expires?: number }) => 
        cookie.expires && cookie.expires < now
      );
    } catch {
      return true;
    }
  }
  
  /**
   * 获取 Cookie 过期时间
   */
  static getExpireTime(cookies: string): Date | null {
    try {
      const cookieList = JSON.parse(cookies);
      let minExpires = Infinity;
      
      for (const cookie of cookieList) {
        if (cookie.expires && cookie.expires < minExpires) {
          minExpires = cookie.expires;
        }
      }
      
      if (minExpires === Infinity) {
        return null;
      }
      
      return new Date(minExpires * 1000);
    } catch {
      return null;
    }
  }
}
