const express = require('express');
const request = require('supertest');

// Minimal asyncHandler that catches errors
function asyncHandler(fn) {
  return (req, res, next) => Promise.resolve(fn(req, res, next)).catch(next);
}

function createApp(depsOverride = {}) {
  const defaultDeps = {
    fetchT: jest.fn().mockResolvedValue({ ok: true, status: 200, json: () => ({}) }),
    SERVICES_FILE: '/tmp/services.json',
    servicesStateManager: {
      read: jest.fn().mockResolvedValue([]),
      write: jest.fn().mockResolvedValue(),
      update: jest.fn().mockResolvedValue([]),
    },
    siteConfig: { tld: 'sami' },
    buildServiceUrl: jest.fn(id => `https://${id}.sami`),
    asyncHandler,
    logError: jest.fn(),
    healthChecker: {
      getCurrentStatus: jest.fn().mockReturnValue({}),
      getServiceStats: jest.fn().mockReturnValue(null),
      configureService: jest.fn(),
      removeService: jest.fn(),
      getOpenIncidents: jest.fn().mockReturnValue([]),
      getIncidentHistory: jest.fn().mockReturnValue([]),
    },
  };

  const deps = { ...defaultDeps, ...depsOverride };
  const healthRoutes = require('../../routes/health');
  const app = express();
  app.use(express.json());
  app.use('/api', healthRoutes(deps));
  // Simple error handler
  app.use((err, req, res, next) => {
    const status = err.statusCode || 500;
    res.status(status).json({ success: false, error: err.message });
  });
  return { app, deps };
}

jest.mock('child_process', () => ({
  execSync: jest.fn(),
}));

jest.mock('../../platform-paths', () => ({
  caCertDir: '/mock/ca',
  pkiRootCert: '/mock/pki/root.crt',
}));

// Mock fs-helpers.exists
jest.mock('../../src/utilities/fs-helpers', () => ({
  exists: jest.fn().mockResolvedValue(true),
}));

jest.mock('../../src/utilities/url-resolver', () => ({
  resolveServiceUrl: jest.fn((id) => `https://${id}.test`),
}));

jest.mock('../../src/utilities/pagination', () => ({
  paginate: jest.fn((data, params) => ({ data, pagination: null })),
  parsePaginationParams: jest.fn(() => null),
}));

const { exists } = require('../../src/utilities/fs-helpers');
const { resolveServiceUrl } = require('../../src/utilities/url-resolver');
const { execSync } = require('child_process');

describe('Health Routes', () => {
  beforeEach(() => {
    jest.clearAllMocks();
    exists.mockResolvedValue(true);
  });

  describe('GET /api/health/cached', () => {
    it('returns cached health data with 200', async () => {
      const { app } = createApp();
      const res = await request(app).get('/api/health/cached');
      expect(res.status).toBe(200);
      expect(res.body.success).toBe(true);
      expect(res.body).toHaveProperty('health');
      expect(res.body).toHaveProperty('lastCheck');
    });
  });

  describe('GET /api/health/services', () => {
    it('returns empty health when no services file', async () => {
      exists.mockResolvedValue(false);
      const { app } = createApp();
      const res = await request(app).get('/api/health/services');
      expect(res.status).toBe(200);
      expect(res.body.success).toBe(true);
      expect(res.body.health).toEqual({});
    });

    it('returns health for each service', async () => {
      const stateManager = {
        read: jest.fn().mockResolvedValue([
          { id: 'plex', name: 'Plex' },
          { id: 'radarr', name: 'Radarr' },
        ]),
      };
      const fetchT = jest.fn().mockResolvedValue({
        ok: true, status: 200, json: () => ({})
      });
      const { app } = createApp({
        servicesStateManager: stateManager,
        fetchT,
      });
      const res = await request(app).get('/api/health/services');
      expect(res.status).toBe(200);
      expect(res.body.success).toBe(true);
      expect(res.body).toHaveProperty('checkedAt');
    });
  });

  describe('GET /api/health/service/:id', () => {
    it('returns 404 when services file missing', async () => {
      exists.mockResolvedValue(false);
      const { app } = createApp();
      const res = await request(app).get('/api/health/service/plex');
      expect(res.status).toBe(404);
    });

    it('returns 404 when service not found', async () => {
      const stateManager = {
        read: jest.fn().mockResolvedValue([{ id: 'radarr', name: 'Radarr' }]),
      };
      const { app } = createApp({ servicesStateManager: stateManager });
      const res = await request(app).get('/api/health/service/nonexistent');
      expect(res.status).toBe(404);
    });

    it('returns health for existing service', async () => {
      const stateManager = {
        read: jest.fn().mockResolvedValue([{ id: 'plex', name: 'Plex' }]),
      };
      const fetchT = jest.fn().mockResolvedValue({
        ok: true, status: 200, json: () => ({})
      });
      const { app } = createApp({
        servicesStateManager: stateManager,
        fetchT,
      });
      const res = await request(app).get('/api/health/service/plex');
      expect(res.status).toBe(200);
      expect(res.body.success).toBe(true);
      expect(res.body.serviceId).toBe('plex');
    });
  });

  describe('GET /api/health/pylon', () => {
    it('returns configured:false when no pylon', async () => {
      const { app } = createApp({ siteConfig: {} });
      const res = await request(app).get('/api/health/pylon');
      expect(res.status).toBe(200);
      expect(res.body.configured).toBe(false);
    });

    it('returns reachable:true when pylon responds', async () => {
      const fetchT = jest.fn().mockResolvedValue({
        ok: true, status: 200, json: () => ({ status: 'ok' })
      });
      const { app } = createApp({
        siteConfig: { pylon: { url: 'http://pylon.test' } },
        fetchT,
      });
      const res = await request(app).get('/api/health/pylon');
      expect(res.status).toBe(200);
      expect(res.body.configured).toBe(true);
      expect(res.body.reachable).toBe(true);
    });

    it('returns reachable:false when pylon errors', async () => {
      const fetchT = jest.fn().mockRejectedValue(new Error('Connection refused'));
      const { app } = createApp({
        siteConfig: { pylon: { url: 'http://pylon.test' } },
        fetchT,
      });
      const res = await request(app).get('/api/health/pylon');
      expect(res.status).toBe(200);
      expect(res.body.configured).toBe(true);
      expect(res.body.reachable).toBe(false);
    });
  });

  describe('GET /api/health-checks/status', () => {
    it('returns current health checker status', async () => {
      const healthChecker = {
        getCurrentStatus: jest.fn().mockReturnValue({
          svc1: { status: 'up', responseTime: 100 }
        }),
        getServiceStats: jest.fn(),
        configureService: jest.fn(),
        removeService: jest.fn(),
        getOpenIncidents: jest.fn().mockReturnValue([]),
        getIncidentHistory: jest.fn().mockReturnValue([]),
      };
      const { app } = createApp({ healthChecker });
      const res = await request(app).get('/api/health-checks/status');
      expect(res.status).toBe(200);
      expect(res.body.success).toBe(true);
      expect(res.body.status.svc1.status).toBe('up');
    });
  });

  describe('GET /api/health-checks/:serviceId/stats', () => {
    it('returns 404 when service not found', async () => {
      const { app } = createApp();
      const res = await request(app).get('/api/health-checks/unknown/stats');
      expect(res.status).toBe(404);
    });

    it('returns stats when service exists', async () => {
      const healthChecker = {
        getCurrentStatus: jest.fn().mockReturnValue({}),
        getServiceStats: jest.fn().mockReturnValue({
          totalChecks: 100, uptime: 99.5
        }),
        configureService: jest.fn(),
        removeService: jest.fn(),
        getOpenIncidents: jest.fn().mockReturnValue([]),
        getIncidentHistory: jest.fn().mockReturnValue([]),
      };
      const { app } = createApp({ healthChecker });
      const res = await request(app).get('/api/health-checks/svc1/stats');
      expect(res.status).toBe(200);
      expect(res.body.stats.uptime).toBe(99.5);
    });
  });

  describe('POST /api/health-checks/:serviceId/configure', () => {
    it('configures health check for service', async () => {
      const healthChecker = {
        getCurrentStatus: jest.fn().mockReturnValue({}),
        getServiceStats: jest.fn(),
        configureService: jest.fn(),
        removeService: jest.fn(),
        getOpenIncidents: jest.fn().mockReturnValue([]),
        getIncidentHistory: jest.fn().mockReturnValue([]),
      };
      const { app } = createApp({ healthChecker });
      const res = await request(app)
        .post('/api/health-checks/svc1/configure')
        .send({ url: 'http://test.local', timeout: 5000 });
      expect(res.status).toBe(200);
      expect(healthChecker.configureService).toHaveBeenCalledWith('svc1', expect.objectContaining({ url: 'http://test.local' }));
    });
  });

  describe('DELETE /api/health-checks/:serviceId/configure', () => {
    it('removes health check configuration', async () => {
      const healthChecker = {
        getCurrentStatus: jest.fn().mockReturnValue({}),
        getServiceStats: jest.fn(),
        configureService: jest.fn(),
        removeService: jest.fn(),
        getOpenIncidents: jest.fn().mockReturnValue([]),
        getIncidentHistory: jest.fn().mockReturnValue([]),
      };
      const { app } = createApp({ healthChecker });
      const res = await request(app).delete('/api/health-checks/svc1/configure');
      expect(res.status).toBe(200);
      expect(healthChecker.removeService).toHaveBeenCalledWith('svc1');
    });
  });

  describe('GET /api/health-checks/incidents', () => {
    it('returns open incidents', async () => {
      const healthChecker = {
        getCurrentStatus: jest.fn().mockReturnValue({}),
        getServiceStats: jest.fn(),
        configureService: jest.fn(),
        removeService: jest.fn(),
        getOpenIncidents: jest.fn().mockReturnValue([
          { id: 'inc-1', serviceId: 'svc1', type: 'outage', status: 'open' }
        ]),
        getIncidentHistory: jest.fn().mockReturnValue([]),
      };
      const { app } = createApp({ healthChecker });
      const res = await request(app).get('/api/health-checks/incidents');
      expect(res.status).toBe(200);
      expect(res.body.incidents).toHaveLength(1);
      expect(res.body.incidents[0].type).toBe('outage');
    });
  });

  // ===== NEW TESTS FOR DEEPER COVERAGE =====

  describe('GET /api/health/services (deeper scenarios)', () => {
    it('falls back to pylon when direct check fails', async () => {
      const stateManager = {
        read: jest.fn().mockResolvedValue([{ id: 'myapp', name: 'MyApp' }]),
      };
      // HEAD fails, GET fails, pylon succeeds
      const fetchT = jest.fn()
        .mockRejectedValueOnce(new Error('HEAD failed'))   // HEAD in checkDirect
        .mockRejectedValueOnce(new Error('GET failed'))    // GET fallback in checkDirect
        .mockResolvedValueOnce({                           // pylon probe call
          ok: true,
          status: 200,
          json: () => ({ status: 'healthy', statusCode: 200, responseTime: 42 }),
        });
      const { app } = createApp({
        servicesStateManager: stateManager,
        fetchT,
        siteConfig: { pylon: { url: 'http://pylon.test' } },
      });
      const res = await request(app).get('/api/health/services');
      expect(res.status).toBe(200);
      expect(res.body.success).toBe(true);
      expect(res.body.health.myapp).toBeDefined();
      expect(res.body.health.myapp.via).toBe('pylon');
    });

    it('returns unhealthy when both direct and pylon fail', async () => {
      const stateManager = {
        read: jest.fn().mockResolvedValue([{ id: 'deadapp', name: 'DeadApp' }]),
      };
      const fetchT = jest.fn()
        .mockRejectedValueOnce(new Error('HEAD failed'))
        .mockRejectedValueOnce(new Error('GET failed'))
        .mockRejectedValueOnce(new Error('pylon failed'));
      const { app } = createApp({
        servicesStateManager: stateManager,
        fetchT,
        siteConfig: { pylon: { url: 'http://pylon.test' } },
      });
      const res = await request(app).get('/api/health/services');
      expect(res.status).toBe(200);
      expect(res.body.health.deadapp.status).toBe('unhealthy');
      expect(res.body.health.deadapp.reason).toMatch(/direct \+ pylon/);
    });

    it('returns unhealthy with "fetch failed" when direct fails and no pylon configured', async () => {
      const stateManager = {
        read: jest.fn().mockResolvedValue([{ id: 'deadapp', name: 'DeadApp' }]),
      };
      const fetchT = jest.fn()
        .mockRejectedValueOnce(new Error('HEAD failed'))
        .mockRejectedValueOnce(new Error('GET failed'));
      const { app } = createApp({
        servicesStateManager: stateManager,
        fetchT,
        siteConfig: {},  // no pylon
      });
      const res = await request(app).get('/api/health/services');
      expect(res.status).toBe(200);
      expect(res.body.health.deadapp.status).toBe('unhealthy');
      expect(res.body.health.deadapp.reason).toBe('fetch failed');
    });

    it('skips services without id or name', async () => {
      const stateManager = {
        read: jest.fn().mockResolvedValue([
          { id: 'valid', name: 'Valid' },
          { url: 'http://no-id-or-name.test' },  // no id, no name
        ]),
      };
      const fetchT = jest.fn().mockResolvedValue({ ok: true, status: 200, json: () => ({}) });
      const { app } = createApp({
        servicesStateManager: stateManager,
        fetchT,
      });
      const res = await request(app).get('/api/health/services');
      expect(res.status).toBe(200);
      // Only the valid service should appear
      expect(Object.keys(res.body.health)).toEqual(['valid']);
    });

    it('returns unknown status when no URL configured for service', async () => {
      resolveServiceUrl.mockReturnValueOnce(null);
      const stateManager = {
        read: jest.fn().mockResolvedValue([{ id: 'nourl', name: 'NoUrl' }]),
      };
      const { app } = createApp({
        servicesStateManager: stateManager,
      });
      const res = await request(app).get('/api/health/services');
      expect(res.status).toBe(200);
      expect(res.body.health.nourl.status).toBe('unknown');
      expect(res.body.health.nourl.reason).toBe('No URL configured');
    });

    it('returns error status when exception occurs during check', async () => {
      // resolveServiceUrl throws an error
      resolveServiceUrl.mockImplementationOnce(() => { throw new Error('resolve boom'); });
      const stateManager = {
        read: jest.fn().mockResolvedValue([{ id: 'boom', name: 'Boom' }]),
      };
      const { app } = createApp({
        servicesStateManager: stateManager,
      });
      const res = await request(app).get('/api/health/services');
      expect(res.status).toBe(200);
      expect(res.body.health.boom.status).toBe('error');
      expect(res.body.health.boom.reason).toBe('resolve boom');
    });

    it('handles servicesData as object with .services property', async () => {
      const stateManager = {
        read: jest.fn().mockResolvedValue({
          services: [{ id: 'wrapped', name: 'Wrapped' }],
        }),
      };
      const fetchT = jest.fn().mockResolvedValue({ ok: true, status: 200, json: () => ({}) });
      const { app } = createApp({
        servicesStateManager: stateManager,
        fetchT,
      });
      const res = await request(app).get('/api/health/services');
      expect(res.status).toBe(200);
      expect(res.body.health.wrapped).toBeDefined();
      expect(res.body.health.wrapped.status).toBe('healthy');
    });

    it('reports unhealthy when server returns 500+', async () => {
      const stateManager = {
        read: jest.fn().mockResolvedValue([{ id: 'err500', name: 'Err500' }]),
      };
      const fetchT = jest.fn().mockResolvedValue({ ok: false, status: 502, json: () => ({}) });
      const { app } = createApp({
        servicesStateManager: stateManager,
        fetchT,
      });
      const res = await request(app).get('/api/health/services');
      expect(res.status).toBe(200);
      expect(res.body.health.err500.status).toBe('unhealthy');
      expect(res.body.health.err500.statusCode).toBe(502);
    });
  });

  describe('GET /api/health/service/:id (pylon fallback)', () => {
    it('falls back to pylon when direct fails', async () => {
      const stateManager = {
        read: jest.fn().mockResolvedValue([{ id: 'plex', name: 'Plex' }]),
      };
      const fetchT = jest.fn()
        .mockRejectedValueOnce(new Error('HEAD failed'))
        .mockRejectedValueOnce(new Error('GET failed'))
        .mockResolvedValueOnce({
          ok: true,
          status: 200,
          json: () => ({ status: 'healthy', statusCode: 200, responseTime: 55 }),
        });
      const { app } = createApp({
        servicesStateManager: stateManager,
        fetchT,
        siteConfig: { pylon: { url: 'http://pylon.test', key: 'secret123' } },
      });
      const res = await request(app).get('/api/health/service/plex');
      expect(res.status).toBe(200);
      expect(res.body.health.via).toBe('pylon');
      expect(res.body.health.status).toBe('healthy');
      // Verify pylon key header was sent
      const pylonCall = fetchT.mock.calls[2];
      expect(pylonCall[1].headers['x-pylon-key']).toBe('secret123');
    });

    it('returns unhealthy when both direct and pylon fail', async () => {
      const stateManager = {
        read: jest.fn().mockResolvedValue([{ id: 'plex', name: 'Plex' }]),
      };
      const fetchT = jest.fn()
        .mockRejectedValueOnce(new Error('HEAD failed'))
        .mockRejectedValueOnce(new Error('GET failed'))
        .mockRejectedValueOnce(new Error('pylon failed'));
      const { app } = createApp({
        servicesStateManager: stateManager,
        fetchT,
        siteConfig: { pylon: { url: 'http://pylon.test' } },
      });
      const res = await request(app).get('/api/health/service/plex');
      expect(res.status).toBe(200);
      expect(res.body.health.status).toBe('unhealthy');
      expect(res.body.health.reason).toMatch(/direct \+ pylon/);
    });

    it('returns unhealthy with "fetch failed" when direct fails and no pylon', async () => {
      const stateManager = {
        read: jest.fn().mockResolvedValue([{ id: 'plex', name: 'Plex' }]),
      };
      const fetchT = jest.fn()
        .mockRejectedValueOnce(new Error('HEAD failed'))
        .mockRejectedValueOnce(new Error('GET failed'));
      const { app } = createApp({
        servicesStateManager: stateManager,
        fetchT,
        siteConfig: {},  // no pylon
      });
      const res = await request(app).get('/api/health/service/plex');
      expect(res.status).toBe(200);
      expect(res.body.health.status).toBe('unhealthy');
      expect(res.body.health.reason).toBe('fetch failed');
    });
  });

  describe('GET /api/health/probe', () => {
    it('returns health result when url provided and direct check succeeds', async () => {
      const fetchT = jest.fn().mockResolvedValue({ ok: true, status: 200 });
      const { app } = createApp({ fetchT });
      const res = await request(app).get('/api/health/probe?url=http://example.com');
      expect(res.status).toBe(200);
      expect(res.body.status).toBe('healthy');
      expect(res.body.statusCode).toBe(200);
      expect(res.body.url).toBe('http://example.com');
    });

    it('returns unhealthy when direct check completely fails', async () => {
      const fetchT = jest.fn()
        .mockRejectedValueOnce(new Error('HEAD failed'))
        .mockRejectedValueOnce(new Error('GET failed'));
      const { app } = createApp({ fetchT });
      const res = await request(app).get('/api/health/probe?url=http://dead.test');
      expect(res.status).toBe(200);
      expect(res.body.status).toBe('unhealthy');
      expect(res.body.reason).toBe('fetch failed');
      expect(res.body.url).toBe('http://dead.test');
    });

    it('returns error when no url parameter provided', async () => {
      const { app } = createApp();
      const res = await request(app).get('/api/health/probe');
      expect(res.status).toBe(400);
    });
  });

  describe('GET /api/health/ca', () => {
    it('returns healthy when cert has >90 days remaining', async () => {
      exists.mockResolvedValue(true);
      const futureDate = new Date();
      futureDate.setDate(futureDate.getDate() + 365);
      const dateStr = futureDate.toUTCString();
      execSync.mockReturnValue(`notBefore=Jan  1 00:00:00 2024 GMT\nnotAfter=${dateStr}`);
      const { app } = createApp();
      const res = await request(app).get('/api/health/ca');
      expect(res.status).toBe(200);
      expect(res.body.caStatus).toBe('healthy');
      expect(res.body.daysUntilExpiration).toBeGreaterThan(90);
    });

    it('returns warning when cert has 30-90 days remaining', async () => {
      exists.mockResolvedValue(true);
      const futureDate = new Date();
      futureDate.setDate(futureDate.getDate() + 60);
      const dateStr = futureDate.toUTCString();
      execSync.mockReturnValue(`notBefore=Jan  1 00:00:00 2024 GMT\nnotAfter=${dateStr}`);
      const { app } = createApp();
      const res = await request(app).get('/api/health/ca');
      expect(res.status).toBe(200);
      expect(res.body.caStatus).toBe('warning');
      expect(res.body.daysUntilExpiration).toBeLessThan(90);
      expect(res.body.daysUntilExpiration).toBeGreaterThanOrEqual(30);
    });

    it('returns critical when cert has <30 days remaining', async () => {
      exists.mockResolvedValue(true);
      const futureDate = new Date();
      futureDate.setDate(futureDate.getDate() + 15);
      const dateStr = futureDate.toUTCString();
      execSync.mockReturnValue(`notBefore=Jan  1 00:00:00 2024 GMT\nnotAfter=${dateStr}`);
      const { app } = createApp();
      const res = await request(app).get('/api/health/ca');
      expect(res.status).toBe(200);
      expect(res.body.caStatus).toBe('critical');
      expect(res.body.daysUntilExpiration).toBeLessThan(30);
      expect(res.body.daysUntilExpiration).toBeGreaterThanOrEqual(0);
    });

    it('returns critical when cert has <7 days remaining', async () => {
      exists.mockResolvedValue(true);
      const futureDate = new Date();
      futureDate.setDate(futureDate.getDate() + 3);
      const dateStr = futureDate.toUTCString();
      execSync.mockReturnValue(`notBefore=Jan  1 00:00:00 2024 GMT\nnotAfter=${dateStr}`);
      const { app } = createApp();
      const res = await request(app).get('/api/health/ca');
      expect(res.status).toBe(200);
      expect(res.body.caStatus).toBe('critical');
      expect(res.body.daysUntilExpiration).toBeLessThan(7);
    });

    it('returns critical when cert is expired', async () => {
      exists.mockResolvedValue(true);
      const pastDate = new Date();
      pastDate.setDate(pastDate.getDate() - 10);
      const dateStr = pastDate.toUTCString();
      execSync.mockReturnValue(`notBefore=Jan  1 00:00:00 2024 GMT\nnotAfter=${dateStr}`);
      const { app } = createApp();
      const res = await request(app).get('/api/health/ca');
      expect(res.status).toBe(200);
      expect(res.body.caStatus).toBe('critical');
      expect(res.body.daysUntilExpiration).toBeLessThan(0);
      expect(res.body.message).toMatch(/EXPIRED/);
    });

    it('returns error when cert file not found', async () => {
      exists.mockResolvedValue(false);
      const { app } = createApp();
      const res = await request(app).get('/api/health/ca');
      expect(res.status).toBe(404);
      expect(res.body.caStatus).toBe('error');
      expect(res.body.error).toMatch(/not found/);
      expect(res.body.daysUntilExpiration).toBeNull();
    });

    it('returns error when execSync throws', async () => {
      exists.mockResolvedValue(true);
      execSync.mockImplementation(() => { throw new Error('openssl not found'); });
      const { app } = createApp();
      const res = await request(app).get('/api/health/ca');
      expect(res.status).toBe(500);
      expect(res.body.caStatus).toBe('error');
      expect(res.body.error).toBe('openssl not found');
      expect(res.body.daysUntilExpiration).toBeNull();
    });
  });

  describe('GET /api/health-checks/incidents/history', () => {
    it('returns incident history', async () => {
      const healthChecker = {
        getCurrentStatus: jest.fn().mockReturnValue({}),
        getServiceStats: jest.fn(),
        configureService: jest.fn(),
        removeService: jest.fn(),
        getOpenIncidents: jest.fn().mockReturnValue([]),
        getIncidentHistory: jest.fn().mockReturnValue([
          { id: 'inc-1', serviceId: 'svc1', type: 'outage', resolvedAt: '2025-01-01T00:00:00Z' },
          { id: 'inc-2', serviceId: 'svc2', type: 'degraded', resolvedAt: '2025-01-02T00:00:00Z' },
        ]),
      };
      const { app } = createApp({ healthChecker });
      const res = await request(app).get('/api/health-checks/incidents/history');
      expect(res.status).toBe(200);
      expect(res.body.success).toBe(true);
      expect(res.body.history).toHaveLength(2);
      expect(res.body.history[0].id).toBe('inc-1');
      expect(res.body.history[1].type).toBe('degraded');
    });
  });

  describe('GET /api/health/pylon (with key)', () => {
    it('sends x-pylon-key header when key is configured', async () => {
      const fetchT = jest.fn().mockResolvedValue({
        ok: true, status: 200, json: () => ({ status: 'ok' }),
      });
      const { app } = createApp({
        siteConfig: { pylon: { url: 'http://pylon.test', key: 'my-secret-key' } },
        fetchT,
      });
      const res = await request(app).get('/api/health/pylon');
      expect(res.status).toBe(200);
      expect(res.body.configured).toBe(true);
      expect(res.body.reachable).toBe(true);
      // Verify the x-pylon-key header was sent
      const fetchCall = fetchT.mock.calls[0];
      expect(fetchCall[1].headers['x-pylon-key']).toBe('my-secret-key');
    });
  });
});
