/**
 * Pacifica密钥工具类
 *
 * 提供Ed25519密钥对生成、验证、转换等工具函数
 * 确保与Pacifica平台兼容的密钥格式
 */

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

// 设置 ed25519 库需要的 SHA512 函数
ed25519.utils.sha512Sync = (...m) => sha512(ed25519.utils.concatBytes(...m));

/**
 * 密钥对接口
 */
export interface KeyPair {
  privateKey: string;
  publicKey: string;
  publicKeyBytes: Uint8Array;
  address: string;
}

/**
 * 密钥验证结果
 */
export interface KeyValidationResult {
  valid: boolean;
  errors: string[];
  keyInfo?: {
    privateKeyLength: number;
    publicKeyLength: number;
    keyFormat: string;
  } | undefined;
}

/**
 * Pacifica密钥工具类
 */
export class PacificaKeyUtils {
  private static readonly PRIVATE_KEY_LENGTH = 32; // 32 bytes for Ed25519
  private static readonly PUBLIC_KEY_LENGTH = 32; // 32 bytes for Ed25519
  private static readonly HEX_PRIVATE_KEY_LENGTH = 64; // 64 hex characters
  private static readonly HEX_PUBLIC_KEY_LENGTH = 64; // 64 hex characters

  /**
   * 生成新的Ed25519密钥对
   */
  public static async generateKeyPair(): Promise<KeyPair> {
    try {
      // 生成32字节的随机私钥
      const privateKeyBytes = ed25519.utils.randomPrivateKey();
      const privateKey = this.bytesToHex(privateKeyBytes);

      // 计算对应的公钥
      const publicKeyBytes = await ed25519.getPublicKey(privateKeyBytes);
      const publicKey = this.bytesToHex(publicKeyBytes);

      // 生成Pacifica地址
      const address = this.generateAddress(publicKeyBytes);

      return {
        privateKey,
        publicKey,
        publicKeyBytes,
        address,
      };

    } catch (error) {
      throw new CredentialManagerError(
        `Failed to generate Ed25519 key pair: ${(error as Error).message}`,
        ErrorType.KEY_GENERATION_ERROR
      );
    }
  }

  /**
   * 从私钥导出完整的密钥对
   */
  public static async deriveKeyPair(privateKey: string): Promise<KeyPair> {
    try {
      // 验证私钥格式
      const validationResult = this.validatePrivateKey(privateKey);
      if (!validationResult.valid) {
        throw new Error(`Invalid private key: ${validationResult.errors.join(', ')}`);
      }

      // 转换私钥为字节数组
      const privateKeyBytes = this.hexToBytes(privateKey);

      // 计算公钥
      const publicKeyBytes = await ed25519.getPublicKey(privateKeyBytes);
      const publicKey = this.bytesToHex(publicKeyBytes);

      // 生成地址
      const address = this.generateAddress(publicKeyBytes);

      return {
        privateKey: privateKey.toLowerCase(),
        publicKey,
        publicKeyBytes,
        address,
      };

    } catch (error) {
      throw new CredentialManagerError(
        `Failed to derive key pair from private key: ${(error as Error).message}`,
        ErrorType.KEY_DERIVATION_ERROR,
        { privateKey: privateKey.substring(0, 8) + '...' }
      );
    }
  }

  /**
   * 验证私钥格式
   */
  public static validatePrivateKey(privateKey: string): KeyValidationResult {
    const errors: string[] = [];

    // 检查是否为字符串
    if (typeof privateKey !== 'string') {
      errors.push('Private key must be a string');
      return { valid: false, errors };
    }

    // 移除可能的0x前缀
    const cleanKey = privateKey.startsWith('0x') ? privateKey.slice(2) : privateKey;

    // 检查长度
    if (cleanKey.length !== this.HEX_PRIVATE_KEY_LENGTH) {
      errors.push(`Private key must be ${this.HEX_PRIVATE_KEY_LENGTH} hex characters, got ${cleanKey.length}`);
    }

    // 检查是否为有效的十六进制
    if (!/^[0-9a-fA-F]*$/.test(cleanKey)) {
      errors.push('Private key must contain only hexadecimal characters');
    }

    // 检查是否为全零（无效的私钥）
    if (/^0+$/.test(cleanKey)) {
      errors.push('Private key cannot be all zeros');
    }

    const valid = errors.length === 0;

    return {
      valid,
      errors,
      keyInfo: valid ? {
        privateKeyLength: cleanKey.length,
        publicKeyLength: this.HEX_PUBLIC_KEY_LENGTH,
        keyFormat: 'ed25519-hex',
      } : undefined,
    };
  }

  /**
   * 验证公钥格式
   */
  public static validatePublicKey(publicKey: string): KeyValidationResult {
    const errors: string[] = [];

    // 检查是否为字符串
    if (typeof publicKey !== 'string') {
      errors.push('Public key must be a string');
      return { valid: false, errors };
    }

    // 移除可能的0x前缀
    const cleanKey = publicKey.startsWith('0x') ? publicKey.slice(2) : publicKey;

    // 检查长度
    if (cleanKey.length !== this.HEX_PUBLIC_KEY_LENGTH) {
      errors.push(`Public key must be ${this.HEX_PUBLIC_KEY_LENGTH} hex characters, got ${cleanKey.length}`);
    }

    // 检查是否为有效的十六进制
    if (!/^[0-9a-fA-F]*$/.test(cleanKey)) {
      errors.push('Public key must contain only hexadecimal characters');
    }

    const valid = errors.length === 0;

    return {
      valid,
      errors,
      keyInfo: valid ? {
        privateKeyLength: this.HEX_PRIVATE_KEY_LENGTH,
        publicKeyLength: cleanKey.length,
        keyFormat: 'ed25519-hex',
      } : undefined,
    };
  }

  /**
   * 生成Pacifica地址从公钥
   */
  public static generateAddress(publicKeyBytes: Uint8Array): string {
    try {
      // Pacifica使用SHA256哈希公钥的前20字节作为地址
      const hash = sha256(publicKeyBytes);
      const addressBytes = hash.slice(0, 20);
      return this.bytesToHex(addressBytes);

    } catch (error) {
      throw new CredentialManagerError(
        `Failed to generate address: ${(error as Error).message}`,
        ErrorType.ADDRESS_GENERATION_ERROR
      );
    }
  }

  /**
   * 验证密钥对是否匹配
   */
  public static async verifyKeyPairMatch(privateKey: string, publicKey: string): Promise<boolean> {
    try {
      const derivedKeyPair = await this.deriveKeyPair(privateKey);
      return derivedKeyPair.publicKey.toLowerCase() === publicKey.toLowerCase();

    } catch (error) {
      return false;
    }
  }

  /**
   * 字节数组转十六进制字符串
   */
  public static bytesToHex(bytes: Uint8Array): string {
    return Array.from(bytes)
      .map(b => b.toString(16).padStart(2, '0'))
      .join('');
  }

  /**
   * 十六进制字符串转字节数组
   */
  public static hexToBytes(hex: string): Uint8Array {
    // 移除0x前缀
    const cleanHex = hex.startsWith('0x') ? hex.slice(2) : hex;

    // 确保长度为偶数
    const paddedHex = cleanHex.length % 2 === 0 ? cleanHex : '0' + cleanHex;

    const result = new Uint8Array(paddedHex.length / 2);
    for (let i = 0; i < paddedHex.length; i += 2) {
      result[i / 2] = parseInt(paddedHex.substring(i, i + 2), 16);
    }
    return result;
  }

  /**
   * 安全地清除内存中的私钥数据
   */
  public static secureWipePrivateKey(privateKey: string): void {
    // 在JavaScript中无法真正清除字符串内存，但可以尝试覆盖
    // 这主要是作为最佳实践的象征性操作
    try {
      if (typeof privateKey === 'string') {
        // 创建一个同样长度的随机字符串来"覆盖"
        const wipedLength = privateKey.length;
        let wiped = '';
        for (let i = 0; i < wipedLength; i++) {
          wiped += Math.random().toString(36).charAt(0);
        }
        // 这在JavaScript中实际上不会清除原始字符串
        // 但表明了安全意识
      }
    } catch (error) {
      // 静默处理清除错误
    }
  }

  /**
   * 检查私钥强度
   */
  public static analyzeKeyStrength(privateKey: string): {
    strength: 'weak' | 'medium' | 'strong';
    entropy: number;
    warnings: string[];
  } {
    const warnings: string[] = [];
    let entropy = 0;

    try {
      const cleanKey = privateKey.startsWith('0x') ? privateKey.slice(2) : privateKey;
      const bytes = this.hexToBytes(cleanKey);

      // 计算熵值（简化版）
      const byteFreq = new Map<number, number>();
      for (const byte of bytes) {
        byteFreq.set(byte, (byteFreq.get(byte) || 0) + 1);
      }

      // Shannon熵计算
      const totalBytes = bytes.length;
      for (const freq of byteFreq.values()) {
        const p = freq / totalBytes;
        entropy -= p * Math.log2(p);
      }

      // 检查常见弱模式
      const hexString = cleanKey.toLowerCase();

      // 检查重复模式
      if (/(.{2,})\1{2,}/.test(hexString)) {
        warnings.push('Contains repeating patterns');
      }

      // 检查顺序模式
      if (/0123456789abcdef|fedcba9876543210/.test(hexString)) {
        warnings.push('Contains sequential patterns');
      }

      // 检查过多的相同字符
      const charCounts = new Map<string, number>();
      for (const char of hexString) {
        charCounts.set(char, (charCounts.get(char) || 0) + 1);
      }

      for (const [char, count] of charCounts) {
        if (count > hexString.length * 0.3) {
          warnings.push(`Character '${char}' appears too frequently`);
        }
      }

      // 确定强度级别
      let strength: 'weak' | 'medium' | 'strong';
      if (entropy < 6 || warnings.length > 2) {
        strength = 'weak';
      } else if (entropy < 7.5 || warnings.length > 0) {
        strength = 'medium';
      } else {
        strength = 'strong';
      }

      return {
        strength,
        entropy: Math.round(entropy * 100) / 100,
        warnings,
      };

    } catch (error) {
      return {
        strength: 'weak',
        entropy: 0,
        warnings: ['Unable to analyze key strength'],
      };
    }
  }

  /**
   * 生成助记词种子（可选功能）
   */
  public static generateMnemonic(): string[] {
    // 简化版的BIP39助记词生成（仅用于演示）
    const words = [
      'abandon', 'ability', 'able', 'about', 'above', 'absent', 'absorb', 'abstract',
      'absurd', 'abuse', 'access', 'accident', 'account', 'accuse', 'achieve', 'acid',
      'acoustic', 'acquire', 'across', 'action', 'actor', 'actress', 'actual', 'adapt',
    ];

    const mnemonic: string[] = [];
    for (let i = 0; i < 12; i++) {
      const randomIndex = Math.floor(Math.random() * words.length);
      const word = words[randomIndex];
      if (word) {
        mnemonic.push(word);
      }
    }

    return mnemonic;
  }
}