/**
 * CLI-Server Integration Tests
 *
 * Tests the full flow: start server, call tRPC from client, verify response.
 * These are INTEGRATION tests, not unit tests - they test the full stack.
 */

import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import { CoordinationServer } from '../../apps/server/server/index.js';
import { ProcessManager, ProcessRegistry } from '../../apps/server/process/index.js';
import { LogManager } from '../../apps/server/logging/index.js';
import { createEventBus } from '../../apps/server/events/index.js';
import { createTrpcClient } from '../../apps/server/cli/trpc-client.js';
import type { TrpcClient } from '../../apps/server/cli/trpc-client.js';

describe('CLI-Server Integration', () => {
  let server: CoordinationServer;
  let client: TrpcClient;
  let testPort: number;

  beforeAll(async () => {
    // Use a random port to avoid conflicts
    testPort = 30000 + Math.floor(Math.random() * 10000);

    // Create dependencies
    const registry = new ProcessRegistry();
    const processManager = new ProcessManager(registry);
    const logManager = new LogManager();
    const eventBus = createEventBus();

    // Create and start server
    server = new CoordinationServer(
      {
        port: testPort,
        pidFile: `/tmp/cw-test-${testPort}.pid`,
      },
      processManager,
      logManager,
      eventBus
    );

    await server.start();

    // Create client pointing to test server
    client = createTrpcClient(testPort);
  });

  afterAll(async () => {
    await server.stop();
  });

  describe('health procedure', () => {
    it('should return health status with correct fields', async () => {
      const result = await client.health.query();

      expect(result).toHaveProperty('status', 'ok');
      expect(result).toHaveProperty('uptime');
      expect(result).toHaveProperty('processCount');
      expect(typeof result.uptime).toBe('number');
      expect(typeof result.processCount).toBe('number');
    });

    it('should return increasing uptime on subsequent calls', async () => {
      const first = await client.health.query();

      // Wait a small amount
      await new Promise((resolve) => setTimeout(resolve, 50));

      const second = await client.health.query();

      expect(second.uptime).toBeGreaterThanOrEqual(first.uptime);
    });

    it('should return processCount of 0 initially', async () => {
      const result = await client.health.query();
      expect(result.processCount).toBe(0);
    });
  });

  describe('status procedure', () => {
    it('should return server info with correct structure', async () => {
      const result = await client.status.query();

      expect(result).toHaveProperty('server');
      expect(result).toHaveProperty('processes');
      expect(Array.isArray(result.processes)).toBe(true);
    });

    it('should return server details with startedAt, uptime, and pid', async () => {
      const result = await client.status.query();

      expect(result.server).toHaveProperty('startedAt');
      expect(result.server).toHaveProperty('uptime');
      expect(result.server).toHaveProperty('pid');

      // startedAt should be an ISO string
      expect(typeof result.server.startedAt).toBe('string');
      expect(() => new Date(result.server.startedAt)).not.toThrow();

      // uptime should be a non-negative number
      expect(typeof result.server.uptime).toBe('number');
      expect(result.server.uptime).toBeGreaterThanOrEqual(0);

      // pid should be a positive integer
      expect(typeof result.server.pid).toBe('number');
      expect(result.server.pid).toBeGreaterThan(0);
    });

    it('should return empty processes array initially', async () => {
      const result = await client.status.query();
      expect(result.processes).toEqual([]);
    });
  });

  describe('error handling', () => {
    it('should throw when server is not running', async () => {
      // Create client pointing to wrong port
      const badClient = createTrpcClient(testPort + 1);

      await expect(badClient.health.query()).rejects.toThrow();
    });
  });
});
