import { readSessionTimeouts, sessionCookieName, sessionCookieOptions } from './session-cookie';

describe('session-cookie', () => {
  const originalNodeEnv = process.env['NODE_ENV'];
  const originalIdle = process.env['SESSION_IDLE_TIMEOUT_SECONDS'];
  const originalAbsolute = process.env['SESSION_ABSOLUTE_TIMEOUT_SECONDS'];

  afterEach(() => {
    restore('NODE_ENV', originalNodeEnv);
    restore('SESSION_IDLE_TIMEOUT_SECONDS', originalIdle);
    restore('SESSION_ABSOLUTE_TIMEOUT_SECONDS', originalAbsolute);
  });

  describe('sessionCookieName', () => {
    it('uses the __Host- prefix in production', () => {
      process.env['NODE_ENV'] = 'production';
      expect(sessionCookieName()).toBe('__Host-portal_session');
    });

    it('drops the __Host- prefix outside production (dev HTTP server)', () => {
      process.env['NODE_ENV'] = 'development';
      expect(sessionCookieName()).toBe('portal_session');
    });
  });

  describe('sessionCookieOptions', () => {
    it('sets Secure only in production', () => {
      process.env['NODE_ENV'] = 'production';
      expect(sessionCookieOptions(1800).secure).toBe(true);
      process.env['NODE_ENV'] = 'development';
      expect(sessionCookieOptions(1800).secure).toBe(false);
    });

    it('converts the idle timeout into milliseconds', () => {
      expect(sessionCookieOptions(1800).maxAge).toBe(1_800_000);
    });

    it('pins httpOnly, sameSite=lax, and path=/', () => {
      const opts = sessionCookieOptions(1800);
      expect(opts.httpOnly).toBe(true);
      expect(opts.sameSite).toBe('lax');
      expect(opts.path).toBe('/');
    });
  });

  describe('readSessionTimeouts', () => {
    it('returns the ADR-0010 defaults when env vars are unset', () => {
      delete process.env['SESSION_IDLE_TIMEOUT_SECONDS'];
      delete process.env['SESSION_ABSOLUTE_TIMEOUT_SECONDS'];
      expect(readSessionTimeouts()).toEqual({ idleSeconds: 1800, absoluteSeconds: 43200 });
    });

    it('parses positive integer overrides', () => {
      process.env['SESSION_IDLE_TIMEOUT_SECONDS'] = '900';
      process.env['SESSION_ABSOLUTE_TIMEOUT_SECONDS'] = '7200';
      expect(readSessionTimeouts()).toEqual({ idleSeconds: 900, absoluteSeconds: 7200 });
    });

    it('rejects non-numeric values', () => {
      process.env['SESSION_IDLE_TIMEOUT_SECONDS'] = 'half-an-hour';
      expect(() => readSessionTimeouts()).toThrow(/must be a positive integer/);
    });

    it('rejects zero and negative values', () => {
      process.env['SESSION_IDLE_TIMEOUT_SECONDS'] = '0';
      expect(() => readSessionTimeouts()).toThrow(/must be a positive integer/);
      process.env['SESSION_IDLE_TIMEOUT_SECONDS'] = '-1';
      expect(() => readSessionTimeouts()).toThrow(/must be a positive integer/);
    });

    it('rejects fractional values', () => {
      process.env['SESSION_IDLE_TIMEOUT_SECONDS'] = '1800.5';
      expect(() => readSessionTimeouts()).toThrow(/must be a positive integer/);
    });
  });
});

function restore(name: string, value: string | undefined): void {
  if (value === undefined) {
    delete process.env[name];
  } else {
    process.env[name] = value;
  }
}
