import { createServer } from 'http';
import express from 'express';

let partnerPayloadRoutes: any;
const mockPlan = jest.fn();

jest.mock('../../services/best-execution-planner', () => ({
  __esModule: true,
  BestExecutionPlanner: jest.fn().mockImplementation(() => ({
    plan: mockPlan,
  })),
}));

jest.mock('../../config/aggregator-route-matrix', () => ({
  __esModule: true,
  loadAggregatorRouteMatrix: jest.fn(() => ({
    version: '2.0.0',
    updated: '2026-04-02T00:00:00.000Z',
    homeChainId: 138,
    liveSwapRoutes: [],
    liveBridgeRoutes: [],
    blockedOrPlannedRoutes: [],
  })),
  filterLiveAggregatorRoutes: jest.fn(() => []),
}));

jest.mock('../middleware/cache');

function createApp() {
  const app = express();
  app.use(express.json());
  app.use('/api/v1', partnerPayloadRoutes);
  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('Partner payload API', () => {
  let server: ReturnType<typeof createServer>;
  let baseUrl: string;

  beforeAll(async () => {
    partnerPayloadRoutes = require('./partner-payloads').default;
    const started = await startServer(createApp());
    server = started.server;
    baseUrl = started.baseUrl;
  });

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

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

  it('prefers planner-v2 routes when concrete route inputs are provided', async () => {
    mockPlan.mockResolvedValue({
      planId: 'planner-route-1',
      generatedAt: new Date().toISOString(),
      decision: 'direct-pool',
      sourceChainId: 138,
      destinationChainId: 138,
      tokenIn: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
      tokenOut: '0x004b63a7b5b0e06f6bb6adb4a5f9f590bf3182d1',
      estimatedAmountOut: '1800000000',
      minAmountOut: '1782000000',
      estimatedGasUsd: 0.22,
      confidenceScore: 0.91,
      riskFlags: [],
      selectedRouteReason: 'Selected deepest eligible dodo pool.',
      rejectedAlternatives: [],
      staleness: { maxFreshnessSeconds: 15, hasStaleLeg: false },
      alternatives: [],
      legs: [
        {
          kind: 'swap',
          provider: 'dodo',
          sourceChainId: 138,
          destinationChainId: 138,
          tokenInAddress: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
          tokenOutAddress: '0x004b63a7b5b0e06f6bb6adb4a5f9f590bf3182d1',
          tokenInSymbol: 'WETH',
          tokenOutSymbol: 'USDT',
          estimatedAmountIn: '1000000000000000000',
          estimatedAmountOut: '1800000000',
          minAmountOut: '1782000000',
          target: '0x86ada6ef91a3b450f89f2b751e93b1b7a3218895',
          poolAddress: '0x1111111111111111111111111111111111111111',
          providerData: { poolAddress: '0x1111111111111111111111111111111111111111' },
          providerDataHex: '0x',
        },
      ],
    });

    const res = await fetch(
      `${baseUrl}/api/v1/routes/partner-payloads?partner=0x&amount=1000000000000000000&fromChainId=138&tokenIn=0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&tokenOut=0x004b63a7b5b0e06f6bb6adb4a5f9f590bf3182d1&includeUnsupported=true`
    );

    expect(res.status).toBe(200);
    const body = (await res.json()) as Record<string, any>;
    expect(body.routeSource).toBe('planner-v2-preferred');
    expect(body.count).toBe(1);
    expect(body.payloads[0].routeId).toBe('planner-route-1');
    expect(mockPlan).toHaveBeenCalled();
  });
});
