/**
 * Unit test for the filesystem (mounted-path / NAS) backup transport
 * (`src/lib/services/backup-destinations/filesystem.ts`).
 */

import { mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync, mkdirSync } from 'node:fs';
import { tmpdir } from 'node:os';
import path from 'node:path';

import { afterEach, beforeEach, describe, expect, it } from 'vitest';

import { FilesystemTransport } from '@/lib/services/backup-destinations/filesystem';
import { BACKUP_NAME_PREFIX } from '@/lib/services/backup-destinations/types';

describe('FilesystemTransport', () => {
  let work: string;
  let destDir: string;
  beforeEach(() => {
    work = mkdtempSync(path.join(tmpdir(), 'pn-fstr-'));
    destDir = path.join(work, 'backups');
    mkdirSync(destDir);
  });
  afterEach(() => {
    rmSync(work, { recursive: true, force: true });
  });

  it('test() rejects when the directory does not exist', async () => {
    const t = new FilesystemTransport({ directory: path.join(work, 'nope') });
    await expect(t.test()).rejects.toThrow();
  });

  it('push() copies the bundle into the destination directory', async () => {
    const local = path.join(work, `${BACKUP_NAME_PREFIX}2026-06-04.tar`);
    writeFileSync(local, Buffer.from('BUNDLE-BYTES'));
    const t = new FilesystemTransport({ directory: destDir });

    const res = await t.push(local, `${BACKUP_NAME_PREFIX}2026-06-04.tar`);

    expect(res.bytes).toBe('BUNDLE-BYTES'.length);
    const landed = readFileSync(path.join(destDir, `${BACKUP_NAME_PREFIX}2026-06-04.tar`), 'utf8');
    expect(landed).toBe('BUNDLE-BYTES');
  });

  it('prune() keeps the N newest bundles and ignores unrelated files', async () => {
    // Five backups (timestamp-in-name sorts chronologically) + an unrelated file.
    for (const d of ['01', '02', '03', '04', '05']) {
      writeFileSync(path.join(destDir, `${BACKUP_NAME_PREFIX}2026-06-${d}.tar`), 'x');
    }
    writeFileSync(path.join(destDir, 'unrelated-keepme.txt'), 'y');

    const t = new FilesystemTransport({ directory: destDir });
    const { deleted } = await t.prune(2);

    expect(deleted).toBe(3);
    const remaining = readdirSync(destDir).sort();
    expect(remaining).toEqual([
      `${BACKUP_NAME_PREFIX}2026-06-04.tar`,
      `${BACKUP_NAME_PREFIX}2026-06-05.tar`,
      'unrelated-keepme.txt',
    ]);
  });

  it('prune(null) keeps everything', async () => {
    for (const d of ['01', '02', '03']) {
      writeFileSync(path.join(destDir, `${BACKUP_NAME_PREFIX}2026-06-${d}.tar`), 'x');
    }
    const t = new FilesystemTransport({ directory: destDir });
    const { deleted } = await t.prune(null);
    expect(deleted).toBe(0);
    expect(readdirSync(destDir).length).toBe(3);
  });
});
