/**
 * Integration tests for report API (CMC, CoinGecko)
 * Uses native fetch + http server (no deprecated supertest)
 */

import { createServer } from 'http';
import express from 'express';
import reportRoutes from './report';

jest.mock('../../database/repositories/token-repo', () => ({
  TokenRepository: jest.fn().mockImplementation(() => ({
    getToken: jest.fn().mockResolvedValue(null),
  })),
}));
jest.mock('../../database/repositories/market-data-repo', () => ({
  MarketDataRepository: jest.fn().mockImplementation(() => ({
    getMarketData: jest.fn().mockResolvedValue(null),
  })),
}));
jest.mock('../../database/repositories/pool-repo', () => ({
  PoolRepository: jest.fn().mockImplementation(() => ({
    getPoolsByToken: jest.fn().mockResolvedValue([]),
    getPoolsByChain: jest.fn().mockResolvedValue([]),
  })),
}));
jest.mock('../middleware/cache');

function createApp() {
  const app = express();
  app.use('/api/v1/report', reportRoutes);
  return app;
}

async function startServer(app: express.Application): Promise<{ server: ReturnType<typeof createServer>; baseUrl: string }> {
  const server = createServer(app);
  await new Promise<void>((resolve) => server.listen(0, () => resolve()));
  const port = (server.address() as { port: number }).port;
  return { server, baseUrl: `http://127.0.0.1:${port}` };
}

describe('Report API', () => {
  let server: ReturnType<typeof createServer>;
  let baseUrl: string;

  beforeAll(async () => {
    const app = createApp();
    const started = await startServer(app);
    server = started.server;
    baseUrl = started.baseUrl;
  });

  afterAll((done) => {
    server.close(done);
  });

  describe('GET /api/v1/report/cmc', () => {
    it('returns 200 with cmc format', async () => {
      const res = await fetch(`${baseUrl}/api/v1/report/cmc?chainId=138`);
      expect(res.status).toBe(200);
      const body = (await res.json()) as Record<string, unknown>;
      expect(body).toHaveProperty('generatedAt');
      expect(body).toHaveProperty('chainId', 138);
      expect(body).toHaveProperty('format', 'coinmarketcap-dex');
      expect(body).toHaveProperty('tokens');
      expect(Array.isArray(body.tokens)).toBe(true);
    });

    it('accepts chainId 651940', async () => {
      const res = await fetch(`${baseUrl}/api/v1/report/cmc?chainId=651940`);
      expect(res.status).toBe(200);
      const body = (await res.json()) as Record<string, unknown>;
      expect(body.chainId).toBe(651940);
    });
  });

  describe('GET /api/v1/report/coingecko', () => {
    it('returns 200 with coingecko format', async () => {
      const res = await fetch(`${baseUrl}/api/v1/report/coingecko?chainId=138`);
      expect(res.status).toBe(200);
      const body = (await res.json()) as Record<string, unknown>;
      expect(body).toHaveProperty('generatedAt');
      expect(body).toHaveProperty('chainId', 138);
      expect(body).toHaveProperty('format', 'coingecko-submission');
      expect(body).toHaveProperty('tokens');
      expect(Array.isArray(body.tokens)).toBe(true);
    });
  });
});
