import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
import { createServiceApp, type FastifyApp } from '@bytelyst/fastify-core';

vi.mock('../../lib/config.js', () => ({
  config: {
    SERVICE_NAME: 'cowork-service',
    PLATFORM_SERVICE_URL: 'http://mock-platform:4003',
  },
}));
vi.mock('../../lib/product-config.js', () => ({
  PRODUCT_ID: 'clawcowork',
}));
vi.mock('../../lib/request-context.js', () => ({
  getUserId: vi.fn(() => 'demo-user'),
}));

import { pushRoutes } from './routes.js';

let app: FastifyApp;
const mockFetch = vi.fn();
vi.stubGlobal('fetch', mockFetch);

beforeAll(async () => {
  app = await createServiceApp({
    name: 'push-routes-test',
    version: '0.0.1',
    logger: false,
  });
  await app.register(pushRoutes);
});

afterAll(async () => {
  await app.close();
});

beforeEach(() => {
  mockFetch.mockReset();
});

describe('push proxy routes', () => {
  it('POST /api/push/register proxies push device registration', async () => {
    mockFetch.mockResolvedValue({
      ok: true,
      json: async () => ({ registered: true }),
    });

    const res = await app.inject({
      method: 'POST',
      url: '/api/push/register',
      headers: { authorization: 'Bearer push-token' },
      payload: { deviceToken: 'device-token', platform: 'ios' },
    });

    expect(res.statusCode).toBe(200);
    expect(JSON.parse(res.payload).registered).toBe(true);
    expect(mockFetch.mock.calls[0][0]).toBe(
      'http://mock-platform:4003/notifications/push/register'
    );
    expect(JSON.parse(mockFetch.mock.calls[0][1].body)).toMatchObject({
      userId: 'demo-user',
      productId: 'clawcowork',
      deviceToken: 'device-token',
    });
  });

  it('DELETE /api/push/register proxies push unregistration', async () => {
    mockFetch.mockResolvedValue({
      ok: true,
      json: async () => ({ removed: true }),
    });

    const res = await app.inject({
      method: 'DELETE',
      url: '/api/push/register',
      payload: { deviceToken: 'device-token' },
    });

    expect(res.statusCode).toBe(200);
    expect(JSON.parse(res.payload).removed).toBe(true);
    expect(mockFetch.mock.calls[0][1].method).toBe('DELETE');
  });

  it('returns 502 when platform-service is unavailable', async () => {
    mockFetch.mockRejectedValue(new Error('ECONNREFUSED'));

    const res = await app.inject({
      method: 'POST',
      url: '/api/push/register',
      payload: { deviceToken: 'device-token' },
    });

    expect(res.statusCode).toBe(502);
  });
});
