import express from 'express';
import assert from 'node:assert/strict';
import { describe, it } from 'node:test';
import onError from '../../src/middlewares/errors.js';
import { HttpError } from '../../src/httpErrors.js';

describe('errors middleware', () => {
  it('headers sent, do nothing', () => {
    let actualStatus: number | undefined;
    let actualJson: Record<string, unknown> | undefined;

    const response = {
      headersSent: true,
      status: (code: number) => {
        actualStatus = code;

        return {
          json: (json: Record<string, unknown>) => {
            actualJson = json;
          },
        };
      },
      locals: { logger: { error: () => undefined } },
    } as unknown as express.Response;

    onError(new Error(), {} as express.Request, response, () => {});

    assert.strictEqual(actualStatus, undefined);
    assert.strictEqual(actualJson, undefined);
  });

  it('handles httpError', () => {
    let actualStatus: number | undefined;
    let actualJson: Record<string, unknown> | undefined;

    const response = {
      headersSent: false,
      status: (code: number) => {
        actualStatus = code;

        return {
          json: (json: Record<string, unknown>) => {
            actualJson = json;
          },
        };
      },
      locals: { logger: { error: () => undefined } },
    } as unknown as express.Response;
    onError(new HttpError('httpError', 429), {} as express.Request, response, () => {});

    assert.strictEqual(actualStatus, 429);
    assert.deepEqual(actualJson, { code: '429', message: 'httpError' });
  });

  it('handles other error', () => {
    let actualStatus: number | undefined;
    let actualJson: Record<string, unknown> | undefined;

    const response = {
      headersSent: false,
      status: (code: number) => {
        actualStatus = code;

        return {
          json: (json: Record<string, unknown>) => {
            actualJson = json;
          },
        };
      },
      locals: { logger: { error: () => undefined } },
    } as unknown as express.Response;
    onError(new Error('error'), {} as express.Request, response, () => {});

    assert.strictEqual(actualStatus, 500);
    assert.strictEqual(actualJson?.code, '500');
    assert.deepEqual(actualJson?.originalError, { code: 'Error', message: 'error' });
  });
});
