import { spawn } from "child_process";
import type { ChildProcess } from "child_process";
import { OpenAI } from "openai";

let serverProcess: ChildProcess | null = null;

const TEST_PORT = 18080;
const BASE_URL = `http://localhost:${TEST_PORT}/v1`;

export function getTestClient(): OpenAI {
  return new OpenAI({
    baseURL: BASE_URL,
    apiKey: "test-key",
    // Surface 429s immediately: the SDK's default retries honor the mock
    // server's retry-after header, which outlasts the test timeout.
    maxRetries: 0,
  });
}

export function getBaseUrl(): string {
  return `http://localhost:${TEST_PORT}`;
}

export async function startServer(
  env: Record<string, string> = {}
): Promise<void> {
  if (serverProcess) {
    await stopServer();
  }

  return new Promise((resolve, reject) => {
    // Default to fast mode (no delays) for tests unless overridden
    const fullEnv = {
      ...process.env,
      PORT: String(TEST_PORT),
      STREAM_INITIAL_DELAY_MS: "0",
      STREAM_DELAY_MS: "0",
      STREAM_JITTER_MS: "0",
      ...env,
    };

    serverProcess = spawn("npx", ["tsx", "src/server.ts"], {
      cwd: process.cwd(),
      env: fullEnv,
      stdio: ["pipe", "pipe", "pipe"],
    });

    let started = false;

    serverProcess.stdout?.on("data", (data: Buffer) => {
      const output = data.toString();
      // Look for the startup message
      if (output.includes("Mock LLM Server running") && !started) {
        started = true;
        // Give a moment for the server to be fully ready
        setTimeout(resolve, 100);
      }
    });

    serverProcess.stderr?.on("data", (data: Buffer) => {
      console.error("Server stderr:", data.toString());
    });

    serverProcess.on("error", (err) => {
      if (!started) {
        reject(err);
      }
    });

    serverProcess.on("exit", (code) => {
      if (!started && code !== 0) {
        reject(new Error(`Server exited with code ${code}`));
      }
    });

    // Timeout after 10 seconds
    setTimeout(() => {
      if (!started) {
        reject(new Error("Server failed to start within 10 seconds"));
      }
    }, 10000);
  });
}

export async function stopServer(): Promise<void> {
  if (serverProcess) {
    serverProcess.kill("SIGTERM");
    serverProcess = null;
    // Wait a bit for port to be released
    await new Promise((resolve) => setTimeout(resolve, 500));
  }
}

export async function resetRateLimit(): Promise<void> {
  const response = await fetch(
    `http://localhost:${TEST_PORT}/api/rate-limit/reset`,
    {
      method: "POST",
    }
  );
  if (!response.ok) {
    throw new Error("Failed to reset rate limit");
  }
}
