/**
 * Security Headers Enforcement Tests
 *
 * Tests that verify security headers are properly set on responses.
 *
 * NOTE: Security headers are applied at Caddy layer. These tests verify
 * the expected headers through the API proxy.
 *
 * @see /projects/Charon/docs/plans/current_spec.md - Security Headers Enforcement Tests
 */

import { test, expect } from '@bgotink/playwright-coverage';
import { request } from '@playwright/test';
import type { APIRequestContext } from '@playwright/test';
import { STORAGE_STATE } from '../constants';

test.describe('Security Headers Enforcement', () => {
  let requestContext: APIRequestContext;

  test.beforeAll(async () => {
    requestContext = await request.newContext({
      baseURL: process.env.PLAYWRIGHT_BASE_URL || 'http://localhost:8080',
      storageState: STORAGE_STATE,
    });
  });

  test.afterAll(async () => {
    await requestContext.dispose();
  });

  test('should return X-Content-Type-Options header', async () => {
    const response = await requestContext.get('/api/v1/health');
    expect(response.ok()).toBe(true);

    // X-Content-Type-Options should be 'nosniff'
    const header = response.headers()['x-content-type-options'];
    if (header) {
      expect(header).toBe('nosniff');
    } else {
      // If backend doesn't set it, Caddy should when configured
      console.log(
        'X-Content-Type-Options not set directly (may be set at Caddy layer)'
      );
    }
  });

  test('should return X-Frame-Options header', async () => {
    const response = await requestContext.get('/api/v1/health');
    expect(response.ok()).toBe(true);

    // X-Frame-Options should be 'DENY' or 'SAMEORIGIN'
    const header = response.headers()['x-frame-options'];
    if (header) {
      expect(['DENY', 'SAMEORIGIN', 'deny', 'sameorigin']).toContain(header);
    } else {
      // If backend doesn't set it, Caddy should when configured
      console.log(
        'X-Frame-Options not set directly (may be set at Caddy layer)'
      );
    }
  });

  test('should document HSTS behavior on HTTPS', async () => {
    // HSTS (Strict-Transport-Security) is only set on HTTPS responses
    // In test environment, we typically use HTTP
    //
    // Expected header on HTTPS:
    //   Strict-Transport-Security: max-age=31536000; includeSubDomains
    //
    // This test verifies HSTS is not incorrectly set on HTTP

    const response = await requestContext.get('/api/v1/health');
    expect(response.ok()).toBe(true);

    const hsts = response.headers()['strict-transport-security'];

    // On HTTP, HSTS should not be present (browsers ignore it anyway)
    if (process.env.PLAYWRIGHT_BASE_URL?.startsWith('https://')) {
      expect(hsts).toBeDefined();
      expect(hsts).toContain('max-age');
    } else {
      // HTTP is fine without HSTS in test env
      console.log('HSTS not present on HTTP (expected behavior)');
    }
  });

  test('should verify Content-Security-Policy when configured', async () => {
    // CSP is optional and configured per-host
    // This test verifies CSP header handling when present

    const response = await requestContext.get('/');
    // May be 200 or redirect
    expect(response.status()).toBeLessThan(500);

    const csp = response.headers()['content-security-policy'];
    if (csp) {
      // CSP should contain valid directives
      expect(
        csp.includes("default-src") ||
          csp.includes("script-src") ||
          csp.includes("style-src")
      ).toBe(true);
    } else {
      // CSP is optional - document its behavior when configured
      console.log('CSP not configured (optional - set per proxy host)');
    }
  });
});
