import { describe, it, expect, vi, beforeAll, beforeEach } from 'vitest';
import { log, setOpencodeClient } from '../src/index.js';
import { saveEnv, resetEnv, createMockOpencodeClient } from './helpers.js';

beforeAll(() => saveEnv());

describe('TestLog', () => {
  beforeEach(() => {
    resetEnv();
    setOpencodeClient(null);
    vi.spyOn(console, 'error').mockImplementation(() => {});
  });

  it('falls back to console.error when no client', async () => {
    await log('warn', 'test message');
    expect(console.error).toHaveBeenCalledWith(
      '[oG-Memory] warn: test message', '',
    );
  });

  it('uses client.app.log when client is available', async () => {
    const mockClient = createMockOpencodeClient();
    setOpencodeClient(mockClient as any);
    await log('info', 'hello', { key: 'val' });
    expect(mockClient.app.log).toHaveBeenCalledWith({
      body: { service: 'oG-Memory', level: 'info', message: 'hello', extra: { key: 'val' } },
    });
  });

  it('does not include extra when not provided', async () => {
    const mockClient = createMockOpencodeClient();
    setOpencodeClient(mockClient as any);
    await log('info', 'simple');
    const callArg = mockClient.app.log.mock.calls[0]![0];
    expect('extra' in callArg.body).toBe(false);
  });

  it('falls back to console.error when client.app.log throws', async () => {
    const mockClient = createMockOpencodeClient();
    mockClient.app.log.mockRejectedValue(new Error('network fail'));
    setOpencodeClient(mockClient as any);
    await log('error', 'fallback test');
    expect(console.error).toHaveBeenCalled();
  });
});