/**
 * Blockchain Client Service
 *
 * identity-service 调用 blockchain-service API
 * - 验证助记词
 * - 从助记词派生地址
 */

import { Injectable, Logger } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';
import { ConfigService } from '@nestjs/config';
import { firstValueFrom } from 'rxjs';

export interface VerifyMnemonicParams {
  mnemonic: string;
  expectedAddresses: Array<{
    chainType: string;
    address: string;
  }>;
}

export interface VerifyMnemonicResult {
  valid: boolean;
  matchedAddresses: string[];
  mismatchedAddresses: string[];
}

export interface VerifyMnemonicByAccountParams {
  accountSequence: string; // 格式: D + YYMMDD + 5位序号
  mnemonic: string;
}

export interface VerifyMnemonicHashResult {
  valid: boolean;
  message?: string;
}

export interface DerivedAddress {
  chainType: string;
  address: string;
}

@Injectable()
export class BlockchainClientService {
  private readonly logger = new Logger(BlockchainClientService.name);
  private readonly blockchainServiceUrl: string;

  constructor(
    private readonly httpService: HttpService,
    private readonly configService: ConfigService,
  ) {
    this.blockchainServiceUrl = this.configService.get<string>(
      'BLOCKCHAIN_SERVICE_URL',
      'http://blockchain-service:3000',
    );
    this.logger.log(`[INIT] BlockchainClientService initialized`);
    this.logger.log(`[INIT] URL: ${this.blockchainServiceUrl}`);
  }

  /**
   * 验证助记词是否匹配指定的钱包地址
   */
  async verifyMnemonic(
    params: VerifyMnemonicParams,
  ): Promise<VerifyMnemonicResult> {
    this.logger.log(
      `Verifying mnemonic against ${params.expectedAddresses.length} addresses`,
    );

    try {
      const response = await firstValueFrom(
        this.httpService.post<VerifyMnemonicResult>(
          `${this.blockchainServiceUrl}/internal/verify-mnemonic`,
          {
            mnemonic: params.mnemonic,
            expectedAddresses: params.expectedAddresses,
          },
          {
            headers: { 'Content-Type': 'application/json' },
            timeout: 30000,
          },
        ),
      );

      this.logger.log(
        `Mnemonic verification result: valid=${response.data.valid}`,
      );
      return response.data;
    } catch (error) {
      this.logger.error('Failed to verify mnemonic', error);
      throw error;
    }
  }

  /**
   * 通过账户序列号验证助记词（用于账户恢复）
   */
  async verifyMnemonicByAccount(
    params: VerifyMnemonicByAccountParams,
  ): Promise<VerifyMnemonicHashResult> {
    this.logger.log(`Verifying mnemonic for account ${params.accountSequence}`);

    try {
      const response = await firstValueFrom(
        this.httpService.post<VerifyMnemonicHashResult>(
          `${this.blockchainServiceUrl}/internal/verify-mnemonic-hash`,
          {
            accountSequence: params.accountSequence,
            mnemonic: params.mnemonic,
          },
          {
            headers: { 'Content-Type': 'application/json' },
            timeout: 30000,
          },
        ),
      );

      this.logger.log(
        `Mnemonic verification result: valid=${response.data.valid}`,
      );
      return response.data;
    } catch (error) {
      this.logger.error('Failed to verify mnemonic', error);
      throw error;
    }
  }

  /**
   * 从助记词派生所有链的钱包地址
   */
  async deriveFromMnemonic(mnemonic: string): Promise<DerivedAddress[]> {
    this.logger.log('Deriving addresses from mnemonic');

    try {
      const response = await firstValueFrom(
        this.httpService.post<{ addresses: DerivedAddress[] }>(
          `${this.blockchainServiceUrl}/internal/derive-from-mnemonic`,
          { mnemonic },
          {
            headers: { 'Content-Type': 'application/json' },
            timeout: 30000,
          },
        ),
      );

      this.logger.log(
        `Derived ${response.data.addresses.length} addresses from mnemonic`,
      );
      return response.data.addresses;
    } catch (error) {
      this.logger.error('Failed to derive addresses from mnemonic', error);
      throw error;
    }
  }

  /**
   * 标记助记词已备份
   */
  async markMnemonicBackedUp(accountSequence: string): Promise<void> {
    this.logger.log(
      `Marking mnemonic as backed up for account ${accountSequence}`,
    );

    try {
      await firstValueFrom(
        this.httpService.put(
          `${this.blockchainServiceUrl}/internal/mnemonic/backup`,
          { accountSequence },
          {
            headers: { 'Content-Type': 'application/json' },
            timeout: 30000,
          },
        ),
      );

      this.logger.log(
        `Mnemonic marked as backed up for account ${accountSequence}`,
      );
    } catch (error) {
      this.logger.error('Failed to mark mnemonic as backed up', error);
      throw error;
    }
  }

  /**
   * 挂失助记词
   */
  async revokeMnemonic(
    accountSequence: string,
    reason: string,
  ): Promise<{ success: boolean; message: string }> {
    this.logger.log(
      `Revoking mnemonic for account ${accountSequence}, reason: ${reason}`,
    );

    try {
      const response = await firstValueFrom(
        this.httpService.post<{ success: boolean; message: string }>(
          `${this.blockchainServiceUrl}/internal/mnemonic/revoke`,
          { accountSequence, reason },
          {
            headers: { 'Content-Type': 'application/json' },
            timeout: 30000,
          },
        ),
      );

      this.logger.log(
        `Mnemonic revoke result: success=${response.data.success}`,
      );
      return response.data;
    } catch (error) {
      this.logger.error('Failed to revoke mnemonic', error);
      throw error;
    }
  }
}
