import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';

import { OpenAIClient } from './openai.js';

vi.mock('../auth/openai.js', () => ({
  ensureValidOpenAIAuth: vi.fn(async () => ({
    access_token: 'at',
    refresh_token: 'rt',
    expires_at: Date.now() + 60_000,
    created_at: new Date().toISOString(),
    account_id: 'acct',
  })),
}));

function makeSse(events: Array<{ event: string; data: any }>): string {
  return events
    .map((e) => `event: ${e.event}\ndata: ${JSON.stringify(e.data)}\n\n`)
    .join('');
}

describe('OpenAIClient OAuth (Codex)', () => {
  const originalFetch = globalThis.fetch;

  beforeEach(() => {
    vi.useFakeTimers();
  });

  afterEach(() => {
    globalThis.fetch = originalFetch;
    vi.useRealTimers();
    vi.restoreAllMocks();
  });

  it('streams SSE and accumulates output_text.delta', async () => {
    const sse = makeSse([
      { event: 'response.created', data: { type: 'response.created', response: { id: 'r1' } } },
      { event: 'response.output_text.delta', data: { type: 'response.output_text.delta', delta: 'hel' } },
      { event: 'response.output_text.delta', data: { type: 'response.output_text.delta', delta: 'lo' } },
      { event: 'response.completed', data: { type: 'response.completed', response: { usage: { input_tokens: 2, output_tokens: 2 } } } },
    ]);

    globalThis.fetch = vi.fn(async (_url: any, init?: any) => {
      const parsed = JSON.parse(init.body);
      expect(parsed.store).toBe(false);
      expect(parsed.stream).toBe(true);
      expect(typeof parsed.instructions).toBe('string');
      expect(Array.isArray(parsed.input)).toBe(true);

      const stream = new ReadableStream({
        start(controller) {
          controller.enqueue(new TextEncoder().encode(sse));
          controller.close();
        },
      });

      return new Response(stream, { status: 200 });
    }) as any;

    const client = new OpenAIClient({ model: 'gpt-5.3-codex', useOAuth: true });
    const resp = await client.chat({
      system: 'You are helpful.',
      messages: [{ role: 'user', content: 'hi' }],
    });

    expect(resp.content).toBe('hello');
    expect(resp.usage).toEqual({ inputTokens: 2, outputTokens: 2 });
  });
});
