import { Injectable, Logger } from '@nestjs/common';
import { PrismaService } from '../../infrastructure/persistence/prisma/prisma.service';
import { AuditActionType, Prisma } from '@prisma/client';
import * as crypto from 'crypto';

export interface AuditLogEntry {
  accountSequence: string;
  actionType: AuditActionType;
  actionDetail: Record<string, unknown>;
  ipAddress?: string;
  userAgent?: string;
  referenceId?: string;
  referenceType?: string;
}

/**
 * 审计分类账服务
 * 设计原则：Append-Only，只增加不修改不删除
 * 用于记录所有敏感操作，如交易、支付密码验证等
 */
@Injectable()
export class AuditLedgerService {
  private readonly logger = new Logger(AuditLedgerService.name);

  constructor(private readonly prisma: PrismaService) {}

  /**
   * 记录审计日志
   * @param entry 审计日志条目
   * @returns 创建的审计日志ID
   */
  async log(entry: AuditLogEntry): Promise<string> {
    try {
      // 获取前一条记录的哈希（用于链式完整性）
      const prevRecord = await this.prisma.auditLedger.findFirst({
        where: { accountSequence: entry.accountSequence },
        orderBy: { createdAt: 'desc' },
        select: { recordHash: true },
      });

      const prevHash = prevRecord?.recordHash || null;

      // 计算当前记录的哈希
      const recordHash = this.calculateHash({
        accountSequence: entry.accountSequence,
        actionType: entry.actionType,
        actionDetail: entry.actionDetail,
        prevHash,
        timestamp: new Date().toISOString(),
      });

      // 创建审计记录（Append-Only，仅插入不修改不删除）
      const auditLog = await this.prisma.auditLedger.create({
        data: {
          accountSequence: entry.accountSequence,
          actionType: entry.actionType,
          actionDetail: entry.actionDetail as Prisma.InputJsonValue,
          ipAddress: entry.ipAddress,
          userAgent: entry.userAgent,
          prevHash,
          recordHash,
          referenceId: entry.referenceId,
          referenceType: entry.referenceType,
        },
      });

      this.logger.log(
        `Audit log created: ${entry.actionType} for ${entry.accountSequence}`,
      );

      return auditLog.id;
    } catch (error) {
      this.logger.error(`Failed to create audit log: ${error.message}`, error.stack);
      // 审计日志失败不应阻止业务操作，但需要记录错误
      throw error;
    }
  }

  /**
   * 记录卖出订单创建
   */
  async logSellOrderCreated(params: {
    accountSequence: string;
    orderNo: string;
    quantity: string;
    price: string;
    tradePasswordVerified: boolean;
    ipAddress?: string;
    userAgent?: string;
  }): Promise<string> {
    return this.log({
      accountSequence: params.accountSequence,
      actionType: AuditActionType.SELL_ORDER_CREATED,
      actionDetail: {
        orderNo: params.orderNo,
        quantity: params.quantity,
        price: params.price,
        tradePasswordVerified: params.tradePasswordVerified,
        timestamp: new Date().toISOString(),
      },
      ipAddress: params.ipAddress,
      userAgent: params.userAgent,
      referenceId: params.orderNo,
      referenceType: 'ORDER',
    });
  }

  /**
   * 记录支付密码验证
   */
  async logTradePasswordVerification(params: {
    accountSequence: string;
    success: boolean;
    purpose: string; // 用途：如 "SELL_ORDER"
    ipAddress?: string;
    userAgent?: string;
  }): Promise<string> {
    return this.log({
      accountSequence: params.accountSequence,
      actionType: params.success
        ? AuditActionType.TRADE_PASSWORD_VERIFIED
        : AuditActionType.TRADE_PASSWORD_FAILED,
      actionDetail: {
        success: params.success,
        purpose: params.purpose,
        timestamp: new Date().toISOString(),
      },
      ipAddress: params.ipAddress,
      userAgent: params.userAgent,
    });
  }

  /**
   * 查询用户的审计日志
   */
  async getAuditLogs(
    accountSequence: string,
    options: {
      actionType?: AuditActionType;
      limit?: number;
      offset?: number;
    } = {},
  ) {
    const { actionType, limit = 50, offset = 0 } = options;

    return this.prisma.auditLedger.findMany({
      where: {
        accountSequence,
        ...(actionType && { actionType }),
      },
      orderBy: { createdAt: 'desc' },
      take: limit,
      skip: offset,
    });
  }

  /**
   * 验证审计日志链的完整性
   * @param accountSequence 用户账户序列号
   * @returns 验证结果
   */
  async verifyChainIntegrity(accountSequence: string): Promise<{
    isValid: boolean;
    totalRecords: number;
    invalidRecords: string[];
  }> {
    const records = await this.prisma.auditLedger.findMany({
      where: { accountSequence },
      orderBy: { createdAt: 'asc' },
    });

    const invalidRecords: string[] = [];
    let prevHash: string | null = null;

    for (const record of records) {
      // 检查 prevHash 是否正确
      if (record.prevHash !== prevHash) {
        invalidRecords.push(record.id);
      }
      prevHash = record.recordHash;
    }

    return {
      isValid: invalidRecords.length === 0,
      totalRecords: records.length,
      invalidRecords,
    };
  }

  /**
   * 计算记录哈希
   */
  private calculateHash(data: Record<string, unknown>): string {
    const json = JSON.stringify(data, Object.keys(data).sort());
    return crypto.createHash('sha256').update(json).digest('hex');
  }
}
