/**
 * DevKit API Tests
 * 
 * Tests for the dev-only API namespace
 */

import { describe, it, expect, beforeAll, afterAll } from '@jest/globals';
import { createLogger } from '@4runr/shared';

// Mock environment to enable DevKit
process.env.NODE_ENV = 'development';
process.env.DEVKIT_ENABLED = 'true';
process.env.DEV_MODE = 'true';
process.env.AUTH_ENABLED = 'false'; // Disable auth for easier testing
process.env.GATEWAY_PERSISTENCE = 'memory';

const logger = createLogger('DevKitAPITest');

describe('DevKit API', () => {
  const GATEWAY_URL = process.env.GATEWAY_URL || 'http://localhost:3000';

  describe('Access Control', () => {
    it('should allow access when DEVKIT_ENABLED=true and NODE_ENV=development', async () => {
      const response = await fetch(`${GATEWAY_URL}/devkit/api/status`);
      
      // Should not be 404/403
      expect(response.status).not.toBe(404);
      expect(response.status).not.toBe(403);
    });

    it('should return valid JSON from /devkit/api/status', async () => {
      const response = await fetch(`${GATEWAY_URL}/devkit/api/status`);
      const data = await response.json();
      
      expect(data).toHaveProperty('gateway');
      expect(data).toHaveProperty('database');
      expect(data).toHaveProperty('redis');
      expect(data).toHaveProperty('sentinel');
      expect(data).toHaveProperty('auth');
      expect(data).toHaveProperty('rateLimit');
      expect(data).toHaveProperty('devkit');
    });
  });

  describe('GET /devkit/api/status', () => {
    it('should return system status', async () => {
      const response = await fetch(`${GATEWAY_URL}/devkit/api/status`);
      const data = await response.json();
      
      expect(response.status).toBe(200);
      expect(data.gateway).toHaveProperty('version');
      expect(data.gateway).toHaveProperty('status');
      expect(data.gateway).toHaveProperty('uptime');
      expect(data.gateway).toHaveProperty('timestamp');
      expect(typeof data.gateway.uptime).toBe('number');
    });

    it('should include database status', async () => {
      const response = await fetch(`${GATEWAY_URL}/devkit/api/status`);
      const data = await response.json();
      
      expect(data.database).toHaveProperty('status');
      expect(data.database).toHaveProperty('latencyMs');
      expect(data.database).toHaveProperty('mode');
      expect(['up', 'down', 'degraded', 'unknown']).toContain(data.database.status);
    });

    it('should include Redis status', async () => {
      const response = await fetch(`${GATEWAY_URL}/devkit/api/status`);
      const data = await response.json();
      
      expect(data.redis).toHaveProperty('status');
      expect(data.redis).toHaveProperty('latencyMs');
      expect(['up', 'down', 'degraded', 'unknown']).toContain(data.redis.status);
    });

    it('should include Sentinel status', async () => {
      const response = await fetch(`${GATEWAY_URL}/devkit/api/status`);
      const data = await response.json();
      
      expect(data.sentinel).toHaveProperty('enabled');
      expect(data.sentinel).toHaveProperty('mode');
      expect(data.sentinel).toHaveProperty('shieldMode');
      expect(typeof data.sentinel.enabled).toBe('boolean');
    });

    it('should include auth configuration', async () => {
      const response = await fetch(`${GATEWAY_URL}/devkit/api/status`);
      const data = await response.json();
      
      expect(data.auth).toHaveProperty('enabled');
      expect(data.auth).toHaveProperty('mode');
      expect(typeof data.auth.enabled).toBe('boolean');
      expect(['api_key', 'jwt', 'mixed', 'unknown']).toContain(data.auth.mode);
    });

    it('should include rate limit configuration', async () => {
      const response = await fetch(`${GATEWAY_URL}/devkit/api/status`);
      const data = await response.json();
      
      expect(data.rateLimit).toHaveProperty('enabled');
      expect(data.rateLimit).toHaveProperty('max');
      expect(data.rateLimit).toHaveProperty('windowMs');
      expect(typeof data.rateLimit.enabled).toBe('boolean');
    });

    it('should include DevKit status', async () => {
      const response = await fetch(`${GATEWAY_URL}/devkit/api/status`);
      const data = await response.json();
      
      expect(data.devkit).toHaveProperty('enabled');
      expect(data.devkit).toHaveProperty('env');
      expect(data.devkit).toHaveProperty('devMode');
      expect(data.devkit.enabled).toBe(true); // Should be true in tests
      expect(data.devkit.env).toBe('development');
    });
  });

  describe('GET /devkit/api/config', () => {
    it('should return non-sensitive configuration', async () => {
      const response = await fetch(`${GATEWAY_URL}/devkit/api/config`);
      const data = await response.json();
      
      expect(response.status).toBe(200);
      expect(data).toHaveProperty('environment');
      expect(data).toHaveProperty('server');
      expect(data).toHaveProperty('persistence');
      expect(data).toHaveProperty('auth');
      expect(data).toHaveProperty('rateLimit');
      expect(data).toHaveProperty('sentinel');
    });

    it('should include environment configuration', async () => {
      const response = await fetch(`${GATEWAY_URL}/devkit/api/config`);
      const data = await response.json();
      
      expect(data.environment).toHaveProperty('NODE_ENV');
      expect(data.environment).toHaveProperty('DEV_MODE');
      expect(data.environment).toHaveProperty('DEVKIT_ENABLED');
      expect(data.environment.NODE_ENV).toBe('development');
    });

    it('should NOT expose sensitive secrets', async () => {
      const response = await fetch(`${GATEWAY_URL}/devkit/api/config`);
      const data = await response.json();
      const configStr = JSON.stringify(data);
      
      // Should not contain any DATABASE_URL, password, secret, or key values
      expect(configStr).not.toMatch(/postgresql:\/\//i);
      expect(configStr).not.toMatch(/password/i);
      expect(configStr).not.toMatch(/secret/i);
      expect(configStr).not.toMatch(/jwt_secret/i);
      expect(configStr).not.toMatch(/encryption_key/i);
      
      // But should indicate if they're configured
      expect(data.persistence).toHaveProperty('databaseConfigured');
      expect(data.persistence).toHaveProperty('redisConfigured');
    });

    it('should include persistence configuration', async () => {
      const response = await fetch(`${GATEWAY_URL}/devkit/api/config`);
      const data = await response.json();
      
      expect(data.persistence).toHaveProperty('mode');
      expect(['memory', 'persistent', 'postgres']).toContain(data.persistence.mode);
    });

    it('should include Sentinel configuration', async () => {
      const response = await fetch(`${GATEWAY_URL}/devkit/api/config`);
      const data = await response.json();
      
      expect(data.sentinel).toHaveProperty('enabled');
      expect(data.sentinel).toHaveProperty('mode');
      expect(data.sentinel).toHaveProperty('shieldMode');
      expect(data.sentinel).toHaveProperty('tokenCap');
      expect(data.sentinel).toHaveProperty('maxTokens');
    });

    it('should include metrics configuration', async () => {
      const response = await fetch(`${GATEWAY_URL}/devkit/api/config`);
      const data = await response.json();
      
      expect(data.metrics).toHaveProperty('enabled');
      expect(data.metrics).toHaveProperty('port');
      expect(data.metrics).toHaveProperty('path');
    });
  });

  describe('GET /devkit/api/metrics/summary', () => {
    it('should return parsed metrics summary', async () => {
      const response = await fetch(`${GATEWAY_URL}/devkit/api/metrics/summary`);
      const data = await response.json();
      
      expect(response.status).toBe(200);
      expect(data).toHaveProperty('timestamp');
      expect(data).toHaveProperty('metrics');
    });

    it('should include HTTP metrics', async () => {
      const response = await fetch(`${GATEWAY_URL}/devkit/api/metrics/summary`);
      const data = await response.json();
      
      expect(data.metrics).toHaveProperty('http');
      expect(data.metrics.http).toHaveProperty('requestsTotal');
      expect(data.metrics.http).toHaveProperty('errorsTotal');
      expect(typeof data.metrics.http.requestsTotal).toBe('number');
    });

    it('should include runs metrics', async () => {
      const response = await fetch(`${GATEWAY_URL}/devkit/api/metrics/summary`);
      const data = await response.json();
      
      expect(data.metrics).toHaveProperty('runs');
      expect(data.metrics.runs).toHaveProperty('created');
      expect(data.metrics.runs).toHaveProperty('started');
      expect(data.metrics.runs).toHaveProperty('completed');
      expect(data.metrics.runs).toHaveProperty('active');
    });

    it('should include queue metrics', async () => {
      const response = await fetch(`${GATEWAY_URL}/devkit/api/metrics/summary`);
      const data = await response.json();
      
      expect(data.metrics).toHaveProperty('queue');
      expect(data.metrics.queue).toHaveProperty('jobsQueued');
      expect(data.metrics.queue).toHaveProperty('jobsCompleted');
      expect(data.metrics.queue).toHaveProperty('jobsFailed');
    });
  });

  describe('GET /devkit/api/health', () => {
    it('should return detailed health checks', async () => {
      const response = await fetch(`${GATEWAY_URL}/devkit/api/health`);
      const data = await response.json();
      
      expect(response.status).toBe(200);
      expect(data).toHaveProperty('status');
      expect(data).toHaveProperty('timestamp');
      expect(data).toHaveProperty('checks');
      expect(['healthy', 'degraded', 'unhealthy']).toContain(data.status);
    });

    it('should include database health check', async () => {
      const response = await fetch(`${GATEWAY_URL}/devkit/api/health`);
      const data = await response.json();
      
      expect(data.checks).toHaveProperty('database');
      expect(data.checks.database).toHaveProperty('status');
    });

    it('should include Redis health check', async () => {
      const response = await fetch(`${GATEWAY_URL}/devkit/api/health`);
      const data = await response.json();
      
      expect(data.checks).toHaveProperty('redis');
      expect(data.checks.redis).toHaveProperty('status');
    });

    it('should include queue health check', async () => {
      const response = await fetch(`${GATEWAY_URL}/devkit/api/health`);
      const data = await response.json();
      
      expect(data.checks).toHaveProperty('queue');
      expect(data.checks.queue).toHaveProperty('status');
    });
  });
});

