import { createHash } from 'node:crypto';

import { generatePkceChallenge, generatePkceVerifier } from './pkce-helpers';

/**
 * Task 3.1 — FAILING tests for the PKCE helper.
 *
 * Validates:
 *   - `code_challenge === BASE64URL(SHA256(code_verifier))` (RFC 7636 S256 algorithm).
 *   - Verifier is URL-safe (A-Z a-z 0-9 - _ . ~ per RFC 3986 unreserved chars + RFC 7636 §4.1).
 *   - Verifier is high-entropy (≥ 43 characters, RFC 7636 §4.1 minimum).
 *   - Each call generates a fresh verifier (randomness check).
 */
describe('PKCE helpers', () => {
  describe('generatePkceVerifier', () => {
    it('produces a string of at least 43 URL-safe characters', () => {
      const verifier = generatePkceVerifier();

      expect(typeof verifier).toBe('string');
      expect(verifier.length).toBeGreaterThanOrEqual(43);
    });

    it('contains only URL-safe characters (RFC 7636 §4.1 unreserved set)', () => {
      const verifier = generatePkceVerifier();

      // RFC 7636 §4.1 unreserved characters: A-Z / a-z / 0-9 / "-" / "." / "_" / "~"
      const urlSafePattern = /^[A-Za-z0-9\-._~]+$/;
      expect(verifier).toMatch(urlSafePattern);
    });

    it('generates a different verifier on each call (randomness)', () => {
      const v1 = generatePkceVerifier();
      const v2 = generatePkceVerifier();

      expect(v1).not.toBe(v2);
    });
  });

  describe('generatePkceChallenge', () => {
    it('produces BASE64URL(SHA256(code_verifier)) matching RFC 7636', () => {
      const verifier = 'dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk';

      const challenge = generatePkceChallenge(verifier);

      // Compute the expected value independently.
      const expected = createHash('sha256')
        .update(verifier)
        .digest('base64url');

      expect(challenge).toBe(expected);
    });

    it('produces different challenges for different verifiers', () => {
      const c1 = generatePkceChallenge('verifier-one');
      const c2 = generatePkceChallenge('verifier-two');

      expect(c1).not.toBe(c2);
    });

    it('challenge does not contain URL-unsafe characters (+, /, =)', () => {
      const verifier = generatePkceVerifier();

      const challenge = generatePkceChallenge(verifier);

      // base64url never contains + / or = (unlike standard base64).
      expect(challenge).not.toMatch(/[+/=]/);
    });
  });
});
