import { spawn, ChildProcess } from 'child_process';
import * as path from 'path';
import * as fs from 'fs';
import { EventEmitter } from 'events';
import { GrpcClient } from './grpc-client';
import { DatabaseManager } from './database';

/**
 * TSS 协议处理结果
 */
export interface KeygenResult {
  success: boolean;
  publicKey: Buffer;
  encryptedShare: Buffer;
  partyIndex: number;
  error?: string;
}

export interface SignResult {
  success: boolean;
  signature: Buffer;
  error?: string;
}

/**
 * TSS 消息处理器接口
 */
interface TSSMessage {
  type: 'outgoing' | 'result' | 'error' | 'progress';
  isBroadcast?: boolean;
  toParties?: string[];
  payload?: string; // base64 encoded
  publicKey?: string; // base64 encoded
  encryptedShare?: string; // base64 encoded
  partyIndex?: number;
  round?: number;
  totalRounds?: number;
  error?: string;
}

/**
 * 会话参与者信息
 */
interface ParticipantInfo {
  partyId: string;
  partyIndex: number;
}

/**
 * TSS 协议处理器
 *
 * 使用子进程方式运行 Go 编写的 TSS 协议实现
 * 这种方式比 WASM 更可靠，特别是对于复杂的密码学操作
 */
export class TSSHandler extends EventEmitter {
  private tssProcess: ChildProcess | null = null;
  private grpcClient: GrpcClient;
  private database: DatabaseManager | null = null;
  private sessionId: string | null = null;
  private partyId: string | null = null;
  private partyIndex: number = -1;
  private participants: ParticipantInfo[] = [];
  private partyIndexMap: Map<string, number> = new Map();
  private isRunning = false;

  // 消息缓冲：在 TSS 进程启动前缓冲收到的消息
  private messageBuffer: Array<{
    messageId: string;
    fromParty: string;
    isBroadcast: boolean;
    payload: Buffer;
  }> = [];
  private isProcessReady = false;
  // 是否已预订阅消息（用于在 keygen 启动前就开始缓冲消息）
  private isPrepared = false;

  constructor(grpcClient: GrpcClient, database?: DatabaseManager) {
    super();
    this.grpcClient = grpcClient;
    this.database = database || null;
  }

  /**
   * 设置数据库管理器（用于消息去重）
   */
  setDatabase(database: DatabaseManager): void {
    this.database = database;
  }

  /**
   * 获取 TSS 二进制文件路径
   */
  private getTSSBinaryPath(): string {
    const platform = process.platform;
    const arch = process.arch;

    let binaryName = 'tss-party';
    if (platform === 'win32') {
      binaryName += '.exe';
    }

    // 开发环境: 在项目目录下
    const devPath = path.join(__dirname, '../../bin', `${platform}-${arch}`, binaryName);
    if (fs.existsSync(devPath)) {
      return devPath;
    }

    // 生产环境: 在 app 资源目录下
    const prodPath = path.join(process.resourcesPath, 'bin', binaryName);
    if (fs.existsSync(prodPath)) {
      return prodPath;
    }

    // 回退: 期望在 PATH 中
    return binaryName;
  }

  /**
   * 预订阅消息流 - 在 joinSession 后立即调用
   * 这确保在其他方开始发送消息时，我们已经准备好接收和缓冲
   *
   * @param sessionId 会话 ID
   * @param partyId 自己的 party ID
   */
  prepareForKeygen(sessionId: string, partyId: string): void {
    // 检查 gRPC 连接状态
    if (!this.grpcClient.isConnected()) {
      console.error('[TSS] Cannot prepare for keygen: gRPC client not connected');
      throw new Error('gRPC client not connected');
    }

    // 如果已经为同一个 session 准备过，跳过
    if (this.isPrepared && this.sessionId === sessionId) {
      console.log('[TSS] Already prepared for same session, skip');
      return;
    }

    // 如果为不同的 session 准备过，先取消旧的订阅
    if (this.isPrepared && this.sessionId !== sessionId) {
      console.log(`[TSS] Switching from session ${this.sessionId?.substring(0, 8)}... to ${sessionId.substring(0, 8)}...`);
      this.grpcClient.removeAllListeners('mpcMessage');
      this.grpcClient.unsubscribeMessages();
      this.messageBuffer = [];
    }

    console.log(`[TSS] Preparing for keygen: session=${sessionId.substring(0, 8)}..., party=${partyId.substring(0, 8)}...`);

    this.sessionId = sessionId;
    this.partyId = partyId;
    this.isPrepared = true;
    this.messageBuffer = [];

    // 立即订阅消息流，开始缓冲消息
    // 使用 bound 方法确保 this 上下文正确
    this.grpcClient.on('mpcMessage', this.handleIncomingMessage.bind(this));
    this.grpcClient.subscribeMessages(sessionId, partyId);

    console.log('[TSS] Message subscription started, buffering enabled');
  }

  /**
   * 取消预订阅
   */
  cancelPrepare(): void {
    if (!this.isPrepared) {
      return;
    }

    console.log('[TSS] Canceling prepare');
    this.isPrepared = false;
    this.messageBuffer = [];
    this.grpcClient.removeAllListeners('mpcMessage');
    this.grpcClient.unsubscribeMessages();
    this.sessionId = null;
    this.partyId = null;
  }

  /**
   * 参与 Keygen 协议
   */
  async participateKeygen(
    sessionId: string,
    partyId: string,
    partyIndex: number,
    participants: ParticipantInfo[],
    threshold: { t: number; n: number },
    encryptionPassword: string
  ): Promise<KeygenResult> {
    if (this.isRunning) {
      throw new Error('TSS protocol already running');
    }

    // 检查是否已经预订阅
    const wasPrepared = this.isPrepared && this.sessionId === sessionId;
    const bufferedCount = this.messageBuffer.length;

    console.log(`[TSS] Starting keygen: wasPrepared=${wasPrepared}, bufferedMessages=${bufferedCount}`);

    this.sessionId = sessionId;
    this.partyId = partyId;
    this.partyIndex = partyIndex;
    this.participants = participants;
    this.isRunning = true;
    this.isProcessReady = false;
    // 注意：不清空消息缓冲，保留预订阅阶段收到的消息

    // 构建 party index map
    this.partyIndexMap.clear();
    for (const p of participants) {
      this.partyIndexMap.set(p.partyId, p.partyIndex);
    }

    return new Promise((resolve, reject) => {
      try {
        const binaryPath = this.getTSSBinaryPath();
        console.log(`[TSS] Binary path: ${binaryPath}`);
        console.log(`[TSS] Binary exists: ${fs.existsSync(binaryPath)}`);

        // 构建参与者列表 JSON
        const participantsJson = JSON.stringify(participants);
        console.log(`[TSS] Participants: ${participantsJson}`);
        console.log(`[TSS] partyIndex=${partyIndex}, threshold=${threshold.t}-of-${threshold.n}`);

        // 启动 TSS 子进程
        const args = [
          'keygen',
          '--session-id', sessionId,
          '--party-id', partyId,
          '--party-index', partyIndex.toString(),
          '--threshold-t', threshold.t.toString(),
          '--threshold-n', threshold.n.toString(),
          '--participants', participantsJson,
          '--password', encryptionPassword,
        ];
        console.log(`[TSS] Spawning: ${binaryPath} ${args.join(' ')}`);

        this.tssProcess = spawn(binaryPath, args);

        let resultData = '';
        let stderrData = '';

        // 如果没有预订阅，现在订阅消息
        // 如果已经预订阅，消息监听器已经注册，不需要重复注册
        if (!wasPrepared) {
          console.log('[TSS] Subscribing to messages (not prepared before)');
          this.grpcClient.on('mpcMessage', this.handleIncomingMessage.bind(this));
          this.grpcClient.subscribeMessages(sessionId, partyId);
        } else {
          console.log(`[TSS] Using existing subscription, ${bufferedCount} messages buffered`);
        }

        // 处理标准输出 (JSON 消息)
        this.tssProcess.stdout?.on('data', (data: Buffer) => {
          const lines = data.toString().split('\n').filter(line => line.trim());

          // 收到第一条输出时，标记进程就绪并发送缓冲的消息
          if (!this.isProcessReady && this.tssProcess?.stdin) {
            this.isProcessReady = true;
            console.log(`[TSS] Process ready, flushing ${this.messageBuffer.length} buffered messages`);
            this.flushMessageBuffer();
          }

          for (const line of lines) {
            try {
              const message: TSSMessage = JSON.parse(line);
              this.handleTSSMessage(message);

              if (message.type === 'result') {
                resultData = line;
              }
            } catch {
              // 非 JSON 输出，记录日志
              console.log('[TSS]', line);
            }
          }
        });

        // 处理标准错误
        this.tssProcess.stderr?.on('data', (data: Buffer) => {
          const errorText = data.toString();
          stderrData += errorText;
          console.error('[TSS stderr]', errorText);
        });

        // 处理进程退出
        this.tssProcess.on('close', (code) => {
          const completedSessionId = this.sessionId;
          this.isRunning = false;
          this.isProcessReady = false;
          this.isPrepared = false;
          this.messageBuffer = [];
          this.tssProcess = null;
          this.sessionId = null;
          this.partyId = null;
          // 清理消息监听器和 gRPC 流订阅，防止下次 keygen 时出错
          this.grpcClient.removeAllListeners('mpcMessage');
          this.grpcClient.unsubscribeMessages();

          if (code === 0 && resultData) {
            try {
              const result: TSSMessage = JSON.parse(resultData);
              if (result.publicKey && result.encryptedShare) {
                // 成功完成后清理该会话的已处理消息记录
                if (this.database && completedSessionId) {
                  this.database.clearProcessedMessages(completedSessionId);
                }
                resolve({
                  success: true,
                  publicKey: Buffer.from(result.publicKey, 'base64'),
                  encryptedShare: Buffer.from(result.encryptedShare, 'base64'),
                  partyIndex: result.partyIndex || partyIndex,
                });
              } else {
                reject(new Error(result.error || 'Keygen failed: no result data'));
              }
            } catch (e) {
              reject(new Error(`Failed to parse keygen result: ${e}`));
            }
          } else {
            const errorMsg = stderrData.trim() || `Keygen process exited with code ${code}`;
            console.error(`[TSS] Process failed: code=${code}, stderr=${stderrData}`);
            reject(new Error(errorMsg));
          }
        });

        // 处理进程错误
        this.tssProcess.on('error', (err) => {
          this.isRunning = false;
          this.isProcessReady = false;
          this.isPrepared = false;
          this.messageBuffer = [];
          this.tssProcess = null;
          this.sessionId = null;
          this.partyId = null;
          // 清理消息监听器和 gRPC 流订阅
          this.grpcClient.removeAllListeners('mpcMessage');
          this.grpcClient.unsubscribeMessages();
          reject(err);
        });

      } catch (err) {
        this.isRunning = false;
        this.isPrepared = false;
        this.sessionId = null;
        this.partyId = null;
        reject(err);
      }
    });
  }

  /**
   * 处理 TSS 进程发出的消息
   */
  private async handleTSSMessage(message: TSSMessage): Promise<void> {
    switch (message.type) {
      case 'outgoing':
        // TSS 进程要发送消息给其他参与者
        if (message.payload && this.sessionId && this.partyId) {
          const payload = Buffer.from(message.payload, 'base64');
          const toParties = message.isBroadcast ? [] : (message.toParties || []);

          try {
            await this.grpcClient.routeMessage(
              this.sessionId,
              this.partyId,
              toParties,
              0, // round number handled by TSS lib
              payload
            );
          } catch (err) {
            console.error('Failed to route TSS message:', err);
          }
        }
        break;

      case 'progress':
        // 进度更新
        this.emit('progress', {
          round: message.round,
          totalRounds: message.totalRounds,
        });
        break;

      case 'error':
        this.emit('error', new Error(message.error));
        break;

      case 'result':
        // 结果会在 close 事件中处理
        break;
    }
  }

  /**
   * 处理从 gRPC 接收的 MPC 消息（带去重）
   *
   * 消息处理状态：
   * 1. isPrepared=true, isRunning=false: 预订阅阶段，缓冲消息
   * 2. isPrepared=true, isRunning=true, isProcessReady=false: 进程启动中，缓冲消息
   * 3. isPrepared=true, isRunning=true, isProcessReady=true: 进程就绪，直接发送
   *
   * Note: gRPC message uses snake_case field names due to keepCase: true in proto-loader
   */
  private handleIncomingMessage(rawMessage: {
    message_id: string;
    from_party: string;
    is_broadcast: boolean;
    payload: Buffer;
  }): void {
    // 转换为内部使用的 camelCase 格式
    const message = {
      messageId: rawMessage.message_id,
      fromParty: rawMessage.from_party,
      isBroadcast: rawMessage.is_broadcast,
      payload: rawMessage.payload,
    };

    // 消息去重检查
    if (this.database && message.messageId) {
      if (this.database.isMessageProcessed(message.messageId)) {
        console.log(`[TSS] Skipping duplicate message: ${message.messageId.substring(0, 8)}...`);
        return;
      }
    }

    // 如果进程就绪，直接发送
    if (this.isProcessReady && this.tssProcess?.stdin) {
      this.sendMessageToProcess(message);
      return;
    }

    // 如果已预订阅或正在运行，缓冲消息
    // 这确保在任何阶段收到的消息都不会丢失
    if (this.isPrepared || this.isRunning) {
      console.log(`[TSS] Buffering message from ${message.fromParty.substring(0, 8)}... (prepared=${this.isPrepared}, running=${this.isRunning}, ready=${this.isProcessReady})`);
      this.messageBuffer.push(message);
      return;
    }

    // 既没预订阅也没运行，忽略消息
    console.log(`[TSS] Ignoring message from ${message.fromParty.substring(0, 8)}... (not prepared)`);
  }

  /**
   * 发送消息给 TSS 进程（并标记为已处理）
   */
  private sendMessageToProcess(message: {
    messageId: string;
    fromParty: string;
    isBroadcast: boolean;
    payload: Buffer;
  }): void {
    if (!this.tssProcess?.stdin) {
      return;
    }

    const fromIndex = this.partyIndexMap.get(message.fromParty);
    if (fromIndex === undefined) {
      console.warn('Received message from unknown party:', message.fromParty);
      return;
    }

    // 发送消息给 TSS 进程
    const inputMessage = JSON.stringify({
      type: 'incoming',
      fromPartyIndex: fromIndex,
      isBroadcast: message.isBroadcast,
      payload: message.payload.toString('base64'),
    });

    this.tssProcess.stdin.write(inputMessage + '\n');

    // 标记消息为已处理（防止重连后重复处理）
    if (this.database && message.messageId && this.sessionId) {
      this.database.markMessageProcessed(message.messageId, this.sessionId);
    }
  }

  /**
   * 发送缓冲的消息
   */
  private flushMessageBuffer(): void {
    if (this.messageBuffer.length === 0) {
      return;
    }

    console.log(`[TSS] Flushing ${this.messageBuffer.length} buffered messages`);
    for (const msg of this.messageBuffer) {
      this.sendMessageToProcess(msg);
    }
    this.messageBuffer = [];
  }

  // ===========================================================================
  // Co-Sign 相关方法 - 与 Keygen 完全隔离的签名功能
  // ===========================================================================

  /**
   * 预订阅签名消息流 - 在 joinSession 后立即调用
   * 与 prepareForKeygen 类似，确保在其他方开始发送消息时已准备好接收和缓冲
   *
   * @param sessionId 签名会话 ID
   * @param partyId 自己的 party ID
   */
  prepareForSign(sessionId: string, partyId: string): void {
    // 检查 gRPC 连接状态
    if (!this.grpcClient.isConnected()) {
      console.error('[TSS-SIGN] Cannot prepare for sign: gRPC client not connected');
      throw new Error('gRPC client not connected');
    }

    // 如果已经为同一个 session 准备过，跳过
    if (this.isPrepared && this.sessionId === sessionId) {
      console.log('[TSS-SIGN] Already prepared for same session, skip');
      return;
    }

    // 如果为不同的 session 准备过，先取消旧的订阅
    if (this.isPrepared && this.sessionId !== sessionId) {
      console.log(`[TSS-SIGN] Switching from session ${this.sessionId?.substring(0, 8)}... to ${sessionId.substring(0, 8)}...`);
      this.grpcClient.removeAllListeners('mpcMessage');
      this.grpcClient.unsubscribeMessages();
      this.messageBuffer = [];
    }

    console.log(`[TSS-SIGN] Preparing for sign: session=${sessionId.substring(0, 8)}..., party=${partyId.substring(0, 8)}...`);

    this.sessionId = sessionId;
    this.partyId = partyId;
    this.isPrepared = true;
    this.messageBuffer = [];

    // 立即订阅消息流，开始缓冲消息
    this.grpcClient.on('mpcMessage', this.handleIncomingMessage.bind(this));
    this.grpcClient.subscribeMessages(sessionId, partyId);

    console.log('[TSS-SIGN] Message subscription started, buffering enabled');
  }

  /**
   * 取消签名预订阅
   */
  cancelSignPrepare(): void {
    if (!this.isPrepared) {
      return;
    }

    console.log('[TSS-SIGN] Canceling sign prepare');
    this.isPrepared = false;
    this.messageBuffer = [];
    this.grpcClient.removeAllListeners('mpcMessage');
    this.grpcClient.unsubscribeMessages();
    this.sessionId = null;
    this.partyId = null;
  }

  /**
   * 参与 Co-Sign 协议
   *
   * @param sessionId 签名会话 ID
   * @param partyId 自己的 party ID
   * @param partyIndex 自己在签名参与方中的索引
   * @param participants 签名参与方列表 (T 个参与方)
   * @param threshold 阈值配置 { t: 签名阈值, n: keygen时的总参与方数 }
   * @param messageHash 待签名的消息哈希 (hex 编码)
   * @param shareData 本地 share 数据 (base64 编码的加密数据)
   * @param sharePassword share 解密密码
   */
  async participateSign(
    sessionId: string,
    partyId: string,
    partyIndex: number,
    participants: ParticipantInfo[],
    threshold: { t: number; n: number },
    messageHash: string,
    shareData: string,
    sharePassword: string
  ): Promise<SignResult> {
    if (this.isRunning) {
      throw new Error('TSS protocol already running');
    }

    // 检查是否已经预订阅
    const wasPrepared = this.isPrepared && this.sessionId === sessionId;
    const bufferedCount = this.messageBuffer.length;

    console.log(`[TSS-SIGN] Starting sign: wasPrepared=${wasPrepared}, bufferedMessages=${bufferedCount}`);

    this.sessionId = sessionId;
    this.partyId = partyId;
    this.partyIndex = partyIndex;
    this.participants = participants;
    this.isRunning = true;
    this.isProcessReady = false;
    // 注意：不清空消息缓冲，保留预订阅阶段收到的消息

    // 构建 party index map
    this.partyIndexMap.clear();
    for (const p of participants) {
      this.partyIndexMap.set(p.partyId, p.partyIndex);
    }

    return new Promise((resolve, reject) => {
      try {
        const binaryPath = this.getTSSBinaryPath();
        console.log(`[TSS-SIGN] Binary path: ${binaryPath}`);
        console.log(`[TSS-SIGN] Binary exists: ${fs.existsSync(binaryPath)}`);

        // 构建参与者列表 JSON
        const participantsJson = JSON.stringify(participants);
        console.log(`[TSS-SIGN] Participants: ${participantsJson}`);
        console.log(`[TSS-SIGN] partyIndex=${partyIndex}, threshold=${threshold.t}-of-${threshold.n}`);
        console.log(`[TSS-SIGN] messageHash=${messageHash.substring(0, 16)}...`);

        // 启动 TSS 子进程 - sign 命令
        const args = [
          'sign',
          '--session-id', sessionId,
          '--party-id', partyId,
          '--party-index', partyIndex.toString(),
          '--threshold-t', threshold.t.toString(),
          '--threshold-n', threshold.n.toString(),
          '--participants', participantsJson,
          '--message-hash', messageHash,
          '--share-data', shareData,
          '--password', sharePassword,
        ];
        console.log(`[TSS-SIGN] Spawning: ${binaryPath} sign ...`);

        this.tssProcess = spawn(binaryPath, args);

        let resultData = '';
        let stderrData = '';

        // 如果没有预订阅，现在订阅消息
        if (!wasPrepared) {
          console.log('[TSS-SIGN] Subscribing to messages (not prepared before)');
          this.grpcClient.on('mpcMessage', this.handleIncomingMessage.bind(this));
          this.grpcClient.subscribeMessages(sessionId, partyId);
        } else {
          console.log(`[TSS-SIGN] Using existing subscription, ${bufferedCount} messages buffered`);
        }

        // 处理标准输出 (JSON 消息)
        this.tssProcess.stdout?.on('data', (data: Buffer) => {
          const lines = data.toString().split('\n').filter(line => line.trim());

          // 收到第一条输出时，标记进程就绪并发送缓冲的消息
          if (!this.isProcessReady && this.tssProcess?.stdin) {
            this.isProcessReady = true;
            console.log(`[TSS-SIGN] Process ready, flushing ${this.messageBuffer.length} buffered messages`);
            this.flushMessageBuffer();
          }

          for (const line of lines) {
            try {
              const message: TSSMessage = JSON.parse(line);
              this.handleTSSMessage(message);

              if (message.type === 'result') {
                resultData = line;
              }
            } catch {
              // 非 JSON 输出，记录日志
              console.log('[TSS-SIGN]', line);
            }
          }
        });

        // 处理标准错误
        this.tssProcess.stderr?.on('data', (data: Buffer) => {
          const errorText = data.toString();
          stderrData += errorText;
          console.error('[TSS-SIGN stderr]', errorText);
        });

        // 处理进程退出
        this.tssProcess.on('close', (code) => {
          const completedSessionId = this.sessionId;
          this.isRunning = false;
          this.isProcessReady = false;
          this.isPrepared = false;
          this.messageBuffer = [];
          this.tssProcess = null;
          this.sessionId = null;
          this.partyId = null;
          // 清理消息监听器和 gRPC 流订阅
          this.grpcClient.removeAllListeners('mpcMessage');
          this.grpcClient.unsubscribeMessages();

          if (code === 0 && resultData) {
            try {
              const result: TSSMessage = JSON.parse(resultData);
              if (result.payload) {
                // 成功完成后清理该会话的已处理消息记录
                if (this.database && completedSessionId) {
                  this.database.clearProcessedMessages(completedSessionId);
                }
                resolve({
                  success: true,
                  signature: Buffer.from(result.payload, 'base64'),
                });
              } else {
                reject(new Error(result.error || 'Sign failed: no result data'));
              }
            } catch (e) {
              reject(new Error(`Failed to parse sign result: ${e}`));
            }
          } else {
            const errorMsg = stderrData.trim() || `Sign process exited with code ${code}`;
            console.error(`[TSS-SIGN] Process failed: code=${code}, stderr=${stderrData}`);
            reject(new Error(errorMsg));
          }
        });

        // 处理进程错误
        this.tssProcess.on('error', (err) => {
          this.isRunning = false;
          this.isProcessReady = false;
          this.isPrepared = false;
          this.messageBuffer = [];
          this.tssProcess = null;
          this.sessionId = null;
          this.partyId = null;
          // 清理消息监听器和 gRPC 流订阅
          this.grpcClient.removeAllListeners('mpcMessage');
          this.grpcClient.unsubscribeMessages();
          reject(err);
        });

      } catch (err) {
        this.isRunning = false;
        this.isPrepared = false;
        this.sessionId = null;
        this.partyId = null;
        reject(err);
      }
    });
  }

  /**
   * 取消正在进行的协议
   */
  cancel(): void {
    if (this.tssProcess) {
      this.tssProcess.kill('SIGTERM');
      this.tssProcess = null;
    }
    this.isRunning = false;
    this.isProcessReady = false;
    this.isPrepared = false;
    this.messageBuffer = [];
    this.sessionId = null;
    this.partyId = null;
    // 清理消息监听器和 gRPC 流订阅
    this.grpcClient.removeAllListeners('mpcMessage');
    this.grpcClient.unsubscribeMessages();
  }

  /**
   * 检查是否正在运行
   */
  getIsRunning(): boolean {
    return this.isRunning;
  }

  /**
   * 检查是否已预订阅
   */
  getIsPrepared(): boolean {
    return this.isPrepared;
  }
}

/**
 * 模拟 TSS Handler
 *
 * 用于开发和测试，不需要实际的 TSS 二进制文件
 * 模拟 keygen 过程并生成假的密钥数据
 */
export class MockTSSHandler extends EventEmitter {
  private grpcClient: GrpcClient;
  private isRunning = false;

  constructor(grpcClient: GrpcClient) {
    super();
    this.grpcClient = grpcClient;
  }

  async participateKeygen(
    sessionId: string,
    partyId: string,
    partyIndex: number,
    participants: ParticipantInfo[],
    threshold: { t: number; n: number },
    encryptionPassword: string
  ): Promise<KeygenResult> {
    if (this.isRunning) {
      throw new Error('TSS protocol already running');
    }

    this.isRunning = true;

    // 模拟 keygen 过程
    const totalRounds = 4;

    for (let round = 1; round <= totalRounds; round++) {
      // 每轮等待 1-2 秒
      await new Promise(resolve => setTimeout(resolve, 1000 + Math.random() * 1000));

      this.emit('progress', {
        round,
        totalRounds,
      });
    }

    this.isRunning = false;

    // 生成模拟的密钥数据
    const mockPublicKey = Buffer.alloc(33);
    mockPublicKey[0] = 0x02; // compressed public key prefix
    for (let i = 1; i < 33; i++) {
      mockPublicKey[i] = Math.floor(Math.random() * 256);
    }

    const mockShareData = Buffer.from(JSON.stringify({
      sessionId,
      partyId,
      partyIndex,
      threshold,
      participants: participants.map(p => ({ partyId: p.partyId, partyIndex: p.partyIndex })),
      createdAt: new Date().toISOString(),
      // 实际的 share 数据会更复杂
      shareSecret: Buffer.alloc(32).fill(partyIndex).toString('hex'),
    }));

    // 简单的 "加密" (实际应该使用 AES-256-GCM)
    const encryptedShare = Buffer.concat([
      Buffer.from('MOCK_ENCRYPTED:'),
      mockShareData,
    ]);

    return {
      success: true,
      publicKey: mockPublicKey,
      encryptedShare,
      partyIndex,
    };
  }

  cancel(): void {
    this.isRunning = false;
  }

  getIsRunning(): boolean {
    return this.isRunning;
  }
}
