// SPDX-FileCopyrightText: 2025 Contributors to the CitrineOS Project
//
// SPDX-License-Identifier: Apache-2.0
import { faker } from '@faker-js/faker';
import { aRequest } from '../../providers/IncomingMessageProvider.js';
import { anAuthenticationOptions } from '../../providers/AuthenticationOptionsProvider.js';
import { CacheNamespace, createIdentifier, DEFAULT_TENANT_ID, ICache } from '@citrineos/base';
import { ConnectedStationFilter } from '../../../index.js';
import { afterEach, beforeEach, describe, expect, it, Mocked, vi } from 'vitest';

describe('ConnectedStationFilter', () => {
  let cache: Mocked<ICache>;
  let filter: ConnectedStationFilter;

  beforeEach(() => {
    cache = {
      get: vi.fn(),
    } as unknown as Mocked<ICache>;

    filter = new ConnectedStationFilter(cache);
  });

  afterEach(() => {
    cache.get.mockReset();
  });

  it('should not reject when station is not connected', async () => {
    const ocppConnectionName = faker.string.uuid().toString();
    const identifier = createIdentifier(DEFAULT_TENANT_ID, ocppConnectionName);
    givenStationIsNotConnected();

    await filter.authenticate(
      DEFAULT_TENANT_ID,
      ocppConnectionName,
      aRequest(),
      anAuthenticationOptions(),
    );

    expect(cache.get).toHaveBeenCalledWith(identifier, CacheNamespace.Connections);
  });

  it('should reject when station is already connected', async () => {
    const ocppConnectionName = faker.string.uuid().toString();
    const identifier = createIdentifier(DEFAULT_TENANT_ID, ocppConnectionName);
    givenStationIsConnected();

    await expect(
      filter.authenticate(
        DEFAULT_TENANT_ID,
        ocppConnectionName,
        aRequest(),
        anAuthenticationOptions(),
      ),
    ).rejects.toThrow(`New connection attempted for already connected identifier ${identifier}`);

    expect(cache.get).toHaveBeenCalledWith(identifier, CacheNamespace.Connections);
  });

  function givenStationIsConnected() {
    cache.get.mockResolvedValue(faker.number.int({ min: 0, max: 3 }).toString() as any);
  }

  function givenStationIsNotConnected() {
    cache.get.mockResolvedValue(null as any);
  }
});
