import * as plugins from '../../plugins.js';
import type { OpsServer } from '../classes.opsserver.js';
import * as interfaces from '../../../ts_interfaces/index.js';
import { requireAdminIdentity } from '../helpers/guards.js';
import { toApiData, toApiDataArray } from '../helpers/serialization.js';

export class BackupsHandler {
  public typedrouter = new plugins.typedrequest.TypedRouter();

  constructor(private opsServerRef: OpsServer) {
    this.opsServerRef.typedrouter.addTypedRouter(this.typedrouter);
    this.registerHandlers();
  }

  private registerHandlers(): void {
    this.typedrouter.addTypedHandler(
      new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetBackups>(
        'getBackups',
        async (dataArg) => {
          await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
          const backups = await this.opsServerRef.oneboxRef.backupManager.listBackups();
          return { backups: toApiDataArray(backups) };
        },
      ),
    );

    this.typedrouter.addTypedHandler(
      new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetBackup>(
        'getBackup',
        async (dataArg) => {
          await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
          const backup = await this.opsServerRef.oneboxRef.database.getBackupById(dataArg.backupId);
          if (!backup) {
            throw new plugins.typedrequest.TypedResponseError('Backup not found');
          }
          return { backup: toApiData(backup) };
        },
      ),
    );

    this.typedrouter.addTypedHandler(
      new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_DeleteBackup>(
        'deleteBackup',
        async (dataArg) => {
          await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
          await this.opsServerRef.oneboxRef.backupManager.deleteBackup(dataArg.backupId);
          return { ok: true };
        },
      ),
    );

    this.typedrouter.addTypedHandler(
      new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_RestoreBackup>(
        'restoreBackup',
        async (dataArg) => {
          await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
          const rawResult = await this.opsServerRef.oneboxRef.backupManager.restoreBackup(
            dataArg.backupId,
            dataArg.options,
          );
          return {
            result: {
              service: {
                name: rawResult.service.name,
                status: rawResult.service.status,
              },
              platformResourcesRestored: rawResult.platformResourcesRestored,
              warnings: rawResult.warnings,
            },
          };
        },
      ),
    );

    this.typedrouter.addTypedHandler(
      new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_DownloadBackup>(
        'downloadBackup',
        async (dataArg) => {
          await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
          const backup = await this.opsServerRef.oneboxRef.database.getBackupById(dataArg.backupId);
          if (!backup) {
            throw new plugins.typedrequest.TypedResponseError('Backup not found');
          }
          // Return a download URL that the client can fetch directly
          const filename = backup.filename || `${backup.serviceName}-${backup.createdAt}.tar.enc`;
          return {
            downloadUrl: `/backups/${dataArg.backupId}/download?jwt=${encodeURIComponent(dataArg.identity.jwt)}`,
            filename,
          };
        },
      ),
    );
  }
}
