import crypto from 'crypto';
import { logger } from '../../utils/logger';
import { VaultService } from '../../services/VaultService';
import { VaultCrypto } from '../../utils/VaultCrypto';
import db from '../../config/database';

export interface SecretSession {
  sessionId: string;
  nodeId: string;
  shopId: string;
  taskId: string;
  sessionKey: string; // 临时会话密钥 (用于解密下发的凭据)
  expiresAt: number;
}

/**
 * [CORE_SEC_03] 节点安全下发通道 (Node Secret Delivery)
 * @description 保证凭据在传输与执行过程中的安全性
 */
export class SecretDeliveryService {
  private static readonly SESSION_TTL_MS = 3600 * 1000; // 1小时有效
  private static readonly TABLE_NAME = 'cf_secret_sessions';

  /**
   * 为任务分配临时的会话密钥
   */
  static async createSession(nodeId: string, shopId: string, taskId: string): Promise<SecretSession> {
    const sessionId = `SESS-${Date.now()}`;
    const sessionKey = crypto.randomBytes(32).toString('hex');
    
    const session: SecretSession = {
      sessionId,
      nodeId,
      shopId,
      taskId,
      sessionKey,
      expiresAt: Date.now() + this.SESSION_TTL_MS
    };

    await db(this.TABLE_NAME).insert({
      session_id: session.sessionId,
      node_id: session.nodeId,
      shop_id: session.shopId,
      task_id: session.taskId,
      session_key: session.sessionKey,
      expires_at: new Date(session.expiresAt),
      created_at: new Date(),
      updated_at: new Date()
    });

    logger.info(`[SecretDelivery] Created session ${sessionId} for Node: ${nodeId}, Task: ${taskId}`);
    return session;
  }

  /**
   * 获取下发给节点的加密负载
   * @description 负载由 Hub 主密钥解密后，再由 SessionKey 加密发送给 Node
   */
  static async getDeliveryPayload(sessionId: string, credentialId: number): Promise<any> {
    logger.info(`[SecretDelivery] Preparing payload for session ${sessionId}`);

    // 1. 获取会话信息
    const session = await db(this.TABLE_NAME).where({ session_id: sessionId }).first();
    if (!session) throw new Error('Session not found');
    if (new Date(session.expires_at).getTime() < Date.now()) {
      throw new Error('Session expired');
    }

    // 2. 获取主存储中的凭据 (需租户隔离)
    const record = await VaultService.getRawRecord(session.tenant_id || 'system', credentialId);
    if (!record) throw new Error('Credential not found');

    // 3. 解密原始凭据 (MasterKey)
    const plainText = VaultCrypto.decrypt(record.encrypted_data, record.iv, record.tag);

    // 4. 使用 SessionKey 重新加密 (Re-wrap)
    const wrapped = VaultCrypto.encrypt(plainText, session.session_key);

    return {
      sessionId,
      wrappedData: wrapped.encryptedData,
      iv: wrapped.iv,
      tag: wrapped.tag,
      credentialType: record.credential_type,
      accountName: record.account_name
    };
  }

  /**
   * 吊销会话
   */
  static async revokeSession(sessionId: string): Promise<void> {
    logger.warn(`[SecretDelivery] Revoking session: ${sessionId}`);
    await db(this.TABLE_NAME).where({ session_id: sessionId }).delete();
  }

  /**
   * 清理过期会话
   */
  static async cleanupExpiredSessions(): Promise<void> {
    const deletedCount = await db(this.TABLE_NAME)
      .where('expires_at', '<', new Date())
      .delete();
    if (deletedCount > 0) {
      logger.info(`[SecretDelivery] Cleaned up ${deletedCount} expired sessions`);
    }
  }
}
