import { getContainer } from '../../lib/cosmos-init.js';
import { productId } from '../../lib/config.js';
import { childLogger } from '../../lib/logger.js';
import type { Backup, BackupParams } from './types.js';

const log = childLogger('backup/repository');

const BACKUPS_CONTAINER = 'backups';

export async function createBackup(params: BackupParams = {}): Promise<Backup> {
  const containersToBackup = params.containers || ['services', 'deployments', 'audit-logs'];
  const backupData: Record<string, any[]> = {};
  let totalItems = 0;

  for (const containerName of containersToBackup) {
    try {
      const { resources } = await getContainer(containerName as any)
        .items.query({
          query: 'SELECT * FROM c WHERE c.productId = @productId',
          parameters: [{ name: '@productId', value: productId }],
        })
        .fetchAll();

      backupData[containerName] = resources;
      totalItems += resources.length;
    } catch (error) {
      log.error({ err: error, containerName }, "failed to backup container");
      throw error;
    }
  }

  const backup: Backup = {
    id: `backup-${Date.now()}`,
    timestamp: new Date().toISOString(),
    containers: containersToBackup,
    itemCount: totalItems,
    size: JSON.stringify(backupData).length,
    productId,
  };

  await getContainer(BACKUPS_CONTAINER).items.create({
    ...backup,
    data: backupData,
  });

  return backup;
}

export async function getBackups(): Promise<Backup[]> {
  try {
    const { resources } = await getContainer(BACKUPS_CONTAINER)
      .items.query({
        query: 'SELECT * FROM c WHERE c.productId = @productId ORDER BY c.timestamp DESC',
        parameters: [{ name: '@productId', value: productId }],
      })
      .fetchAll();

    return resources as Backup[];
  } catch (error) {
    log.error({ err: error }, "failed to get backups");
    return [];
  }
}

export async function getBackup(backupId: string): Promise<Backup | null> {
  try {
    const { resource } = await getContainer(BACKUPS_CONTAINER).item(backupId).read();
    return resource as Backup;
  } catch (error) {
    return null;
  }
}

export async function restoreBackup(backupId: string): Promise<void> {
  const backup = await getBackup(backupId);
  if (!backup) {
    throw new Error('Backup not found');
  }

  const backupData = (backup as any).data;
  if (!backupData) {
    throw new Error('Backup data not found');
  }

  for (const containerName of backup.containers) {
    const items = backupData[containerName];
    if (!items) continue;

    const targetContainer = getContainer(containerName as any);

    for (const item of items) {
      try {
        await targetContainer.items.upsert(item);
      } catch (error) {
        log.error({ err: error, containerName }, "failed to restore backup item");
      }
    }
  }
}

export async function deleteBackup(backupId: string): Promise<void> {
  try {
    await getContainer(BACKUPS_CONTAINER).item(backupId).delete();
  } catch (error) {
    log.error({ err: error }, "failed to delete backup");
    throw error;
  }
}
