import { assertEquals } from 'jsr:@std/assert';
import { describe, it } from 'jsr:@std/testing/bdd';
import { TypedRequest } from '@api.global/typedrequest';
import { createTestContainer, getTestPorts, loginAndGetIdentity } from './helpers/server.helper.ts';
import { ObjectStorageContainer } from '../ts/index.ts';
import type { IReq_GetClusterHealth } from '../ts_interfaces/requests/status.ts';
import type * as interfaces from '../ts_interfaces/index.ts';

const PORT_INDEX = 9;
const ports = getTestPorts(PORT_INDEX);
const url = `http://localhost:${ports.uiPort}/typedrequest`;
const storageDirectory = `.nogit/testdata-${PORT_INDEX}`;

const cleanupStorageDirectory = async () => {
  try {
    await Deno.remove(storageDirectory, { recursive: true });
  } catch (error) {
    if (!(error instanceof Deno.errors.NotFound)) {
      throw error;
    }
  }
};

describe('Cluster health', { sanitizeResources: false, sanitizeOps: false }, () => {
  it('exposes smartstorage cluster health through the management API', async () => {
    await cleanupStorageDirectory();

    let container: ObjectStorageContainer | null = null;
    try {
      const drivePaths = Array.from({ length: 6 }, (_value, index) => {
        return `${storageDirectory}/drive-${index + 1}`;
      });

      container = createTestContainer(PORT_INDEX, {
        storageDirectory,
        clusterEnabled: true,
        clusterNodeId: 'objectstorage-test-node',
        clusterQuicPort: 19433,
        drivePaths,
        erasureDataShards: 4,
        erasureParityShards: 2,
        erasureChunkSizeBytes: 1024 * 1024,
      });
      await container.start();

      const identity: interfaces.data.IIdentity = await loginAndGetIdentity(ports.uiPort);
      const req = new TypedRequest<IReq_GetClusterHealth>(url, 'getClusterHealth');
      const response = await req.fire({ identity });
      const health = response.clusterHealth;

      assertEquals(health.enabled, true);
      assertEquals(health.nodeId, 'objectstorage-test-node');
      assertEquals(health.quorumHealthy, true);
      assertEquals(health.majorityHealthy, true);
      assertEquals(health.drives?.length, 6);
      assertEquals(health.drives?.every((drive) => drive.status === 'online'), true);
      assertEquals(health.erasure?.dataShards, 4);
      assertEquals(health.erasure?.parityShards, 2);
      assertEquals(health.erasure?.totalShards, 6);
    } finally {
      if (container) {
        await container.stop();
      }
      await cleanupStorageDirectory();
    }
  });
});
