import { describe, it, expect, vi } from 'vitest';
import express from 'express';
import request from 'supertest';
import { createAdminGatewayStatusRouter, type AdminGatewayStatusDeps } from './admin-gateway-status-api.js';
import type { GatewayMountHandle } from './gateway-mount.js';
import type { ConfigManager } from '../config-manager.js';

function makeMount(state: string, errors: string[] = []): GatewayMountHandle {
  return {
    getState: vi.fn().mockReturnValue(state),
    getErrors: vi.fn().mockReturnValue(errors),
    applyConfig: vi.fn(),
    stop: vi.fn(),
  } as unknown as GatewayMountHandle;
}

function makeConfigManager(config: unknown): ConfigManager {
  return {
    getConfig: vi.fn().mockReturnValue(config),
  } as unknown as ConfigManager;
}

function makeApp(deps: AdminGatewayStatusDeps): express.Application {
  const app = express();
  app.use('/api/admin/gateway/status', createAdminGatewayStatusRouter(deps));
  return app;
}

describe('Admin Gateway Status API', () => {
  it('reports unavailable when there is no mount handle', async () => {
    const app = makeApp({ mount: null, configManager: null, workerPort: 9876 });

    const res = await request(app).get('/api/admin/gateway/status');

    expect(res.status).toBe(200);
    expect(res.body).toEqual({
      state: 'unavailable',
      enabled: null,
      errors: [],
      mounted: false,
      sharedPort: 9876,
      message: 'gateway hot-reload unsupported in this deploy (no ConfigManager)',
    });
  });

  it('reports the desired enabled flag from config even without a mount', async () => {
    const app = makeApp({
      mount: null,
      configManager: makeConfigManager({ gateway: { enabled: true } }),
      workerPort: 4000,
    });

    const res = await request(app).get('/api/admin/gateway/status');

    expect(res.status).toBe(200);
    expect(res.body.state).toBe('unavailable');
    expect(res.body.enabled).toBe(true);
    expect(res.body.sharedPort).toBe(4000);
  });

  it('reports mounted=true when the mount state is running', async () => {
    const app = makeApp({
      mount: makeMount('running'),
      configManager: makeConfigManager({ gateway: { enabled: true } }),
      workerPort: 9876,
    });

    const res = await request(app).get('/api/admin/gateway/status');

    expect(res.status).toBe(200);
    expect(res.body).toEqual({
      state: 'running',
      enabled: true,
      errors: [],
      mounted: false || true, // mounted is true exactly when state === 'running'
      sharedPort: 9876,
    });
    expect(res.body.mounted).toBe(true);
  });

  it('reports mounted=false with validation errors when disabled', async () => {
    const errors = ['backend url missing', 'no virtual keys'];
    const app = makeApp({
      mount: makeMount('disabled', errors),
      configManager: makeConfigManager({ gateway: { enabled: false } }),
      workerPort: 9876,
    });

    const res = await request(app).get('/api/admin/gateway/status');

    expect(res.status).toBe(200);
    expect(res.body.state).toBe('disabled');
    expect(res.body.enabled).toBe(false);
    expect(res.body.mounted).toBe(false);
    expect(res.body.errors).toEqual(errors);
  });

  it('defaults enabled to false when the config has no gateway block', async () => {
    // readGatewayConfig normalizes a missing block to enabled=false.
    const app = makeApp({
      mount: makeMount('disabled'),
      configManager: makeConfigManager({}),
      workerPort: 9876,
    });

    const res = await request(app).get('/api/admin/gateway/status');

    expect(res.status).toBe(200);
    expect(res.body.enabled).toBe(false);
  });

  it('reports enabled=null when reading the config throws', async () => {
    const throwing = {
      getConfig: vi.fn().mockImplementation(() => { throw new Error('config unreadable'); }),
    } as unknown as ConfigManager;
    const app = makeApp({
      mount: makeMount('running'),
      configManager: throwing,
      workerPort: 9876,
    });

    const res = await request(app).get('/api/admin/gateway/status');

    expect(res.status).toBe(200);
    expect(res.body.enabled).toBeNull();
    expect(res.body.state).toBe('running');
  });

  it('reports enabled=null when there is a mount but no ConfigManager', async () => {
    const app = makeApp({
      mount: makeMount('starting'),
      configManager: null,
      workerPort: 9876,
    });

    const res = await request(app).get('/api/admin/gateway/status');

    expect(res.status).toBe(200);
    expect(res.body.state).toBe('starting');
    expect(res.body.enabled).toBeNull();
    expect(res.body.mounted).toBe(false);
  });
});
