/**
 * Pacifica签名器实现
 *
 * 使用@noble/ed25519库实现Ed25519签名，满足<50ms性能要求
 */

import * as ed25519 from '@noble/ed25519';
import { sha512 } from '@noble/hashes/sha512';
import { Platform, SignResult, CredentialManagerError, ErrorType } from '@/core/types';

// 设置ed25519所需的哈希函数
ed25519.etc.sha512Sync = (...m) => sha512(ed25519.etc.concatBytes(...m));

// ============================================================================
// Pacifica特定类型
// ============================================================================

export enum PacificaOrderType {
  MARKET = 'market',
  LIMIT = 'limit',
  STOP_LOSS = 'stop_loss',
  TAKE_PROFIT = 'take_profit',
  CANCEL = 'cancel',
  CANCEL_ALL = 'cancel_all',
}

export interface PacificaSignRequest {
  accountId: string;
  message: Uint8Array;
  orderType: PacificaOrderType;
  options?: PacificaSignOptions;
}

export interface PacificaSignOptions {
  timeout?: number;
  includeTimestamp?: boolean;
  encoding?: 'base64' | 'base58' | 'hex';
  enableBatchOptimization?: boolean;
}

export interface PacificaSignResponse {
  success: boolean;
  signature: string;
  algorithm: string;
  timestamp: Date;
  executionTime?: number;
  error?: string;
  publicKey: string;
  orderType: PacificaOrderType;
}

export interface PacificaVerifyRequest {
  accountId: string;
  message: Uint8Array;
  signature: string;
  publicKey: string;
  orderType?: PacificaOrderType;
}

export interface PacificaVerifyResponse {
  success: boolean;
  algorithm: 'ed25519';
  publicKey: string;
  isValid?: boolean;
  timestamp?: Date;
  verificationId?: string;
  error?: string;
}

export interface PacificaOrderMessage {
  order_type: PacificaOrderType;
  symbol: string;
  side: 'buy' | 'sell';
  size: string;
  price?: string;
  client_order_id?: string;
  client_id?: string; // 为了兼容契约测试
  expiry?: number; // 为了兼容契约测试
  timestamp?: number;
}

export interface PacificaCancelMessage {
  action: 'cancel' | 'cancel_all';
  order_type?: string; // 为了兼容契约测试
  symbol?: string;
  client_order_id?: string;
  order_id?: string;
  timestamp?: number;
}

// ============================================================================
// 常量定义
// ============================================================================

export const PACIFICA_CONSTANTS = {
  PRIVATE_KEY_LENGTH: 32,
  PUBLIC_KEY_LENGTH: 32,
  SIGNATURE_LENGTH: 64,
  PRIVATE_KEY_HEX_LENGTH: 64,
  PUBLIC_KEY_BASE58_LENGTH: 44,
  SIGNATURE_BASE64_LENGTH: 88,
  MAX_MESSAGE_SIZE: 1024 * 1024, // 1MB
  DEFAULT_SIGN_TIMEOUT: 30000,
  MAX_BATCH_SIZE: 100,
} as const;

// ============================================================================
// 错误类型
// ============================================================================

export enum PacificaErrorCode {
  INVALID_PRIVATE_KEY = 'INVALID_PRIVATE_KEY',
  INVALID_PUBLIC_KEY = 'INVALID_PUBLIC_KEY',
  INVALID_MESSAGE = 'INVALID_MESSAGE',
  SIGNATURE_FAILED = 'SIGNATURE_FAILED',
  VERIFICATION_FAILED = 'VERIFICATION_FAILED',
  ACCOUNT_NOT_FOUND = 'ACCOUNT_NOT_FOUND',
  TIMEOUT = 'TIMEOUT',
  BATCH_SIZE_EXCEEDED = 'BATCH_SIZE_EXCEEDED',
  MESSAGE_TOO_LARGE = 'MESSAGE_TOO_LARGE',
}

export class PacificaSignerError extends Error {
  constructor(
    message: string,
    public readonly code: PacificaErrorCode,
    public readonly details?: any
  ) {
    super(message);
    this.name = 'PacificaSignerError';
  }
}

// ============================================================================
// 接口定义
// ============================================================================

export interface IPacificaSigner {
  readonly platform: Platform.PACIFICA;
  signOrder(request: PacificaSignRequest): Promise<PacificaSignResponse>;
  verifySignature(request: PacificaVerifyRequest): Promise<PacificaVerifyResponse>;
  getPublicKey(accountId: string): Promise<string>;
  signBatch(requests: PacificaSignRequest[]): Promise<PacificaSignResponse[]>;
}

// ============================================================================
// Pacifica签名器实现
// ============================================================================

export class PacificaSigner implements IPacificaSigner {
  public readonly platform = Platform.PACIFICA;
  private accountCredentials = new Map<string, string>(); // accountId -> privateKey
  private publicKeyCache = new Map<string, string>(); // accountId -> publicKey

  /**
   * 添加账户凭证
   */
  public addAccount(accountId: string, privateKey: string): void {
    this.validatePrivateKey(privateKey);
    this.accountCredentials.set(accountId, privateKey);
    // 清除公钥缓存，强制重新生成
    this.publicKeyCache.delete(accountId);
  }

  /**
   * 移除账户
   */
  public removeAccount(accountId: string): void {
    this.accountCredentials.delete(accountId);
    this.publicKeyCache.delete(accountId);
  }

  /**
   * 签名订单
   */
  public async signOrder(request: PacificaSignRequest): Promise<PacificaSignResponse> {
    const startTime = Date.now();

    try {
      // 验证请求
      this.validateSignRequest(request);

      // 获取私钥
      const privateKey = this.getAccountPrivateKey(request.accountId);

      // 设置默认选项
      const options = {
        timeout: PACIFICA_CONSTANTS.DEFAULT_SIGN_TIMEOUT,
        includeTimestamp: true,
        encoding: 'base64' as const,
        ...request.options,
      };

      // 检查超时
      const timeoutPromise = new Promise<never>((_, reject) => {
        setTimeout(() => {
          reject(new PacificaSignerError(
            `Signing timeout after ${options.timeout}ms`,
            PacificaErrorCode.TIMEOUT,
            { accountId: request.accountId, timeout: options.timeout }
          ));
        }, options.timeout);
      });

      // 执行签名
      const signPromise = this.performSigning(request.message, privateKey, options.encoding);

      const { signature, publicKey } = await Promise.race([signPromise, timeoutPromise]);

      const signTime = Date.now() - startTime;

      // 验证性能要求
      if (signTime >= 50) {
        console.warn(`Pacifica signing took ${signTime}ms, exceeding 50ms requirement`);
      }

      return {
        success: true,
        signature,
        algorithm: 'ed25519',
        publicKey,
        orderType: request.orderType,
        timestamp: new Date(),
        executionTime: signTime,
      };

    } catch (error) {
      const signTime = Date.now() - startTime;

      if (error instanceof PacificaSignerError) {
        return {
          success: false,
          signature: '',
          algorithm: 'ed25519',
          publicKey: '',
          orderType: request.orderType,
          timestamp: new Date(),
          error: error.message,
        };
      }

      return {
        success: false,
        signature: '',
        algorithm: 'ed25519',
        publicKey: '',
        orderType: request.orderType,
        timestamp: new Date(),
        error: `Unexpected error: ${(error as Error).message}`,
      };
    }
  }

  /**
   * 验证签名
   */
  public async verifySignature(request: PacificaVerifyRequest): Promise<PacificaVerifyResponse> {
    try {
      // 验证请求
      if (!request.message || !request.signature || !request.publicKey) {
        throw new PacificaSignerError(
          'Missing required fields for verification',
          PacificaErrorCode.VERIFICATION_FAILED,
          request
        );
      }

      // 解码签名
      const signatureBytes = this.decodeSignature(request.signature);
      const publicKeyBytes = this.decodePublicKey(request.publicKey);

      // 执行验证
      const isValid = await ed25519.verify(signatureBytes, request.message, publicKeyBytes);

      return {
        success: isValid,
        algorithm: 'ed25519',
        publicKey: request.publicKey,
        isValid,
        timestamp: new Date(),
        verificationId: `verify_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
      };

    } catch (error) {
      return {
        success: false,
        algorithm: 'ed25519',
        publicKey: request.publicKey,
        isValid: false,
        timestamp: new Date(),
        error: `Verification failed: ${(error as Error).message}`,
      };
    }
  }

  /**
   * 获取公钥
   */
  public async getPublicKey(accountId: string): Promise<string> {
    // 检查缓存
    const cached = this.publicKeyCache.get(accountId);
    if (cached) {
      return cached;
    }

    // 获取私钥并生成公钥
    const privateKey = this.getAccountPrivateKey(accountId);
    const privateKeyBytes = this.hexToBytes(privateKey);
    const publicKeyBytes = await ed25519.getPublicKey(privateKeyBytes);
    const publicKeyBase58 = this.bytesToBase58(publicKeyBytes);

    // 缓存公钥
    this.publicKeyCache.set(accountId, publicKeyBase58);

    return publicKeyBase58;
  }

  /**
   * 批量签名
   */
  public async signBatch(requests: PacificaSignRequest[]): Promise<PacificaSignResponse[]> {
    // 验证批量大小
    if (requests.length > PACIFICA_CONSTANTS.MAX_BATCH_SIZE) {
      throw new PacificaSignerError(
        `Batch size ${requests.length} exceeds maximum ${PACIFICA_CONSTANTS.MAX_BATCH_SIZE}`,
        PacificaErrorCode.BATCH_SIZE_EXCEEDED,
        { requestCount: requests.length, maxSize: PACIFICA_CONSTANTS.MAX_BATCH_SIZE }
      );
    }

    // 并行执行签名
    const signPromises = requests.map(request => this.signOrder(request));
    return Promise.all(signPromises);
  }

  // ============================================================================
  // 私有方法
  // ============================================================================

  /**
   * 验证签名请求
   */
  private validateSignRequest(request: PacificaSignRequest): void {
    if (!request.accountId || typeof request.accountId !== 'string') {
      throw new PacificaSignerError(
        'Invalid account ID',
        PacificaErrorCode.ACCOUNT_NOT_FOUND,
        { accountId: request.accountId }
      );
    }

    if (!request.message || !(request.message instanceof Uint8Array)) {
      throw new PacificaSignerError(
        'Invalid message: must be Uint8Array',
        PacificaErrorCode.INVALID_MESSAGE,
        { message: request.message }
      );
    }

    if (request.message.length > PACIFICA_CONSTANTS.MAX_MESSAGE_SIZE) {
      throw new PacificaSignerError(
        `Message too large: ${request.message.length} bytes > ${PACIFICA_CONSTANTS.MAX_MESSAGE_SIZE}`,
        PacificaErrorCode.MESSAGE_TOO_LARGE,
        { messageSize: request.message.length }
      );
    }

    if (!Object.values(PacificaOrderType).includes(request.orderType)) {
      throw new PacificaSignerError(
        `Invalid order type: ${request.orderType}`,
        PacificaErrorCode.INVALID_MESSAGE,
        { orderType: request.orderType }
      );
    }
  }

  /**
   * 验证私钥格式
   */
  private validatePrivateKey(privateKey: string): void {
    if (!privateKey || typeof privateKey !== 'string') {
      throw new PacificaSignerError(
        'Private key must be a string',
        PacificaErrorCode.INVALID_PRIVATE_KEY,
        { privateKey }
      );
    }

    if (!/^[0-9a-fA-F]{64}$/.test(privateKey)) {
      throw new PacificaSignerError(
        'Private key must be 64 character hexadecimal string',
        PacificaErrorCode.INVALID_PRIVATE_KEY,
        { privateKey: privateKey.substring(0, 10) + '...' }
      );
    }
  }

  /**
   * 获取账户私钥
   */
  private getAccountPrivateKey(accountId: string): string {
    const privateKey = this.accountCredentials.get(accountId);
    if (!privateKey) {
      throw new PacificaSignerError(
        `Account not found: ${accountId}`,
        PacificaErrorCode.ACCOUNT_NOT_FOUND,
        { accountId }
      );
    }
    return privateKey;
  }

  /**
   * 执行实际签名操作
   */
  private async performSigning(
    message: Uint8Array,
    privateKey: string,
    encoding: 'base64' | 'base58' | 'hex'
  ): Promise<{ signature: string; publicKey: string }> {
    try {
      const privateKeyBytes = this.hexToBytes(privateKey);
      const signatureBytes = await ed25519.sign(message, privateKeyBytes);
      const publicKeyBytes = await ed25519.getPublicKey(privateKeyBytes);

      const signature = this.encodeSignature(signatureBytes, encoding);
      const publicKey = this.bytesToBase58(publicKeyBytes);

      return { signature, publicKey };

    } catch (error) {
      throw new PacificaSignerError(
        `Signing failed: ${(error as Error).message}`,
        PacificaErrorCode.SIGNATURE_FAILED,
        { error: (error as Error).message }
      );
    }
  }

  /**
   * 工具方法：十六进制转字节数组
   */
  private hexToBytes(hex: string): Uint8Array {
    const bytes = new Uint8Array(hex.length / 2);
    for (let i = 0; i < hex.length; i += 2) {
      bytes[i / 2] = parseInt(hex.substr(i, 2), 16);
    }
    return bytes;
  }

  /**
   * 工具方法：字节数组转Base58（简化版本）
   */
  private bytesToBase58(bytes: Uint8Array): string {
    // 简化的Base58编码（实际项目中应使用专业库）
    return Buffer.from(bytes).toString('base64').replace(/[+=]/g, '').substring(0, 44);
  }

  /**
   * 工具方法：编码签名
   */
  private encodeSignature(signature: Uint8Array, encoding: 'base64' | 'base58' | 'hex'): string {
    switch (encoding) {
      case 'base64':
        return Buffer.from(signature).toString('base64');
      case 'hex':
        return Buffer.from(signature).toString('hex');
      case 'base58':
        return this.bytesToBase58(signature);
      default:
        return Buffer.from(signature).toString('base64');
    }
  }

  /**
   * 工具方法：解码签名
   */
  private decodeSignature(signature: string): Uint8Array {
    // 自动检测格式并解码
    if (signature.startsWith('0x')) {
      return new Uint8Array(Buffer.from(signature.substring(2), 'hex'));
    } else if (/^[0-9a-fA-F]+$/.test(signature)) {
      return new Uint8Array(Buffer.from(signature, 'hex'));
    } else {
      return new Uint8Array(Buffer.from(signature, 'base64'));
    }
  }

  /**
   * 工具方法：解码公钥
   */
  private decodePublicKey(publicKey: string): Uint8Array {
    // 简化的Base58解码
    return new Uint8Array(Buffer.from(publicKey + '==', 'base64').slice(0, 32));
  }
}