import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import Fastify from 'fastify';
import { sessionRoutes } from './routes.js';
import { setIpcBridge, type IpcBridge } from '../../lib/ipc-bridge.js';

vi.mock('../../lib/product-config.js', () => ({
  PRODUCT_ID: 'clawcowork',
  productConfig: {
    backendPort: 4009,
  },
}));

vi.mock('../../lib/request-context.js', () => ({
  getUserId: vi.fn(() => 'demo-user'),
}));

let app: ReturnType<typeof Fastify>;
const call = vi.fn();

beforeEach(async () => {
  setIpcBridge({
    isRunning: true,
    call,
  } as unknown as IpcBridge);

  app = Fastify({ logger: false });
  app.decorateRequest('jwtPayload', null);
  await app.register(sessionRoutes);
  call.mockReset();
});

afterEach(async () => {
  setIpcBridge(null);
  await app.close();
});

describe('sessions routes', () => {
  it('lists sessions via IPC', async () => {
    call.mockResolvedValue({
      result: { sessions: [{ id: 'sess-1', messageCount: 3 }] },
    });

    const res = await app.inject({ method: 'GET', url: '/api/sessions' });
    expect(res.statusCode).toBe(200);
    expect(JSON.parse(res.payload).sessions).toHaveLength(1);
    expect(call).toHaveBeenCalledWith(
      'list_sessions',
      expect.objectContaining({
        auth: expect.objectContaining({ userId: 'demo-user' }),
      })
    );
  });

  it('returns a single session via IPC', async () => {
    call.mockResolvedValue({
      result: { session: { id: 'sess-1', messages: [] } },
    });

    const res = await app.inject({ method: 'GET', url: '/api/sessions/sess-1' });
    expect(res.statusCode).toBe(200);
    expect(JSON.parse(res.payload).session.id).toBe('sess-1');
  });

  it('maps not found errors for session fetch', async () => {
    call.mockResolvedValue({
      error: { code: -32001, message: 'not found' },
    });

    const res = await app.inject({ method: 'GET', url: '/api/sessions/missing' });
    expect(res.statusCode).toBe(404);
  });

  it('deletes a session via IPC', async () => {
    call.mockResolvedValue({
      result: { deleted: true, sessionId: 'sess-1' },
    });

    const res = await app.inject({ method: 'DELETE', url: '/api/sessions/sess-1' });
    expect(res.statusCode).toBe(200);
    expect(JSON.parse(res.payload).deleted).toBe(true);
  });
});
