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

const mockGetCurrentUser = vi.fn();
vi.mock('@/lib/auth-server', () => ({
  getCurrentUser: (...args: unknown[]) => mockGetCurrentUser(...args),
  getCurrentUserFromRequest: (...args: unknown[]) => mockGetCurrentUser(...args),
}));

const mockLogError = vi.fn();
vi.mock('@/lib/logger', () => ({
  logError: (...args: unknown[]) => mockLogError(...args),
}));

import { GET, POST } from '@/app/api/agent-runtime/route';

async function callGet(qs = '') {
  const { NextRequest } = await import('next/server');
  return GET(
    new NextRequest(
      new Request(`http://localhost:3001/api/agent-runtime${qs}`, {
        headers: { Authorization: 'Bearer test', 'x-product-id': 'lysnrai' },
      })
    )
  );
}

async function callPost(payload: unknown) {
  const { NextRequest } = await import('next/server');
  return POST(
    new NextRequest(
      new Request('http://localhost:3001/api/agent-runtime', {
        method: 'POST',
        headers: { Authorization: 'Bearer test', 'x-product-id': 'lysnrai' },
        body: JSON.stringify(payload),
      })
    )
  );
}

describe('agent runtime proxy route', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('returns 401 for unauthenticated callers', async () => {
    mockGetCurrentUser.mockResolvedValue(null);
    const res = await callGet();
    expect(res.status).toBe(401);
  });

  it('proxies GET session requests to platform-service', async () => {
    mockGetCurrentUser.mockResolvedValue({ id: 'usr_admin', role: 'admin' });
    const fetchMock = vi.fn().mockResolvedValue({
      status: 200,
      json: async () => ({ sessions: [{ sessionId: 'sess_1' }], count: 1 }),
    });
    vi.stubGlobal('fetch', fetchMock);

    const res = await callGet('?section=sessions&userId=user_1');

    expect(res.status).toBe(200);
    expect(fetchMock).toHaveBeenCalledWith(
      'http://localhost:4003/api/agent-runtime/sessions?userId=user_1',
      expect.objectContaining({
        method: 'GET',
        headers: expect.objectContaining({
          'x-user-id': 'usr_admin',
          'x-product-id': 'lysnrai',
        }),
      })
    );
  });

  it('proxies Cowork checkpoint list requests to cowork-service', async () => {
    mockGetCurrentUser.mockResolvedValue({ id: 'usr_admin', role: 'admin' });
    const fetchMock = vi.fn().mockResolvedValue({
      status: 200,
      json: async () => ({ checkpoints: [{ checkpointId: 'ckpt_task-1' }], count: 1 }),
    });
    vi.stubGlobal('fetch', fetchMock);

    const res = await callGet('?section=checkpoints&productId=clawcowork&limit=10');

    expect(res.status).toBe(200);
    expect(fetchMock).toHaveBeenCalledWith(
      'http://localhost:4009/api/agent-runtime/checkpoints?limit=10',
      expect.objectContaining({
        method: 'GET',
        headers: expect.objectContaining({
          'x-user-id': 'usr_admin',
          'x-product-id': 'clawcowork',
        }),
      })
    );
  });

  it('proxies Cowork checkpoint detail requests to cowork-service', async () => {
    mockGetCurrentUser.mockResolvedValue({ id: 'usr_admin', role: 'admin' });
    const fetchMock = vi.fn().mockResolvedValue({
      status: 200,
      json: async () => ({
        checkpoint: { checkpointId: 'ckpt_task-1' },
        detail: { goal: 'Review the repository' },
      }),
    });
    vi.stubGlobal('fetch', fetchMock);

    const res = await callGet(
      '?section=checkpoint-detail&productId=clawcowork&checkpointId=ckpt_task-1'
    );

    expect(res.status).toBe(200);
    expect(fetchMock).toHaveBeenCalledWith(
      'http://localhost:4009/api/agent-runtime/checkpoints/ckpt_task-1',
      expect.objectContaining({
        method: 'GET',
        headers: expect.objectContaining({
          'x-user-id': 'usr_admin',
          'x-product-id': 'clawcowork',
        }),
      })
    );
  });

  it('proxies POST dispatch validation requests to platform-service', async () => {
    mockGetCurrentUser.mockResolvedValue({ id: 'usr_admin', role: 'admin' });
    const fetchMock = vi.fn().mockResolvedValue({
      status: 200,
      json: async () => ({ valid: true }),
    });
    vi.stubGlobal('fetch', fetchMock);

    const res = await callPost({
      dispatchId: 'dispatch_1',
      targetProductId: 'lysnrai',
      targetExecutor: 'generic-agent',
      userId: 'user_1',
      title: 'Test',
      intent: 'Validate payload',
      artifactRefs: [],
      memoryRefs: [],
      dispatchContext: {
        originSurface: 'web',
        originProductId: 'lysnrai',
        dispatchMode: 'interactive',
        initiatedAt: '2026-04-04T08:00:00.000Z',
      },
    });

    expect(res.status).toBe(200);
    expect(fetchMock).toHaveBeenCalledWith(
      'http://localhost:4003/api/agent-runtime/dispatch/validate',
      expect.objectContaining({
        method: 'POST',
      })
    );
  });
});
