/**
 * 主凭证管理器实现
 */

import { Account, LoadResult, SignResult, CredentialManagerOptions, ManagerStats, Platform, AccountStatus } from './types';
import { IConfigLoader, ConfigLoader } from '@/loaders/ConfigLoader';
import { ISigner, Signer } from './Signer';
import { PlatformDetectionService } from './PlatformDetector';
import { PacificaSignerStrategy } from '@/platforms/pacifica/PacificaSignerStrategy';
import { PacificaDetector } from '@/platforms/pacifica/PacificaDetector';
import { AsterDetector } from '@/platforms/aster/AsterDetector';
import { BinanceDetector } from '@/platforms/binance/BinanceDetector';

export interface ICredentialManager {
  loadConfig(configPath: string): Promise<LoadResult>;
  watchConfig(configPath: string, callback?: (accounts: Account[]) => void): void;
  stopWatching(): void;
  getAccount(accountId: string): Account | null;
  listAccounts(): Account[];
  sign(accountId: string, message: Uint8Array): Promise<SignResult>;
  verify(accountId: string, message: Uint8Array, signature: string): Promise<boolean>;
  addAccount(accountConfig: any): Promise<boolean>;
  removeAccount(accountId: string): Promise<boolean>;
  getStats(): Promise<ManagerStats>;
  destroy(): Promise<void>;
}

export class CredentialManager implements ICredentialManager {
  private configLoader: IConfigLoader;
  private signer: ISigner;
  private platformDetection: PlatformDetectionService;
  private accounts = new Map<string, Account>();
  private options: Required<CredentialManagerOptions>;
  private signatureStats = { total: 0, successful: 0, totalTime: 0 };
  private startTime = Date.now();
  private destroyed = false;

  constructor(options: CredentialManagerOptions = {}) {
    this.options = {
      enableFileWatching: true,
      signTimeout: 30000,
      enableLogging: true,
      logLevel: 'info',
      ...options,
    };

    this.configLoader = new ConfigLoader();
    this.signer = new Signer();
    this.platformDetection = new PlatformDetectionService();
  }

  public async loadConfig(configPath: string): Promise<LoadResult> {
    const result = await this.configLoader.loadConfig(configPath);

    if (result.success) {
      // 清除现有账户
      this.accounts.clear();

      // 加载新账户
      for (const account of result.accounts) {
        this.accounts.set(account.id, account);
        this.signer.addAccount(account.id, account.platform, account.credentials);
      }
    }

    return result;
  }

  public watchConfig(configPath: string, callback?: (accounts: Account[]) => void): void {
    this.configLoader.watchConfig(configPath, (accounts) => {
      // 更新内部账户映射
      this.accounts.clear();
      for (const account of accounts) {
        this.accounts.set(account.id, account);
        this.signer.addAccount(account.id, account.platform, account.credentials);
      }

      if (callback) {
        callback(accounts);
      }
    });
  }

  public stopWatching(): void {
    this.configLoader.stopWatching();
  }

  public getAccount(accountId: string): Account | null {
    return this.accounts.get(accountId) || null;
  }

  public listAccounts(): Account[] {
    return Array.from(this.accounts.values());
  }

  public async sign(accountId: string, message: Uint8Array): Promise<SignResult> {
    const startTime = Date.now();
    const result = await this.signer.sign(accountId, message);
    const execTime = Date.now() - startTime;

    this.signatureStats.total++;
    this.signatureStats.totalTime += execTime;
    if (result.success) {
      this.signatureStats.successful++;
    }

    return {
      ...result,
      executionTime: execTime
    };
  }

  public async verify(accountId: string, message: Uint8Array, signature: string): Promise<boolean> {
    return await this.signer.verify(accountId, message, signature);
  }

  public async getStats(): Promise<ManagerStats> {
    if (this.destroyed) {
      throw new Error('CredentialManager has been destroyed');
    }

    const accounts = Array.from(this.accounts.values());
    const accountsByPlatform: Record<Platform, number> = {
      [Platform.PACIFICA]: 0,
      [Platform.ASTER]: 0,
      [Platform.BINANCE]: 0,
    };
    const accountsByStatus: Record<AccountStatus, number> = {
      [AccountStatus.LOADING]: 0,
      [AccountStatus.ACTIVE]: 0,
      [AccountStatus.ERROR]: 0,
      [AccountStatus.REMOVED]: 0,
    };

    accounts.forEach(account => {
      accountsByPlatform[account.platform]++;
      accountsByStatus[account.status || AccountStatus.ACTIVE]++;
    });

    return {
      totalAccounts: accounts.length,
      accountsByPlatform,
      accountsByStatus,
      totalSignatures: this.signatureStats.total,
      successRate: this.signatureStats.total > 0 ? this.signatureStats.successful / this.signatureStats.total : 0,
      averageSignatureTime: this.signatureStats.total > 0 ? this.signatureStats.totalTime / this.signatureStats.total : 0,
      memoryUsage: process.memoryUsage().heapUsed,
      uptime: Date.now() - this.startTime,
    };
  }

  public async addAccount(accountConfig: any): Promise<boolean> {
    try {
      const account: Account = {
        id: accountConfig.id,
        platform: accountConfig.platform,
        credentials: accountConfig.credentials,
        metadata: accountConfig.metadata,
        status: AccountStatus.ACTIVE
      };

      this.accounts.set(account.id, account);
      this.signer.addAccount(account.id, account.platform, account.credentials);
      return true;
    } catch (error) {
      return false;
    }
  }

  public async removeAccount(accountId: string): Promise<boolean> {
    try {
      const account = this.accounts.get(accountId);
      if (account) {
        this.accounts.delete(accountId);
        return true;
      }
      return false;
    } catch (error) {
      return false;
    }
  }

  public registerPlatformDetectors(): void {
    // 注册平台检测器
    this.platformDetection.registerDetector(new PacificaDetector());
    this.platformDetection.registerDetector(new AsterDetector());
    this.platformDetection.registerDetector(new BinanceDetector());
  }

  public registerSignerStrategies(): void {
    // 注册Pacifica签名策略
    const pacificaStrategy = new PacificaSignerStrategy();
    this.signer.registerStrategy(Platform.PACIFICA, pacificaStrategy);

    // TODO: 注册其他平台的签名策略
    // this.signer.registerStrategy(Platform.ASTER, new AsterSignerStrategy());
    // this.signer.registerStrategy(Platform.BINANCE, new BinanceSignerStrategy());
  }

  public async destroy(): Promise<void> {
    if (this.destroyed) {
      return;
    }

    this.stopWatching();
    this.accounts.clear();
    this.destroyed = true;
  }
}