import { Injectable, Logger } from '@nestjs/common';
import { PrismaService } from '@/infrastructure/persistence/prisma/prisma.service';
import { RecoveryMnemonicAdapter } from '@/infrastructure/blockchain/recovery-mnemonic.adapter';

export interface VerifyMnemonicByAccountParams {
  accountSequence: string;
  mnemonic: string;
}

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

/**
 * 助记词验证服务
 * 通过账户序列号查询存储的哈希并验证助记词
 */
@Injectable()
export class MnemonicVerificationService {
  private readonly logger = new Logger(MnemonicVerificationService.name);

  constructor(
    private readonly prisma: PrismaService,
    private readonly recoveryMnemonic: RecoveryMnemonicAdapter,
  ) {}

  /**
   * 验证助记词是否匹配指定账户
   */
  async verifyMnemonicByAccount(params: VerifyMnemonicByAccountParams): Promise<VerifyMnemonicResult> {
    const { accountSequence, mnemonic } = params;
    this.logger.log(`Verifying mnemonic for account ${accountSequence}`);

    // 1. 先检查是否有已挂失的助记词 (安全检查)
    const revokedRecord = await this.prisma.recoveryMnemonic.findFirst({
      where: {
        accountSequence,
        status: 'REVOKED',
      },
      orderBy: { revokedAt: 'desc' },
    });

    if (revokedRecord) {
      this.logger.warn(`Account ${accountSequence} has revoked mnemonic, rejecting recovery attempt`);
      return {
        valid: false,
        message: '该助记词已被挂失，无法用于账户恢复。如需帮助请联系客服。',
      };
    }

    // 2. 查询账户的 ACTIVE 助记词记录
    const recoveryRecord = await this.prisma.recoveryMnemonic.findFirst({
      where: {
        accountSequence,
        status: 'ACTIVE',
      },
    });

    if (!recoveryRecord) {
      this.logger.warn(`No active recovery mnemonic found for account ${accountSequence}`);
      return {
        valid: false,
        message: 'Account has no recovery mnemonic configured',
      };
    }

    // 3. 使用 RecoveryMnemonicAdapter 验证哈希 (bcrypt 是异步的)
    const result = await this.recoveryMnemonic.verifyMnemonic(mnemonic, recoveryRecord.mnemonicHash);

    if (result.valid) {
      this.logger.log(`Mnemonic verified successfully for account ${accountSequence}`);
    } else {
      this.logger.warn(`Mnemonic verification failed for account ${accountSequence}: ${result.message}`);
    }

    return result;
  }

  /**
   * 保存助记词记录（创建账户时调用）
   */
  async saveRecoveryMnemonic(params: {
    accountSequence: string;
    publicKey: string;
    encryptedMnemonic: string;
    mnemonicHash: string;
  }): Promise<void> {
    this.logger.log(`Saving recovery mnemonic for account ${params.accountSequence}`);

    await this.prisma.recoveryMnemonic.create({
      data: {
        accountSequence: params.accountSequence,
        publicKey: params.publicKey,
        encryptedMnemonic: params.encryptedMnemonic,
        mnemonicHash: params.mnemonicHash,
        status: 'ACTIVE',
        isBackedUp: false,
      },
    });

    this.logger.log(`Recovery mnemonic saved for account ${params.accountSequence}`);
  }

  /**
   * 标记助记词已备份
   */
  async markAsBackedUp(accountSequence: string): Promise<void> {
    await this.prisma.recoveryMnemonic.updateMany({
      where: {
        accountSequence,
        status: 'ACTIVE',
      },
      data: {
        isBackedUp: true,
      },
    });
    this.logger.log(`Recovery mnemonic marked as backed up for account ${accountSequence}`);
  }

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

    // 查找 ACTIVE 状态的助记词
    const activeRecord = await this.prisma.recoveryMnemonic.findFirst({
      where: {
        accountSequence,
        status: 'ACTIVE',
      },
    });

    if (!activeRecord) {
      this.logger.warn(`No active mnemonic found for account ${accountSequence}`);
      return {
        success: false,
        message: '该账户没有可挂失的助记词',
      };
    }

    // 更新状态为 REVOKED
    await this.prisma.recoveryMnemonic.update({
      where: { id: activeRecord.id },
      data: {
        status: 'REVOKED',
        revokedAt: new Date(),
        revokedReason: reason,
      },
    });

    this.logger.log(`Mnemonic revoked successfully for account ${accountSequence}`);
    return {
      success: true,
      message: '助记词已挂失',
    };
  }

  /**
   * 检查助记词是否已挂失
   */
  async isMnemonicRevoked(accountSequence: string): Promise<boolean> {
    const revokedRecord = await this.prisma.recoveryMnemonic.findFirst({
      where: {
        accountSequence,
        status: 'REVOKED',
      },
    });
    return !!revokedRecord;
  }
}
