/**
 * Tests for /api/agent/v1/[...path] — agent-facing platform proxy.
 */

import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import type { NextRequest } from 'next/server';

const mockFetch = vi.fn();
vi.stubGlobal('fetch', mockFetch);

import { GET, POST } from '@/app/api/agent/v1/[...path]/route';

function mockNextRequest(
  method: string,
  path: string,
  body?: string,
  headers?: Record<string, string>
): NextRequest {
  const headerMap = new Map(Object.entries(headers || {}));
  return {
    method,
    headers: {
      get: (key: string) => headerMap.get(key.toLowerCase()) || headerMap.get(key) || null,
    },
    nextUrl: {
      searchParams: new URLSearchParams('limit=10'),
    },
    text: async () => body || '',
  } as unknown as NextRequest;
}

describe('agent v1 proxy', () => {
  const originalEnv = { ...process.env };

  beforeEach(() => {
    vi.clearAllMocks();
    process.env.PLATFORM_API_URL = 'http://localhost:4003';
  });

  afterEach(() => {
    process.env = { ...originalEnv };
  });

  it('proxies agent list requests with product and agent key headers', async () => {
    mockFetch.mockResolvedValue({ status: 200, text: async () => JSON.stringify({ items: [] }) });

    const req = mockNextRequest('GET', 'items/assigned', undefined, {
      'x-agent-key': 'agent-key-1',
      'x-product-id': 'tracker',
    });
    const res = await GET(req, { params: Promise.resolve({ path: ['items', 'assigned'] }) });

    expect(res.status).toBe(200);
    expect(mockFetch).toHaveBeenCalledWith(
      expect.stringContaining('/api/agent/v1/items/assigned?limit=10'),
      expect.objectContaining({
        method: 'GET',
        headers: expect.objectContaining({
          'x-agent-key': 'agent-key-1',
          'x-product-id': 'tracker',
        }),
      })
    );
  });

  it('proxies agent mutation requests with JSON body', async () => {
    mockFetch.mockResolvedValue({
      status: 201,
      text: async () => JSON.stringify({ id: 'item_1' }),
    });
    const body = JSON.stringify({ title: 'Agent-created item' });
    const req = mockNextRequest('POST', 'items', body, { authorization: 'Bearer token' });

    const res = await POST(req, { params: Promise.resolve({ path: ['items'] }) });

    expect(res.status).toBe(201);
    expect(mockFetch).toHaveBeenCalledWith(
      expect.stringContaining('/api/agent/v1/items'),
      expect.objectContaining({
        method: 'POST',
        body,
        headers: expect.objectContaining({ Authorization: 'Bearer token' }),
      })
    );
  });

  it('returns 502 when the agent API is unavailable', async () => {
    mockFetch.mockRejectedValue(new Error('ECONNREFUSED'));

    const req = mockNextRequest('GET', 'items/assigned');
    const res = await GET(req, { params: Promise.resolve({ path: ['items', 'assigned'] }) });

    expect(res.status).toBe(502);
    await expect(res.json()).resolves.toEqual({ error: 'Agent API unavailable' });
  });
});
