import { test } from 'node:test';
import assert from 'node:assert/strict';
import { createStore } from 'jotai';
import { ImportRoomKeyProgressData, ImportRoomKeyStage } from 'matrix-js-sdk/lib/crypto-api';
import { backupRestoreProgressAtom, BackupProgressStatus } from './backupRestore';

// backupRestoreProgressAtom maps ImportRoomKeyProgressData stages onto an
// IBackupProgress status held in an unexported baseAtom:
//   Fetch    -> Fetching
//   LoadKeys with successes+failures === total -> Done
//   LoadKeys otherwise -> Loading{ downloaded = successes+failures }
// We drive the write atom through a jotai store and read back the getter.

const load = (successes: number, failures: number, total: number): ImportRoomKeyProgressData => ({
  stage: ImportRoomKeyStage.LoadKeys,
  successes,
  failures,
  total,
});

test('starts Idle', () => {
  const store = createStore();
  assert.deepEqual(store.get(backupRestoreProgressAtom), {
    status: BackupProgressStatus.Idle,
  });
});

test('Fetch stage -> Fetching', () => {
  const store = createStore();
  store.set(backupRestoreProgressAtom, { stage: ImportRoomKeyStage.Fetch });
  assert.deepEqual(store.get(backupRestoreProgressAtom), {
    status: BackupProgressStatus.Fetching,
  });
});

test('LoadKeys with downloaded === total -> Done', () => {
  const store = createStore();
  store.set(backupRestoreProgressAtom, load(8, 2, 10));
  assert.deepEqual(store.get(backupRestoreProgressAtom), {
    status: BackupProgressStatus.Done,
  });
});

test('LoadKeys mid-progress -> Loading with downloaded = successes + failures', () => {
  const store = createStore();
  store.set(backupRestoreProgressAtom, load(3, 1, 10));
  assert.deepEqual(store.get(backupRestoreProgressAtom), {
    status: BackupProgressStatus.Loading,
    data: { downloaded: 4, successes: 3, failures: 1, total: 10 },
  });
});

test('LoadKeys at zero progress -> Loading with downloaded 0', () => {
  const store = createStore();
  store.set(backupRestoreProgressAtom, load(0, 0, 5));
  assert.deepEqual(store.get(backupRestoreProgressAtom), {
    status: BackupProgressStatus.Loading,
    data: { downloaded: 0, successes: 0, failures: 0, total: 5 },
  });
});

test('Fetch then LoadKeys completion transitions Fetching -> Done', () => {
  const store = createStore();
  store.set(backupRestoreProgressAtom, { stage: ImportRoomKeyStage.Fetch });
  assert.equal(store.get(backupRestoreProgressAtom).status, BackupProgressStatus.Fetching);
  store.set(backupRestoreProgressAtom, load(5, 0, 5));
  assert.equal(store.get(backupRestoreProgressAtom).status, BackupProgressStatus.Done);
});
