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 } from '@/app/api/timeline/route';

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

describe('GET /api/timeline', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

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

  it('forwards query params to platform-service and returns timeline items', async () => {
    mockGetCurrentUser.mockResolvedValue({ id: 'usr_admin', role: 'admin' });
    const fetchMock = vi.fn().mockResolvedValue({
      status: 200,
      json: async () => ({
        items: [
          {
            itemId: 'timeline_evt_1',
            title: 'Transcript captured',
          },
        ],
        count: 1,
      }),
    });
    vi.stubGlobal('fetch', fetchMock);

    const res = await callTimeline('?limit=20&eventName=artifact.created');

    expect(res.status).toBe(200);
    const data = await res.json();
    expect(data.count).toBe(1);
    expect(fetchMock).toHaveBeenCalledWith(
      'http://localhost:4003/api/timeline?limit=20&eventName=artifact.created',
      expect.objectContaining({
        method: 'GET',
        headers: expect.objectContaining({
          'x-user-id': 'usr_admin',
          'x-product-id': 'lysnrai',
        }),
      })
    );
  });

  it('allows an explicit product override for internal timeline review', async () => {
    mockGetCurrentUser.mockResolvedValue({ id: 'usr_admin', role: 'admin' });
    const fetchMock = vi.fn().mockResolvedValue({
      status: 200,
      json: async () => ({ items: [], count: 0 }),
    });
    vi.stubGlobal('fetch', fetchMock);

    const res = await callTimeline('?productId=flowmonk&limit=10');

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

  it('returns 502 when platform-service proxying fails', async () => {
    mockGetCurrentUser.mockResolvedValue({ id: 'usr_admin', role: 'admin' });
    vi.stubGlobal('fetch', vi.fn().mockRejectedValue(new Error('boom')));

    const res = await callTimeline();

    expect(res.status).toBe(502);
    expect(mockLogError).toHaveBeenCalled();
  });
});
