import { Injectable, Logger } from '@nestjs/common';
import * as fs from 'fs';
import * as path from 'path';
import * as archiver from 'archiver';
import { BackupTarget } from '@/domain/enums';
import {
  BackupHandler,
  BackupResult,
  ProgressCallback,
} from '@/domain/interfaces/backup-handler.interface';

@Injectable()
export class ZookeeperBackupHandler implements BackupHandler {
  readonly target = BackupTarget.ZOOKEEPER;
  private readonly logger = new Logger(ZookeeperBackupHandler.name);

  private readonly dataDir = '/backup-source/zookeeper/data';
  private readonly logDir = '/backup-source/zookeeper/log';

  async execute(outputDir: string, onProgress: ProgressCallback): Promise<BackupResult> {
    const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
    const fileName = `zookeeper-${timestamp}.tar.gz`;
    const filePath = path.join(outputDir, fileName);

    fs.mkdirSync(outputDir, { recursive: true });

    onProgress(0, 'ZooKeeper 数据打包开始...');

    return new Promise<BackupResult>((resolve, reject) => {
      const output = fs.createWriteStream(filePath);
      const archive = archiver('tar', { gzip: true });

      output.on('close', () => {
        const fileSize = archive.pointer();
        this.logger.log(`ZooKeeper 备份完成: ${fileName}, 大小: ${fileSize} bytes`);
        onProgress(100, 'ZooKeeper 备份完成');
        resolve({ fileName, filePath, fileSize });
      });

      archive.on('error', (err) => {
        this.logger.error(`ZooKeeper 备份打包失败: ${err.message}`);
        reject(err);
      });

      archive.pipe(output);

      if (fs.existsSync(this.dataDir)) {
        archive.directory(this.dataDir, 'data');
        onProgress(30, '打包 ZooKeeper data/...');
      }

      if (fs.existsSync(this.logDir)) {
        archive.directory(this.logDir, 'log');
        onProgress(60, '打包 ZooKeeper log/...');
      }

      archive.finalize();
    });
  }
}
