import { test, expect } from '@playwright/test';

const BASE = process.env.BASE_URL || 'https://marketing-stage-r4tfklscwq-uc.a.run.app';

const get = (path: string, headers: Record<string, string> = {}) =>
  fetch(`${BASE}${path}`, { headers });

// ── /api/health ───────────────────────────────────────────────────────────────

test('/api/health — returns 200 with status:ok', async () => {
  const r = await get('/api/health');
  expect(r.status).toBe(200);
  const body = await r.json() as Record<string, string>;
  expect(body.status).toBe('ok');
  expect(body.service).toBe('neuron-web');
});

test('/api/health — content-type is application/json', async () => {
  const r = await get('/api/health');
  expect(r.headers.get('content-type')).toContain('application/json');
});

// ── /api/founding-count ───────────────────────────────────────────────────────

test('/api/founding-count — returns numeric fields', async () => {
  const r = await get('/api/founding-count');
  expect(r.status).toBe(200);
  const body = await r.json() as Record<string, number>;
  expect(typeof body.sold).toBe('number');
  expect(typeof body.total).toBe('number');
  expect(typeof body.remaining).toBe('number');
  // Invariants
  expect(body.total).toBe(1000);
  expect(body.sold).toBeGreaterThanOrEqual(0);
  expect(body.remaining).toBe(body.total - body.sold);
});

// ── /api/supabase-config ──────────────────────────────────────────────────────
// Requires a permitted Origin. See security.test.ts for CORS tests.

test('/api/supabase-config — returns url and anon_key for allowed origin', async () => {
  const r = await get('/api/supabase-config', { Origin: 'https://neurontechnologies.ai' });
  expect(r.status).toBe(200);
  const body = await r.json() as Record<string, string>;
  expect(body.url).toMatch(/supabase\.co/);
  expect(typeof body.anon_key).toBe('string');
  expect(body.anon_key.length).toBeGreaterThan(20);
});

test('/api/supabase-config — anon_key is a valid JWT shape', async () => {
  const r = await get('/api/supabase-config', { Origin: 'https://neurontechnologies.ai' });
  const body = await r.json() as Record<string, string>;
  // Supabase anon key is a JWT: three base64 segments separated by dots
  const parts = body.anon_key.split('.');
  expect(parts).toHaveLength(3);
});

// ── /sitemap.xml ──────────────────────────────────────────────────────────────

test('/sitemap.xml — returns valid XML with production URLs', async () => {
  const r = await get('/sitemap.xml');
  expect(r.status).toBe(200);
  expect(r.headers.get('content-type')).toContain('xml');
  const text = await r.text();
  expect(text).toContain('<urlset');
  expect(text).toContain('neurontechnologies.ai');
  // Must not leak stage URL
  expect(text).not.toContain('run.app');
  expect(text).not.toContain('stage');
});

test('/sitemap.xml — includes all major pages', async () => {
  const r = await get('/sitemap.xml');
  const text = await r.text();
  expect(text).toContain('neurontechnologies.ai/');
  expect(text).toContain('neurontechnologies.ai/about');
  expect(text).toContain('neurontechnologies.ai/legal/terms');
  expect(text).toContain('neurontechnologies.ai/legal/enterprise-terms');
});

// ── /robots.txt ───────────────────────────────────────────────────────────────

test('/robots.txt — accessible with correct directives', async () => {
  const r = await get('/robots.txt');
  expect(r.status).toBe(200);
  const text = await r.text();
  expect(text).toContain('User-agent');
  // Private paths are disallowed
  expect(text).toContain('Disallow: /checkout');
  expect(text).toContain('Disallow: /account');
  expect(text).toContain('Disallow: /api/');
  // Sitemap link points to production
  expect(text).toContain('Sitemap: https://neurontechnologies.ai/sitemap.xml');
});

// ── /llms.txt ─────────────────────────────────────────────────────────────────

test('/llms.txt — accessible', async () => {
  const r = await get('/llms.txt');
  expect(r.status).toBe(200);
  const text = await r.text();
  expect(text.length).toBeGreaterThan(0);
});

// ── 404 handling ─────────────────────────────────────────────────────────────

test('Unknown route returns 404', async () => {
  const r = await get('/this-route-xyz-does-not-exist-abc123');
  expect(r.status).toBe(404);
});

// ── /api/webhooks/stripe — POST-only, requires valid signature ────────────────

test('/api/webhooks/stripe — rejects missing Stripe-Signature with 400', async () => {
  const r = await fetch(`${BASE}/api/webhooks/stripe`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ type: 'payment_intent.succeeded' }),
  });
  expect(r.status).toBe(400);
});

// ── /api/demo — POST only, auth-gated ────────────────────────────────────────

test('/api/demo — missing access_token returns auth_required', async () => {
  const r = await fetch(`${BASE}/api/demo`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ message: 'hello' }),
  });
  const body = await r.json() as Record<string, unknown>;
  expect(body.auth_required).toBe(true);
});

// ── /api/soul-health — internal gate ─────────────────────────────────────────
// The probe responses embedded in the JSON body may contain literal newlines
// (control characters), so we test via text matching, not JSON.parse.

test('/api/soul-health — 404 without X-Internal header', async () => {
  const r = await get('/api/soul-health');
  expect(r.status).toBe(404);
});

test('/api/soul-health — 200 with X-Internal: true, body contains soul_url', async () => {
  const r = await get('/api/soul-health', { 'X-Internal': 'true' });
  expect(r.status).toBe(200);
  const text = await r.text();
  expect(text).toContain('"soul_url"');
  expect(text).toMatch(/soul_url.*https?:\/\//);
});
