import { afterEach, beforeEach, describe, expect, it } from 'bun:test';
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import getPort from 'get-port';
import {
  getOpenAICompatProxyStatus,
  listOpenAICompatProxyStatuses,
  startOpenAICompatProxy,
  stopOpenAICompatProxy,
} from '../../../src/proxy/proxy-daemon';
import { resolveOpenAICompatProxyPreferredPort } from '../../../src/proxy/proxy-port-resolver';
import { resolveOpenAICompatProfileConfig } from '../../../src/proxy/profile-router';
import {
  getLegacyOpenAICompatProxyPidPath,
  getLegacyOpenAICompatProxySessionPath,
  getOpenAICompatProxyPidPath,
  getOpenAICompatProxySessionPath,
} from '../../../src/proxy/proxy-daemon-paths';
import { mutateUnifiedConfig } from '../../../src/config/unified-config-loader';

let originalCcsHome: string | undefined;
let tempDir: string;

beforeEach(() => {
  originalCcsHome = process.env.CCS_HOME;
  tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ccs-openai-proxy-'));
  process.env.CCS_HOME = tempDir;
});

afterEach(async () => {
  await stopOpenAICompatProxy();
  if (originalCcsHome !== undefined) {
    process.env.CCS_HOME = originalCcsHome;
  } else {
    delete process.env.CCS_HOME;
  }
  fs.rmSync(tempDir, { recursive: true, force: true });
});

describe('openai proxy daemon lifecycle', () => {
  it('starts, reports status, serves health/models, and stops', async () => {
    const port = await getPort();
    const settingsPath = path.join(tempDir, 'hf.settings.json');
    fs.writeFileSync(
      settingsPath,
      JSON.stringify({
        env: {
          ANTHROPIC_BASE_URL: 'http://127.0.0.1:11434',
          ANTHROPIC_AUTH_TOKEN: 'ollama',
          ANTHROPIC_MODEL: 'qwen3-coder',
          CCS_DROID_PROVIDER: 'generic-chat-completion-api',
        },
      }),
      'utf8'
    );

    const profile = resolveOpenAICompatProfileConfig('hf', settingsPath, {
      ANTHROPIC_BASE_URL: 'http://127.0.0.1:11434',
      ANTHROPIC_AUTH_TOKEN: 'ollama',
      ANTHROPIC_MODEL: 'qwen3-coder',
      CCS_DROID_PROVIDER: 'generic-chat-completion-api',
    });
    if (!profile) {
      throw new Error('Expected an OpenAI-compatible profile');
    }

    const started = await startOpenAICompatProxy(profile, { port });
    expect(started.success).toBe(true);
    expect(started.authToken).toBeTruthy();

    const status = await getOpenAICompatProxyStatus();
    expect(status.running).toBe(true);
    expect(status.profileName).toBe('hf');
    expect(status.authToken).toBe(started.authToken);

    const health = await fetch(`http://127.0.0.1:${port}/health`);
    expect(health.status).toBe(200);

    const models = (await (
      await fetch(`http://127.0.0.1:${port}/v1/models`, {
        headers: { 'x-api-key': started.authToken! },
      })
    ).json()) as { data?: Array<{ id: string }> };
    expect(models.data?.map((entry) => entry.id)).toEqual(['qwen3-coder']);

    const headRoot = await fetch(`http://127.0.0.1:${port}/`, { method: 'HEAD' });
    expect(headRoot.status).toBe(200);
    expect(headRoot.headers.get('content-type')).toBe('application/json');
    expect(await headRoot.text()).toBe('');

    const headHealth = await fetch(`http://127.0.0.1:${port}/health`, { method: 'HEAD' });
    expect(headHealth.status).toBe(200);
    expect(headHealth.headers.get('content-type')).toBe('application/json');
    expect(await headHealth.text()).toBe('');

    const stopped = await stopOpenAICompatProxy();
    expect(stopped.success).toBe(true);
    expect((await getOpenAICompatProxyStatus()).running).toBe(false);
  }, 35000);

  it('allows different profiles to run on different ports', async () => {
    const firstPort = await getPort();
    const firstSettingsPath = path.join(tempDir, 'hf.settings.json');
    fs.writeFileSync(
      firstSettingsPath,
      JSON.stringify({
        env: {
          ANTHROPIC_BASE_URL: 'http://127.0.0.1:11434',
          ANTHROPIC_AUTH_TOKEN: 'ollama',
          ANTHROPIC_MODEL: 'qwen3-coder',
          CCS_DROID_PROVIDER: 'generic-chat-completion-api',
        },
      }),
      'utf8'
    );
    const firstProfile = resolveOpenAICompatProfileConfig('hf', firstSettingsPath, {
      ANTHROPIC_BASE_URL: 'http://127.0.0.1:11434',
      ANTHROPIC_AUTH_TOKEN: 'ollama',
      ANTHROPIC_MODEL: 'qwen3-coder',
      CCS_DROID_PROVIDER: 'generic-chat-completion-api',
    });
    if (!firstProfile) {
      throw new Error('Expected first OpenAI-compatible profile');
    }

    const firstStart = await startOpenAICompatProxy(firstProfile, { port: firstPort });
    expect(firstStart.success).toBe(true);

    const secondPort = await getPort();
    const secondSettingsPath = path.join(tempDir, 'openai.settings.json');
    fs.writeFileSync(
      secondSettingsPath,
      JSON.stringify({
        env: {
          ANTHROPIC_BASE_URL: 'https://api.openai.com/v1',
          ANTHROPIC_AUTH_TOKEN: 'sk-openai',
          ANTHROPIC_MODEL: 'gpt-4.1',
        },
      }),
      'utf8'
    );
    const secondProfile = resolveOpenAICompatProfileConfig('openai', secondSettingsPath, {
      ANTHROPIC_BASE_URL: 'https://api.openai.com/v1',
      ANTHROPIC_AUTH_TOKEN: 'sk-openai',
      ANTHROPIC_MODEL: 'gpt-4.1',
    });
    if (!secondProfile) {
      throw new Error('Expected second OpenAI-compatible profile');
    }

    const secondStart = await startOpenAICompatProxy(secondProfile, { port: secondPort });
    expect(secondStart.success).toBe(true);
    expect(secondStart.port).toBe(secondPort);

    const health = await fetch(`http://127.0.0.1:${firstPort}/health`);
    expect(health.status).toBe(200);

    const secondHealth = await fetch(`http://127.0.0.1:${secondPort}/health`);
    expect(secondHealth.status).toBe(200);
  });

  it('uses an adaptive implicit port instead of defaulting to 3456 for shared defaults', async () => {
    const settingsPath = path.join(tempDir, 'adaptive-default.settings.json');
    fs.writeFileSync(
      settingsPath,
      JSON.stringify({
        env: {
          ANTHROPIC_BASE_URL: 'https://api.openai.com/v1',
          ANTHROPIC_AUTH_TOKEN: 'sk-adaptive-default',
          ANTHROPIC_MODEL: 'gpt-4.1',
        },
      }),
      'utf8'
    );

    const profile = resolveOpenAICompatProfileConfig('adaptive-default', settingsPath, {
      ANTHROPIC_BASE_URL: 'https://api.openai.com/v1',
      ANTHROPIC_AUTH_TOKEN: 'sk-adaptive-default',
      ANTHROPIC_MODEL: 'gpt-4.1',
    });
    if (!profile) {
      throw new Error('Expected adaptive-default OpenAI-compatible profile');
    }

    const started = await startOpenAICompatProxy(profile);
    expect(started.success).toBe(true);
    expect(started.port).not.toBe(3456);
  });

  it('keeps a legacy singleton daemon visible across upgrade', async () => {
    const port = await getPort();
    const settingsPath = path.join(tempDir, 'legacy.settings.json');
    fs.writeFileSync(
      settingsPath,
      JSON.stringify({
        env: {
          ANTHROPIC_BASE_URL: 'http://127.0.0.1:11434',
          ANTHROPIC_AUTH_TOKEN: 'ollama-legacy',
          ANTHROPIC_MODEL: 'qwen3-coder',
          CCS_DROID_PROVIDER: 'generic-chat-completion-api',
        },
      }),
      'utf8'
    );

    const profile = resolveOpenAICompatProfileConfig('legacy', settingsPath, {
      ANTHROPIC_BASE_URL: 'http://127.0.0.1:11434',
      ANTHROPIC_AUTH_TOKEN: 'ollama-legacy',
      ANTHROPIC_MODEL: 'qwen3-coder',
      CCS_DROID_PROVIDER: 'generic-chat-completion-api',
    });
    if (!profile) {
      throw new Error('Expected a legacy OpenAI-compatible profile');
    }

    const started = await startOpenAICompatProxy(profile, { port });
    expect(started.success).toBe(true);
    expect(started.pid).toBeDefined();

    const proxyDir = path.dirname(getLegacyOpenAICompatProxyPidPath());
    fs.writeFileSync(getLegacyOpenAICompatProxyPidPath(), String(started.pid), 'utf8');
    fs.writeFileSync(
      getLegacyOpenAICompatProxySessionPath(),
      JSON.stringify(
        {
          profileName: profile.profileName,
          settingsPath: profile.settingsPath,
          host: '127.0.0.1',
          port,
          baseUrl: profile.baseUrl,
          authToken: started.authToken,
          model: profile.model,
        },
        null,
        2
      ) + '\n',
      'utf8'
    );
    fs.rmSync(path.join(proxyDir, 'legacy.daemon.pid'), { force: true });
    fs.rmSync(path.join(proxyDir, 'legacy.session.json'), { force: true });

    const status = await getOpenAICompatProxyStatus('legacy');
    expect(status.running).toBe(true);
    expect(status.port).toBe(port);

    const restarted = await startOpenAICompatProxy(profile);
    expect(restarted.success).toBe(true);
    expect(restarted.alreadyRunning).toBe(true);
    expect(restarted.port).toBe(port);

    const stopped = await stopOpenAICompatProxy('legacy');
    expect(stopped.success).toBe(true);
    expect(fs.existsSync(getLegacyOpenAICompatProxyPidPath())).toBe(false);
    expect(fs.existsSync(getLegacyOpenAICompatProxySessionPath())).toBe(false);
  }, 35000);

  it('fails when an explicit port is already occupied', async () => {
    const server = Bun.serve({
      port: 0,
      hostname: '127.0.0.1',
      fetch: () => new Response('busy'),
    });
    const occupiedPort = server.port;

    try {
      const settingsPath = path.join(tempDir, 'occupied-explicit.settings.json');
      fs.writeFileSync(
        settingsPath,
        JSON.stringify({
          env: {
            ANTHROPIC_BASE_URL: 'http://127.0.0.1:11434',
            ANTHROPIC_AUTH_TOKEN: 'ollama-explicit',
            ANTHROPIC_MODEL: 'qwen3-coder',
            CCS_DROID_PROVIDER: 'generic-chat-completion-api',
          },
        }),
        'utf8'
      );

      const profile = resolveOpenAICompatProfileConfig('explicit', settingsPath, {
        ANTHROPIC_BASE_URL: 'http://127.0.0.1:11434',
        ANTHROPIC_AUTH_TOKEN: 'ollama-explicit',
        ANTHROPIC_MODEL: 'qwen3-coder',
        CCS_DROID_PROVIDER: 'generic-chat-completion-api',
      });
      if (!profile) {
        throw new Error('Expected an explicit-port OpenAI-compatible profile');
      }

      const started = await startOpenAICompatProxy(profile, { port: occupiedPort });
      expect(started.success).toBe(false);
      expect(started.port).toBe(occupiedPort);
      expect(started.error).toContain(`Requested proxy port ${occupiedPort} is already in use`);
    } finally {
      server.stop(true);
    }
  });

  it('fails when a configured profile port is already occupied', async () => {
    const server = Bun.serve({
      port: 0,
      hostname: '127.0.0.1',
      fetch: () => new Response('busy'),
    });
    const occupiedPort = server.port;

    try {
      mutateUnifiedConfig((config) => {
        config.proxy = {
          ...(config.proxy ?? {}),
          profile_ports: { mapped: occupiedPort },
        };
      });

      const settingsPath = path.join(tempDir, 'occupied-mapped.settings.json');
      fs.writeFileSync(
        settingsPath,
        JSON.stringify({
          env: {
            ANTHROPIC_BASE_URL: 'http://127.0.0.1:11434',
            ANTHROPIC_AUTH_TOKEN: 'ollama-mapped',
            ANTHROPIC_MODEL: 'qwen3-coder',
            CCS_DROID_PROVIDER: 'generic-chat-completion-api',
          },
        }),
        'utf8'
      );

      const profile = resolveOpenAICompatProfileConfig('mapped', settingsPath, {
        ANTHROPIC_BASE_URL: 'http://127.0.0.1:11434',
        ANTHROPIC_AUTH_TOKEN: 'ollama-mapped',
        ANTHROPIC_MODEL: 'qwen3-coder',
        CCS_DROID_PROVIDER: 'generic-chat-completion-api',
      });
      if (!profile) {
        throw new Error('Expected a mapped-port OpenAI-compatible profile');
      }

      const started = await startOpenAICompatProxy(profile);
      expect(started.success).toBe(false);
      expect(started.port).toBe(occupiedPort);
      expect(started.error).toContain(`Requested proxy port ${occupiedPort} is already in use`);
    } finally {
      server.stop(true);
    }
  });

  it('falls back when a configured shared proxy.port is occupied', async () => {
    const server = Bun.serve({
      port: 0,
      hostname: '127.0.0.1',
      fetch: () => new Response('busy'),
    });
    const occupiedPort = server.port;

    try {
      mutateUnifiedConfig((config) => {
        config.proxy = {
          ...(config.proxy ?? {}),
          port: occupiedPort,
        };
      });

      const settingsPath = path.join(tempDir, 'shared-port.settings.json');
      fs.writeFileSync(
        settingsPath,
        JSON.stringify({
          env: {
            ANTHROPIC_BASE_URL: 'http://127.0.0.1:11434',
            ANTHROPIC_AUTH_TOKEN: 'ollama-shared-port',
            ANTHROPIC_MODEL: 'qwen3-coder',
            CCS_DROID_PROVIDER: 'generic-chat-completion-api',
          },
        }),
        'utf8'
      );

      const profile = resolveOpenAICompatProfileConfig('shared-port', settingsPath, {
        ANTHROPIC_BASE_URL: 'http://127.0.0.1:11434',
        ANTHROPIC_AUTH_TOKEN: 'ollama-shared-port',
        ANTHROPIC_MODEL: 'qwen3-coder',
        CCS_DROID_PROVIDER: 'generic-chat-completion-api',
      });
      if (!profile) {
        throw new Error('Expected shared-port OpenAI-compatible profile');
      }

      const started = await startOpenAICompatProxy(profile);
      expect(started.success).toBe(true);
      expect(started.port).not.toBe(occupiedPort);
    } finally {
      server.stop(true);
    }
  });

  it('keeps the existing proxy running if replacement startup fails', async () => {
    const firstPort = await getPort();
    const busyServer = Bun.serve({
      port: 0,
      hostname: '127.0.0.1',
      fetch: () => new Response('busy'),
    });
    const occupiedPort = busyServer.port;

    try {
      const settingsPath = path.join(tempDir, 'rollback.settings.json');
      fs.writeFileSync(
        settingsPath,
        JSON.stringify({
          env: {
            ANTHROPIC_BASE_URL: 'http://127.0.0.1:11434',
            ANTHROPIC_AUTH_TOKEN: 'ollama-rollback',
            ANTHROPIC_MODEL: 'qwen3-coder',
            CCS_DROID_PROVIDER: 'generic-chat-completion-api',
          },
        }),
        'utf8'
      );

      const profile = resolveOpenAICompatProfileConfig('rollback', settingsPath, {
        ANTHROPIC_BASE_URL: 'http://127.0.0.1:11434',
        ANTHROPIC_AUTH_TOKEN: 'ollama-rollback',
        ANTHROPIC_MODEL: 'qwen3-coder',
        CCS_DROID_PROVIDER: 'generic-chat-completion-api',
      });
      if (!profile) {
        throw new Error('Expected a rollback OpenAI-compatible profile');
      }

      const firstStart = await startOpenAICompatProxy(profile, { port: firstPort });
      expect(firstStart.success).toBe(true);

      const restarted = await startOpenAICompatProxy(profile, { port: occupiedPort });
      expect(restarted.success).toBe(false);

      const status = await getOpenAICompatProxyStatus('rollback');
      expect(status.running).toBe(true);
      expect(status.port).toBe(firstPort);
      expect((await fetch(`http://127.0.0.1:${firstPort}/health`)).status).toBe(200);
    } finally {
      busyServer.stop(true);
    }
  });

  it('returns to the adaptive canonical port after a stale fallback session', async () => {
    const stalePort = await getPort();
    const settingsPath = path.join(tempDir, 'outside-range.settings.json');
    fs.writeFileSync(
      settingsPath,
      JSON.stringify({
        env: {
          ANTHROPIC_BASE_URL: 'http://127.0.0.1:11434',
          ANTHROPIC_AUTH_TOKEN: 'ollama-outside-range',
          ANTHROPIC_MODEL: 'qwen3-coder',
          CCS_DROID_PROVIDER: 'generic-chat-completion-api',
        },
      }),
      'utf8'
    );

    const profile = resolveOpenAICompatProfileConfig('outside-range', settingsPath, {
      ANTHROPIC_BASE_URL: 'http://127.0.0.1:11434',
      ANTHROPIC_AUTH_TOKEN: 'ollama-outside-range',
      ANTHROPIC_MODEL: 'qwen3-coder',
      CCS_DROID_PROVIDER: 'generic-chat-completion-api',
    });
    if (!profile) {
      throw new Error('Expected an outside-range OpenAI-compatible profile');
    }

    fs.mkdirSync(path.dirname(getOpenAICompatProxySessionPath('outside-range')), { recursive: true });
    fs.writeFileSync(
      getOpenAICompatProxySessionPath('outside-range'),
      JSON.stringify(
        {
          profileName: profile.profileName,
          settingsPath: profile.settingsPath,
          host: '127.0.0.1',
          port: stalePort,
          baseUrl: profile.baseUrl,
          authToken: 'stale-token',
          model: profile.model,
        },
        null,
        2
      ) + '\n',
      'utf8'
    );

    const started = await startOpenAICompatProxy(profile);
    expect(started.success).toBe(true);
    expect(started.port).toBe(resolveOpenAICompatProxyPreferredPort('outside-range'));
    expect(started.port).not.toBe(stalePort);
  });

  it('does not keep a stopped shared-default profile anchored to legacy port 3456', async () => {
    const settingsPath = path.join(tempDir, 'legacy-shared-default.settings.json');
    fs.writeFileSync(
      settingsPath,
      JSON.stringify({
        env: {
          ANTHROPIC_BASE_URL: 'https://api.openai.com/v1',
          ANTHROPIC_AUTH_TOKEN: 'sk-legacy-shared-default',
          ANTHROPIC_MODEL: 'gpt-4.1',
        },
      }),
      'utf8'
    );

    const profile = resolveOpenAICompatProfileConfig('legacy-shared-default', settingsPath, {
      ANTHROPIC_BASE_URL: 'https://api.openai.com/v1',
      ANTHROPIC_AUTH_TOKEN: 'sk-legacy-shared-default',
      ANTHROPIC_MODEL: 'gpt-4.1',
    });
    if (!profile) {
      throw new Error('Expected legacy-shared-default OpenAI-compatible profile');
    }

    fs.mkdirSync(path.dirname(getOpenAICompatProxySessionPath('legacy-shared-default')), {
      recursive: true,
    });
    fs.writeFileSync(
      getOpenAICompatProxySessionPath('legacy-shared-default'),
      JSON.stringify(
        {
          profileName: profile.profileName,
          settingsPath: profile.settingsPath,
          host: '127.0.0.1',
          port: 3456,
          baseUrl: profile.baseUrl,
          authToken: 'stale-token',
          model: profile.model,
        },
        null,
        2
      ) + '\n',
      'utf8'
    );

    const started = await startOpenAICompatProxy(profile);
    expect(started.success).toBe(true);
    expect(started.port).not.toBe(3456);
  });

  it('stops legacy daemons even when the legacy session is missing a profile name', async () => {
    const port = await getPort();
    const settingsPath = path.join(tempDir, 'legacy-missing-profile.settings.json');
    fs.writeFileSync(
      settingsPath,
      JSON.stringify({
        env: {
          ANTHROPIC_BASE_URL: 'http://127.0.0.1:11434',
          ANTHROPIC_AUTH_TOKEN: 'ollama-legacy-missing-profile',
          ANTHROPIC_MODEL: 'qwen3-coder',
          CCS_DROID_PROVIDER: 'generic-chat-completion-api',
        },
      }),
      'utf8'
    );

    const profile = resolveOpenAICompatProfileConfig('legacy-missing-profile', settingsPath, {
      ANTHROPIC_BASE_URL: 'http://127.0.0.1:11434',
      ANTHROPIC_AUTH_TOKEN: 'ollama-legacy-missing-profile',
      ANTHROPIC_MODEL: 'qwen3-coder',
      CCS_DROID_PROVIDER: 'generic-chat-completion-api',
    });
    if (!profile) {
      throw new Error('Expected a legacy fallback OpenAI-compatible profile');
    }

    const started = await startOpenAICompatProxy(profile, { port });
    expect(started.success).toBe(true);
    expect(started.pid).toBeDefined();

    const proxyDir = path.dirname(getLegacyOpenAICompatProxyPidPath());
    fs.writeFileSync(getLegacyOpenAICompatProxyPidPath(), String(started.pid), 'utf8');
    fs.writeFileSync(
      getLegacyOpenAICompatProxySessionPath(),
      JSON.stringify(
        {
          settingsPath: profile.settingsPath,
          host: '127.0.0.1',
          port,
          baseUrl: profile.baseUrl,
          authToken: started.authToken,
          model: profile.model,
        },
        null,
        2
      ) + '\n',
      'utf8'
    );
    fs.rmSync(path.join(proxyDir, 'legacy-missing-profile.daemon.pid'), { force: true });
    fs.rmSync(path.join(proxyDir, 'legacy-missing-profile.session.json'), { force: true });

    const statuses = await listOpenAICompatProxyStatuses();
    expect(statuses.some((status) => status.port === port)).toBe(true);

    const stopped = await stopOpenAICompatProxy();
    expect(stopped.success).toBe(true);
    expect(fs.existsSync(getLegacyOpenAICompatProxyPidPath())).toBe(false);
    expect(fs.existsSync(getLegacyOpenAICompatProxySessionPath())).toBe(false);
  }, 35000);

  it('keeps the requested profile name in stopped status results', async () => {
    const status = await getOpenAICompatProxyStatus('never-started');
    expect(status.running).toBe(false);
    expect(status.profileName).toBe('never-started');
  });

  it('does not treat another profile on the same port as already running', async () => {
    const sharedPort = await getPort();
    const firstSettingsPath = path.join(tempDir, 'profile-b.settings.json');
    fs.writeFileSync(
      firstSettingsPath,
      JSON.stringify({
        env: {
          ANTHROPIC_BASE_URL: 'https://api.openai.com/v1',
          ANTHROPIC_AUTH_TOKEN: 'sk-profile-b',
          ANTHROPIC_MODEL: 'gpt-4.1',
        },
      }),
      'utf8'
    );

    const firstProfile = resolveOpenAICompatProfileConfig('profile-b', firstSettingsPath, {
      ANTHROPIC_BASE_URL: 'https://api.openai.com/v1',
      ANTHROPIC_AUTH_TOKEN: 'sk-profile-b',
      ANTHROPIC_MODEL: 'gpt-4.1',
    });
    if (!firstProfile) {
      throw new Error('Expected first OpenAI-compatible profile');
    }

    const firstStart = await startOpenAICompatProxy(firstProfile, { port: sharedPort });
    expect(firstStart.success).toBe(true);

    const secondSettingsPath = path.join(tempDir, 'profile-a.settings.json');
    fs.writeFileSync(
      secondSettingsPath,
      JSON.stringify({
        env: {
          ANTHROPIC_BASE_URL: 'https://api.openai.com/v1',
          ANTHROPIC_AUTH_TOKEN: 'sk-profile-a',
          ANTHROPIC_MODEL: 'gpt-4.1',
        },
      }),
      'utf8'
    );

    const secondProfile = resolveOpenAICompatProfileConfig('profile-a', secondSettingsPath, {
      ANTHROPIC_BASE_URL: 'https://api.openai.com/v1',
      ANTHROPIC_AUTH_TOKEN: 'sk-profile-a',
      ANTHROPIC_MODEL: 'gpt-4.1',
    });
    if (!secondProfile) {
      throw new Error('Expected second OpenAI-compatible profile');
    }

    fs.writeFileSync(
      getOpenAICompatProxySessionPath('profile-a'),
      JSON.stringify(
        {
          profileName: 'profile-a',
          settingsPath: secondProfile.settingsPath,
          host: '127.0.0.1',
          port: sharedPort,
          baseUrl: secondProfile.baseUrl,
          authToken: 'stale-token-a',
          model: secondProfile.model,
        },
        null,
        2
      ) + '\n',
      'utf8'
    );

    const secondStart = await startOpenAICompatProxy(secondProfile);
    expect(secondStart.success).toBe(true);
    expect(secondStart.alreadyRunning).not.toBe(true);
    expect(secondStart.authToken).not.toBe('stale-token-a');
  });

  it('replaces pid-only proxy state before starting a new daemon', async () => {
    const firstPort = await getPort();
    const replacementPort = await getPort();
    const settingsPath = path.join(tempDir, 'pid-only.settings.json');
    fs.writeFileSync(
      settingsPath,
      JSON.stringify({
        env: {
          ANTHROPIC_BASE_URL: 'https://api.openai.com/v1',
          ANTHROPIC_AUTH_TOKEN: 'sk-pid-only',
          ANTHROPIC_MODEL: 'gpt-4.1',
        },
      }),
      'utf8'
    );

    const profile = resolveOpenAICompatProfileConfig('pid-only', settingsPath, {
      ANTHROPIC_BASE_URL: 'https://api.openai.com/v1',
      ANTHROPIC_AUTH_TOKEN: 'sk-pid-only',
      ANTHROPIC_MODEL: 'gpt-4.1',
    });
    if (!profile) {
      throw new Error('Expected pid-only OpenAI-compatible profile');
    }

    const firstStart = await startOpenAICompatProxy(profile, { port: firstPort });
    expect(firstStart.success).toBe(true);
    expect(firstStart.pid).toBeDefined();

    fs.unlinkSync(getOpenAICompatProxySessionPath('pid-only'));

    const replacement = await startOpenAICompatProxy(profile, { port: replacementPort });
    expect(replacement.success).toBe(true);
    expect(replacement.port).toBe(replacementPort);
    expect(replacement.pid).toBeDefined();
    expect(replacement.pid).not.toBe(firstStart.pid);

    const stalePidPath = getOpenAICompatProxyPidPath('pid-only');
    expect(fs.readFileSync(stalePidPath, 'utf8').trim()).toBe(String(replacement.pid));
    expect((await fetch(`http://127.0.0.1:${replacementPort}/health`)).status).toBe(200);
  });

  it('does not stop another profile when a stale pid file points at its daemon', async () => {
    const firstPort = await getPort();
    const secondPort = await getPort();
    const firstSettingsPath = path.join(tempDir, 'profile-b-stale-pid.settings.json');
    fs.writeFileSync(
      firstSettingsPath,
      JSON.stringify({
        env: {
          ANTHROPIC_BASE_URL: 'https://api.openai.com/v1',
          ANTHROPIC_AUTH_TOKEN: 'sk-profile-b-stale-pid',
          ANTHROPIC_MODEL: 'gpt-4.1',
        },
      }),
      'utf8'
    );
    const firstProfile = resolveOpenAICompatProfileConfig('profile-b-stale-pid', firstSettingsPath, {
      ANTHROPIC_BASE_URL: 'https://api.openai.com/v1',
      ANTHROPIC_AUTH_TOKEN: 'sk-profile-b-stale-pid',
      ANTHROPIC_MODEL: 'gpt-4.1',
    });
    if (!firstProfile) {
      throw new Error('Expected first OpenAI-compatible profile');
    }

    const firstStart = await startOpenAICompatProxy(firstProfile, { port: firstPort });
    expect(firstStart.success).toBe(true);
    expect(firstStart.pid).toBeDefined();

    const secondSettingsPath = path.join(tempDir, 'profile-a-stale-pid.settings.json');
    fs.writeFileSync(
      secondSettingsPath,
      JSON.stringify({
        env: {
          ANTHROPIC_BASE_URL: 'https://api.openai.com/v1',
          ANTHROPIC_AUTH_TOKEN: 'sk-profile-a-stale-pid',
          ANTHROPIC_MODEL: 'gpt-4.1',
        },
      }),
      'utf8'
    );
    const secondProfile = resolveOpenAICompatProfileConfig('profile-a-stale-pid', secondSettingsPath, {
      ANTHROPIC_BASE_URL: 'https://api.openai.com/v1',
      ANTHROPIC_AUTH_TOKEN: 'sk-profile-a-stale-pid',
      ANTHROPIC_MODEL: 'gpt-4.1',
    });
    if (!secondProfile) {
      throw new Error('Expected second OpenAI-compatible profile');
    }

    fs.writeFileSync(
      getOpenAICompatProxyPidPath('profile-a-stale-pid'),
      String(firstStart.pid),
      'utf8'
    );

    const secondStart = await startOpenAICompatProxy(secondProfile, { port: secondPort });
    expect(secondStart.success).toBe(true);
    expect(secondStart.port).toBe(secondPort);
    expect((await fetch(`http://127.0.0.1:${firstPort}/health`)).status).toBe(200);
    expect((await fetch(`http://127.0.0.1:${secondPort}/health`)).status).toBe(200);
  });
});
