import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import http from 'node:http';
import { isMcplocalRunning } from './mcp-client.js';

const MCPLOCAL_URL = process.env['MCPLOCAL_URL'] ?? 'http://localhost:3200';

let available = false;

function fetchJson<T>(urlPath: string, method = 'GET', body?: unknown): Promise<T | null> {
  return new Promise((resolve) => {
    const payload = body !== undefined ? JSON.stringify(body) : undefined;
    const req = http.request(`${MCPLOCAL_URL}${urlPath}`, {
      method,
      timeout: 5000,
      headers: payload ? { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload) } : {},
    }, (res) => {
      const chunks: Buffer[] = [];
      res.on('data', (chunk: Buffer) => chunks.push(chunk));
      res.on('end', () => {
        try {
          resolve(JSON.parse(Buffer.concat(chunks).toString()) as T);
        } catch {
          resolve(null);
        }
      });
    });
    req.on('error', () => resolve(null));
    req.on('timeout', () => { req.destroy(); resolve(null); });
    if (payload) req.write(payload);
    req.end();
  });
}

beforeAll(async () => {
  available = await isMcplocalRunning();
});

afterAll(async () => {
  // Always ensure pause is off after tests
  if (available) {
    await fetchJson('/pause', 'PUT', { paused: false });
  }
});

describe('Pause Queue smoke tests', () => {
  describe('GET /pause', () => {
    it('returns pause state', async () => {
      if (!available) return;

      const state = await fetchJson<{ paused: boolean; queueSize: number }>('/pause');
      expect(state).not.toBeNull();
      expect(typeof state!.paused).toBe('boolean');
      expect(typeof state!.queueSize).toBe('number');
    });
  });

  describe('PUT /pause', () => {
    it('can enable and disable pause mode', async () => {
      if (!available) return;

      // Enable
      const on = await fetchJson<{ paused: boolean; queueSize: number }>('/pause', 'PUT', { paused: true });
      expect(on).not.toBeNull();
      expect(on!.paused).toBe(true);

      // Verify
      const state = await fetchJson<{ paused: boolean }>('/pause');
      expect(state!.paused).toBe(true);

      // Disable
      const off = await fetchJson<{ paused: boolean; queueSize: number }>('/pause', 'PUT', { paused: false });
      expect(off).not.toBeNull();
      expect(off!.paused).toBe(false);
    });

    it('rejects non-boolean paused value', async () => {
      if (!available) return;

      const result = await fetchJson<{ error: string }>('/pause', 'PUT', { paused: 'yes' });
      expect(result).not.toBeNull();
      expect(result!.error).toBeTruthy();
    });
  });

  describe('GET /pause/queue', () => {
    it('returns empty queue when not paused', async () => {
      if (!available) return;

      const result = await fetchJson<{ paused: boolean; items: unknown[] }>('/pause/queue');
      expect(result).not.toBeNull();
      expect(Array.isArray(result!.items)).toBe(true);
    });
  });

  describe('POST /pause/release-all', () => {
    it('returns released count', async () => {
      if (!available) return;

      const result = await fetchJson<{ released: number; queueSize: number }>('/pause/release-all', 'POST');
      expect(result).not.toBeNull();
      expect(typeof result!.released).toBe('number');
      expect(result!.queueSize).toBe(0);
    });
  });

  describe('POST /pause/queue/:id/release', () => {
    it('returns 404 for non-existent item', async () => {
      if (!available) return;

      const result = await fetchJson<{ error: string }>('/pause/queue/nonexistent/release', 'POST');
      expect(result).not.toBeNull();
      expect(result!.error).toMatch(/not found/i);
    });
  });

  describe('POST /pause/queue/:id/edit', () => {
    it('returns 404 for non-existent item', async () => {
      if (!available) return;

      const result = await fetchJson<{ error: string }>('/pause/queue/nonexistent/edit', 'POST', { content: 'test' });
      expect(result).not.toBeNull();
      expect(result!.error).toMatch(/not found/i);
    });

    it('rejects missing content', async () => {
      if (!available) return;

      const result = await fetchJson<{ error: string }>('/pause/queue/nonexistent/edit', 'POST', {});
      expect(result).not.toBeNull();
      expect(result!.error).toBeTruthy();
    });
  });

  describe('POST /pause/queue/:id/drop', () => {
    it('returns 404 for non-existent item', async () => {
      if (!available) return;

      const result = await fetchJson<{ error: string }>('/pause/queue/nonexistent/drop', 'POST');
      expect(result).not.toBeNull();
      expect(result!.error).toMatch(/not found/i);
    });
  });
});
