import assert from 'node:assert/strict';
import { describe, it } from 'node:test';
import * as errors from '../src/errors.js';
import * as httpErrors from '../src/httpErrors.js';

describe('handleErrorResponse', () => {
  it('returns correct httpError given status code', () => {
    assert.ok(errors.buildHttpError(401, 'unauthorized') instanceof httpErrors.UnauthorizedError);
    assert.ok(errors.buildHttpError(403, 'forbidden') instanceof httpErrors.ForbiddenError);
    assert.ok(errors.buildHttpError(404, 'not found') instanceof httpErrors.NotFoundError);
    assert.ok(errors.buildHttpError(408, 'timeout') instanceof httpErrors.TimeoutError);
    assert.ok(errors.buildHttpError(410, 'resource gone') instanceof httpErrors.ResourceGoneError);
    assert.ok(errors.buildHttpError(422, 'unprocessable entity') instanceof httpErrors.UnprocessableEntityError);
    assert.ok(errors.buildHttpError(423, 'resource gone') instanceof httpErrors.ProviderInstanceLockedError);
    assert.ok(errors.buildHttpError(429, 'rate limit exceeded') instanceof httpErrors.RateLimitExceededError);
    assert.ok(errors.buildHttpError(500, 'internal server error') instanceof httpErrors.HttpError);
  });
});

describe('parseRetryAfterSeconds', () => {
  it('parses integer delay-seconds', () => {
    assert.equal(errors.parseRetryAfterSeconds('30'), 30);
  });

  it('rounds fractional delay-seconds up', () => {
    assert.equal(errors.parseRetryAfterSeconds('30.2'), 31);
  });

  it('trims surrounding whitespace', () => {
    assert.equal(errors.parseRetryAfterSeconds(' 30 '), 30);
  });

  it('parses an HTTP-date into seconds, rounded up', () => {
    const seconds = errors.parseRetryAfterSeconds(new Date(Date.now() + 5000).toUTCString());
    assert.ok(typeof seconds === 'number' && seconds >= 4 && seconds <= 6);
  });

  it('clamps a past HTTP-date to zero', () => {
    assert.equal(errors.parseRetryAfterSeconds(new Date(Date.now() - 60_000).toUTCString()), 0);
  });

  it('returns undefined for an unparseable value', () => {
    assert.equal(errors.parseRetryAfterSeconds('soon'), undefined);
  });

  it('returns undefined for an absent or blank header', () => {
    assert.equal(errors.parseRetryAfterSeconds(undefined), undefined);
    assert.equal(errors.parseRetryAfterSeconds(null), undefined);
    assert.equal(errors.parseRetryAfterSeconds(''), undefined);
    assert.equal(errors.parseRetryAfterSeconds('   '), undefined);
  });
});
