/**
 * API smoke tests for UAT / production readiness.
 * Tests health, routing, and auth validation without requiring full DB/Redis in CI.
 *
 * Run: npm test -- smoke
 */

import request from 'supertest';

// Load app without starting server (server.ts is not imported)
// Suppress DB config console logs in test
const originalEnv = process.env.NODE_ENV;
process.env.NODE_ENV = process.env.NODE_ENV || 'test';

let app: import('express').Application;
beforeAll(() => {
  app = require('../../app').default;
});

afterAll(() => {
  process.env.NODE_ENV = originalEnv;
});

describe('API Smoke – Health & Routing', () => {
  it('SMK-01: GET /health returns 200 and status OK', async () => {
    const res = await request(app).get('/health');
    expect(res.status).toBe(200);
    expect(res.body).toHaveProperty('status', 'OK');
    expect(res.body).toHaveProperty('timestamp');
    expect(res.body).toHaveProperty('uptime');
  });

  it('SMK-02: GET /api/v1/health returns 200 and service name', async () => {
    const res = await request(app).get('/api/v1/health');
    expect(res.status).toBe(200);
    expect(res.body).toHaveProperty('status', 'OK');
    expect(res.body).toHaveProperty('service', 're-workflow-backend');
  });

  it('SMK-03: GET /api/v1/health/db returns 200 (connected) or 503 (disconnected)', async () => {
    const res = await request(app).get('/api/v1/health/db');
    expect([200, 503]).toContain(res.status);
    if (res.status === 200) {
      expect(res.body).toHaveProperty('database', 'connected');
    } else {
      expect(res.body).toHaveProperty('database', 'disconnected');
    }
  });

  it('SMK-04: Invalid API route returns 404 with JSON', async () => {
    const res = await request(app).get('/api/v1/invalid-route-xyz');
    expect(res.status).toBe(404);
    expect(res.body).toHaveProperty('success', false);
    expect(res.body).toHaveProperty('message');
  });
});

describe('API Smoke – Authentication', () => {
  it('AUTH-01: POST /api/v1/auth/sso-callback with empty body returns 400', async () => {
    const res = await request(app)
      .post('/api/v1/auth/sso-callback')
      .send({})
      .set('Content-Type', 'application/json');
    expect(res.status).toBe(400);
    expect(res.body).toHaveProperty('success', false);
    // Auth route validator returns "Request body validation failed"; legacy app route returns "email and oktaSub required"
    expect(res.body.message).toMatch(/email|oktaSub|required|validation failed/i);
  });

  it('AUTH-02: POST /api/v1/auth/sso-callback without oktaSub returns 400', async () => {
    const res = await request(app)
      .post('/api/v1/auth/sso-callback')
      .send({ email: 'test@example.com' })
      .set('Content-Type', 'application/json');
    expect(res.status).toBe(400);
    expect(res.body).toHaveProperty('success', false);
  });

  it('AUTH-03: POST /api/v1/auth/sso-callback without email returns 400', async () => {
    const res = await request(app)
      .post('/api/v1/auth/sso-callback')
      .send({ oktaSub: 'okta-123' })
      .set('Content-Type', 'application/json');
    expect(res.status).toBe(400);
    expect(res.body).toHaveProperty('success', false);
  });

  it('AUTH-04: GET /api/v1/users without token returns 401', async () => {
    const res = await request(app).get('/api/v1/users');
    expect(res.status).toBe(401);
  });

  it('AUTH-05: GET /api/v1/users with invalid token returns 401', async () => {
    const res = await request(app)
      .get('/api/v1/users')
      .set('Authorization', 'Bearer invalid-token');
    expect(res.status).toBe(401);
  });
});

describe('API Smoke – Security Headers (SEC-01, SEC-02, SEC-03)', () => {
  it('SEC-01: Response includes Content-Security-Policy header', async () => {
    const res = await request(app).get('/health');
    expect(res.status).toBe(200);
    expect(res.headers).toHaveProperty('content-security-policy');
    expect(res.headers['content-security-policy']).toBeTruthy();
  });

  it('SEC-02: Response includes X-Frame-Options (SAMEORIGIN or deny)', async () => {
    const res = await request(app).get('/health');
    expect(res.status).toBe(200);
    expect(res.headers).toHaveProperty('x-frame-options');
    expect(res.headers['x-frame-options'].toUpperCase()).toMatch(/SAMEORIGIN|DENY/);
  });

  it('SEC-03: GET /metrics without admin auth returns 401', async () => {
    const res = await request(app).get('/metrics');
    expect(res.status).toBe(401);
  });
});
