import express from 'express';
import assert from 'node:assert/strict';
import { describe, it } from 'node:test';
import extractCredentials from '../../src/middlewares/credentials.js';
import { BadRequestError } from '../../src/httpErrors.js';

describe('credentials middleware', () => {
  it('generates', async () => {
    const credentials = Buffer.from(
      JSON.stringify({
        accessToken: 'abc',
      }),
    ).toString('base64');

    const request = { header: (_key: string) => credentials } as express.Request;
    const response = { locals: {} } as express.Response;

    extractCredentials(request, response, () => {});

    assert.deepEqual(response.locals, {
      credentials: {
        accessToken: 'abc',
      },
    });
  });

  it('malformed header', async () => {
    const request = { header: (_key: string) => 'nope' } as express.Request;
    const response = { locals: {} } as express.Response;

    assert.throws(() => extractCredentials(request, response, () => {}), BadRequestError);
  });

  it('variables', async () => {
    const credentials = Buffer.from(
      JSON.stringify({
        apiKey: 'abc',
      }),
    ).toString('base64');

    const request = { header: (_key: string) => credentials } as express.Request;
    const response = { locals: {} } as express.Response;

    extractCredentials(request, response, () => {});

    assert.deepEqual(response.locals, {
      credentials: {
        apiKey: 'abc',
      },
    });
  });

  it('extracts a credential carrying a rateLimitOverride', async () => {
    const credentials = Buffer.from(
      JSON.stringify({
        accessToken: 'abc',
        rateLimitOverride: { standard: { reqPerPeriod: 5000, periodMs: 60_000 } },
      }),
    ).toString('base64');

    const request = { header: (_key: string) => credentials } as express.Request;
    const response = { locals: {} } as express.Response;

    extractCredentials(request, response, () => {});

    assert.deepEqual(response.locals, {
      credentials: {
        accessToken: 'abc',
        rateLimitOverride: { standard: { reqPerPeriod: 5000, periodMs: 60_000 } },
      },
    });
  });

  it('decorates the logger with the credential id and user id', async () => {
    const credentials = Buffer.from(
      JSON.stringify({
        accessToken: 'abc',
        unitoCredentialId: 'cred-123',
        unitoUserId: 'user-456',
      }),
    ).toString('base64');

    const decorated: Record<string, unknown>[] = [];
    const request = { header: (_key: string) => credentials } as express.Request;
    const response = {
      locals: { logger: { decorate: (metadata: Record<string, unknown>) => decorated.push(metadata) } },
    } as unknown as express.Response;

    extractCredentials(request, response, () => {});

    assert.deepEqual(decorated, [{ credentialId: 'cred-123' }, { userId: 'user-456' }]);
  });
});
