/**
 * Tests for /api/products/[...path] — products registry proxy (owner-scoped
 * "my projects" via GET /api/products/mine).
 */

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 } from '@/app/api/products/[...path]/route';

function mockNextRequest(
  method: 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() },
    text: async () => body || '',
  } as unknown as NextRequest;
}

describe('products proxy', () => {
  const originalEnv = { ...process.env };
  beforeEach(() => {
    vi.clearAllMocks();
    process.env.PLATFORM_API_URL = 'http://localhost:4003';
  });
  afterEach(() => {
    process.env = { ...originalEnv };
  });

  it('proxies GET /products/mine, forwarding the bearer token', async () => {
    mockFetch.mockResolvedValue({
      status: 200,
      text: async () => JSON.stringify({ products: [{ productId: 'acme' }] }),
    });
    const req = mockNextRequest('GET', undefined, { authorization: 'Bearer tok' });
    const res = await GET(req, { params: Promise.resolve({ path: ['mine'] }) });

    expect(res.status).toBe(200);
    expect(mockFetch).toHaveBeenCalledWith(
      expect.stringContaining('/api/products/mine'),
      expect.objectContaining({
        method: 'GET',
        headers: expect.objectContaining({ Authorization: 'Bearer tok' }),
      })
    );
  });

  it('promotes x-tracker-token to a bearer when no Authorization is present', async () => {
    mockFetch.mockResolvedValue({ status: 200, text: async () => '{}' });
    const req = mockNextRequest('GET', undefined, { 'x-tracker-token': 'ttok' });
    await GET(req, { params: Promise.resolve({ path: ['mine'] }) });
    expect(mockFetch).toHaveBeenCalledWith(
      expect.any(String),
      expect.objectContaining({
        headers: expect.objectContaining({ Authorization: 'Bearer ttok' }),
      })
    );
  });

  it('returns 502 when the products service is unavailable', async () => {
    mockFetch.mockRejectedValue(new Error('ECONNREFUSED'));
    const req = mockNextRequest('GET');
    const res = await GET(req, { params: Promise.resolve({ path: ['mine'] }) });
    expect(res.status).toBe(502);
    await expect(res.json()).resolves.toEqual({ error: 'Products service unavailable' });
  });
});
