/**
 * Backup Client Service
 *
 * mpc-service 调用 backup-service 存储/获取 delegate share
 * backup-service 负责安全存储 MPC 分片备份
 */

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

export interface StoreBackupShareParams {
  userId: string;
  accountSequence: string;
  username: string;
  publicKey: string;
  partyId: string;
  partyIndex: number;
  encryptedShare: string;
}

export interface RetrieveBackupShareParams {
  userId: string;
  publicKey: string;
}

export interface BackupShareResult {
  encryptedShareData: string;
  partyIndex: number;
  publicKey: string;
}

@Injectable()
export class BackupClientService {
  private readonly logger = new Logger(BackupClientService.name);
  private readonly backupServiceUrl: string;
  private readonly serviceJwtSecret: string;
  private readonly enabled: boolean;

  constructor(
    private readonly httpService: HttpService,
    private readonly configService: ConfigService,
  ) {
    this.backupServiceUrl = this.configService.get<string>('BACKUP_SERVICE_URL', 'http://localhost:3002');
    this.serviceJwtSecret = this.configService.get<string>('SERVICE_JWT_SECRET', '');
    this.enabled = this.configService.get<string>('BACKUP_SERVICE_ENABLED', 'true') === 'true';

    this.logger.log(`[INIT] BackupClientService initialized`);
    this.logger.log(`[INIT] URL: ${this.backupServiceUrl}`);
    this.logger.log(`[INIT] Enabled: ${this.enabled}`);
  }

  /**
   * 检查 backup-service 是否启用
   */
  isEnabled(): boolean {
    return this.enabled && !!this.serviceJwtSecret;
  }

  /**
   * 存储 delegate share 到 backup-service
   */
  async storeBackupShare(params: StoreBackupShareParams): Promise<void> {
    if (!this.isEnabled()) {
      this.logger.warn('Backup service is disabled, skipping backup share storage');
      return;
    }

    this.logger.log(`Storing backup share: userId=${params.userId}, username=${params.username}`);

    try {
      const serviceToken = this.generateServiceToken();

      await firstValueFrom(
        this.httpService.post(
          `${this.backupServiceUrl}/backup-share/store`,
          {
            userId: params.userId,
            accountSequence: params.accountSequence,
            publicKey: params.publicKey,
            encryptedShareData: params.encryptedShare,
          },
          {
            headers: {
              'Content-Type': 'application/json',
              'X-Service-Token': serviceToken,
            },
            timeout: 30000,
          },
        ),
      );

      this.logger.log(`Backup share stored successfully: userId=${params.userId}`);
    } catch (error) {
      this.logger.error(`Failed to store backup share: userId=${params.userId}`, error);
      throw error; // 抛出异常，让调用方处理
    }
  }

  /**
   * 从 backup-service 获取 delegate share (用于签名)
   */
  async retrieveBackupShare(params: RetrieveBackupShareParams): Promise<BackupShareResult | null> {
    if (!this.isEnabled()) {
      this.logger.warn('Backup service is disabled');
      return null;
    }

    this.logger.log(`Retrieving backup share: userId=${params.userId}`);

    try {
      const serviceToken = this.generateServiceToken();

      const response = await firstValueFrom(
        this.httpService.post<BackupShareResult>(
          `${this.backupServiceUrl}/backup-share/retrieve`,
          {
            userId: params.userId,
            publicKey: params.publicKey,
          },
          {
            headers: {
              'Content-Type': 'application/json',
              'X-Service-Token': serviceToken,
            },
            timeout: 30000,
          },
        ),
      );

      this.logger.log(`Backup share retrieved: userId=${params.userId}`);
      return response.data;
    } catch (error) {
      this.logger.error(`Failed to retrieve backup share: userId=${params.userId}`, error);
      return null;
    }
  }

  /**
   * 生成服务间认证 JWT
   */
  private generateServiceToken(): string {
    return jwt.sign(
      {
        service: 'mpc-service',
        iat: Math.floor(Date.now() / 1000),
      },
      this.serviceJwtSecret,
      { expiresIn: '5m' },
    );
  }
}
