import { lastValueFrom, of, throwError } from 'rxjs';
import { ApiTimingInterceptor, resolveApiSlowRequestThreshold } from './api-timing.interceptor';

describe('ApiTimingInterceptor', () => {
  const originalEnv = process.env.API_SLOW_REQUEST_MS;

  afterEach(() => {
    process.env.API_SLOW_REQUEST_MS = originalEnv;
    jest.restoreAllMocks();
  });

  it('uses a safe default threshold when env is missing or invalid', () => {
    delete process.env.API_SLOW_REQUEST_MS;
    expect(resolveApiSlowRequestThreshold()).toBe(1000);

    process.env.API_SLOW_REQUEST_MS = 'not-a-number';
    expect(resolveApiSlowRequestThreshold()).toBe(1000);
  });

  it('uses a positive configured threshold', () => {
    process.env.API_SLOW_REQUEST_MS = '250';

    expect(resolveApiSlowRequestThreshold()).toBe(250);
  });

  it('logs slow HTTP requests with method and url', async () => {
    process.env.API_SLOW_REQUEST_MS = '10';
    const interceptor = new ApiTimingInterceptor();
    const warn = jest.fn();
    (interceptor as any).logger.warn = warn;
    jest.spyOn(Date, 'now').mockReturnValueOnce(1000).mockReturnValueOnce(1025);
    const context = {
      switchToHttp: () => ({
        getRequest: () => ({
          method: 'PUT',
          originalUrl: '/api/v1/data/dev-tasks',
        }),
      }),
    };
    const next = { handle: () => of({ ok: true }) };

    await lastValueFrom(interceptor.intercept(context as any, next as any));

    expect(warn).toHaveBeenCalledWith(expect.stringContaining('PUT /api/v1/data/dev-tasks'));
    expect(warn).toHaveBeenCalledWith(expect.stringContaining('25ms'));
  });

  it('logs slow HTTP requests even when the handler fails', async () => {
    process.env.API_SLOW_REQUEST_MS = '10';
    const interceptor = new ApiTimingInterceptor();
    const warn = jest.fn();
    (interceptor as any).logger.warn = warn;
    jest.spyOn(Date, 'now').mockReturnValueOnce(1000).mockReturnValueOnce(1030);
    const context = {
      switchToHttp: () => ({
        getRequest: () => ({
          method: 'PATCH',
          url: '/api/v1/data/bugs',
        }),
      }),
    };
    const next = { handle: () => throwError(() => new Error('boom')) };

    await expect(lastValueFrom(interceptor.intercept(context as any, next as any))).rejects.toThrow('boom');

    expect(warn).toHaveBeenCalledWith(expect.stringContaining('PATCH /api/v1/data/bugs'));
    expect(warn).toHaveBeenCalledWith(expect.stringContaining('30ms'));
  });
});
