import express from 'express';
import multer from 'multer';
import path from 'path';
import {
  listMedia,
  createMedia,
  getMediaBySn,
  fetchOriginalImage,
  listCctv,
  listSatRequests,
  createSatRequest,
  updateSatRequestStatus,
  isValidSatStatus,
  requestOilInference,
  checkInferenceHealth,
  stitchImages,
  listDroneStreams,
  startDroneStream,
  stopDroneStream,
  getHlsDirectory,
} from './aerialService.js';
import { isValidNumber } from '../middleware/security.js';
import { requireAuth, requirePermission } from '../auth/authMiddleware.js';

const router = express.Router();
const stitchUpload = multer({ storage: multer.memoryStorage(), limits: { fileSize: 50 * 1024 * 1024 } });

// ============================================================
// AERIAL_MEDIA 라우트
// ============================================================

// GET /api/aerial/media — 미디어 목록
router.get('/media', requireAuth, requirePermission('aerial', 'READ'), async (req, res) => {
  try {
    const { equipType, mediaType, acdntSn, search } = req.query;
    const acdntSnNum = acdntSn ? parseInt(acdntSn as string, 10) : undefined;
    if (acdntSn && !isValidNumber(acdntSnNum, 1, 999999)) {
      res.status(400).json({ error: '유효하지 않은 사고 번호' });
      return;
    }
    const items = await listMedia({
      equipType: equipType as string | undefined,
      mediaType: mediaType as string | undefined,
      acdntSn: acdntSnNum,
      search: search as string | undefined,
    });
    res.json(items);
  } catch (err) {
    console.error('[aerial] 미디어 목록 오류:', err);
    res.status(500).json({ error: '미디어 목록 조회 실패' });
  }
});

// POST /api/aerial/media — 미디어 메타 등록
router.post('/media', requireAuth, requirePermission('aerial', 'CREATE'), async (req, res) => {
  try {
    const {
      acdntSn, fileNm, orgnlNm, filePath, lon, lat, locDc,
      equipTpCd, equipNm, mediaTpCd, takngDtm, fileSz, resolution,
    } = req.body;
    if (!fileNm) {
      res.status(400).json({ error: '파일명은 필수입니다.' });
      return;
    }
    const result = await createMedia({
      acdntSn, fileNm, orgnlNm, filePath, lon, lat, locDc,
      equipTpCd, equipNm, mediaTpCd, takngDtm, fileSz, resolution,
    });
    res.status(201).json(result);
  } catch (err) {
    console.error('[aerial] 미디어 등록 오류:', err);
    res.status(500).json({ error: '미디어 등록 실패' });
  }
});

// GET /api/aerial/media/:sn/download — 원본 이미지 다운로드
router.get('/media/:sn/download', requireAuth, requirePermission('aerial', 'READ'), async (req, res) => {
  try {
    const sn = parseInt(req.params['sn'] as string, 10);
    if (!isValidNumber(sn, 1, 999999)) {
      res.status(400).json({ error: '유효하지 않은 미디어 번호' });
      return;
    }

    const media = await getMediaBySn(sn);
    if (!media) {
      res.status(404).json({ error: '미디어를 찾을 수 없습니다.' });
      return;
    }

    // fileId 추출: FILE_NM의 앞 36자가 UUID 형식인지 검증 (이미지 분석 생성 레코드만 다운로드 가능)
    const fileId = media.fileNm.substring(0, 36);
    const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
    if (!UUID_PATTERN.test(fileId) || !media.equipNm) {
      res.status(404).json({ error: '다운로드 가능한 이미지가 없습니다.' });
      return;
    }

    const buffer = await fetchOriginalImage(media.equipNm, fileId);
    const downloadName = media.orgnlNm ?? media.fileNm;
    res.setHeader('Content-Type', 'image/jpeg');
    res.setHeader('Content-Disposition', `attachment; filename*=UTF-8''${encodeURIComponent(downloadName)}`);
    res.send(buffer);
  } catch (err) {
    console.error('[aerial] 이미지 다운로드 오류:', err);
    res.status(502).json({ error: '이미지 다운로드 실패' });
  }
});

// ============================================================
// CCTV_CAMERA 라우트
// ============================================================

// GET /api/aerial/cctv — CCTV 목록
router.get('/cctv', requireAuth, requirePermission('aerial', 'READ'), async (req, res) => {
  try {
    const { region, status } = req.query;
    const items = await listCctv({
      region: region as string | undefined,
      status: status as string | undefined,
    });
    res.json(items);
  } catch (err) {
    console.error('[aerial] CCTV 목록 오류:', err);
    res.status(500).json({ error: 'CCTV 목록 조회 실패' });
  }
});

// ============================================================
// KBS 재난안전포탈 CCTV HLS 리졸버
// ============================================================

/** KBS cctvId → 실제 HLS m3u8 URL 캐시 (5분 TTL) */
const kbsHlsCache = new Map<string, { url: string; ts: number }>();
const KBS_CACHE_TTL = 5 * 60 * 1000;

// GET /api/aerial/cctv/kbs-hls/:cctvId/stream.m3u8 — KBS CCTV를 HLS로 리졸브 + 프록시
router.get('/cctv/kbs-hls/:cctvId/stream.m3u8', async (req, res) => {
  try {
    const cctvId = req.params.cctvId as string;
    if (!/^\d+$/.test(cctvId)) {
      res.status(400).json({ error: '유효하지 않은 cctvId' });
      return;
    }

    let m3u8Url: string | null = null;

    // 캐시 확인
    const cached = kbsHlsCache.get(cctvId);
    if (cached && Date.now() - cached.ts < KBS_CACHE_TTL) {
      m3u8Url = cached.url;
    } else {
      // 1단계: KBS 팝업 API에서 loomex API URL 추출
      const popupRes = await fetch(
        `https://d.kbs.co.kr/special/cctv/cctvPopup?type=LIVE&cctvId=${cctvId}`,
        { headers: { 'User-Agent': 'Mozilla/5.0 (compatible; WING-OPS/1.0)' } },
      );
      if (!popupRes.ok) {
        res.status(502).json({ error: 'KBS 팝업 API 응답 실패' });
        return;
      }
      const popupHtml = await popupRes.text();
      const urlMatch = popupHtml.match(/id="url"\s+value="([^"]+)"/);
      if (!urlMatch) {
        res.status(502).json({ error: 'KBS 스트림 URL을 찾을 수 없습니다' });
        return;
      }

      // 2단계: loomex API에서 실제 m3u8 URL 획득
      const loomexRes = await fetch(urlMatch[1], {
        headers: { 'User-Agent': 'Mozilla/5.0 (compatible; WING-OPS/1.0)' },
      });
      if (!loomexRes.ok) {
        res.status(502).json({ error: 'KBS 스트림 서버 응답 실패' });
        return;
      }
      m3u8Url = (await loomexRes.text()).trim();
      kbsHlsCache.set(cctvId, { url: m3u8Url, ts: Date.now() });
    }

    // 3단계: m3u8 매니페스트를 프록시하여 세그먼트 URL 재작성
    const upstream = await fetch(m3u8Url, {
      headers: { 'User-Agent': 'Mozilla/5.0 (compatible; WING-OPS/1.0)' },
    });
    if (!upstream.ok) {
      // 캐시 무효화 후 재시도 유도
      kbsHlsCache.delete(cctvId);
      res.status(502).json({ error: 'HLS 매니페스트 가져오기 실패' });
      return;
    }

    const text = await upstream.text();
    const baseUrl = m3u8Url.substring(0, m3u8Url.lastIndexOf('/') + 1);
    const proxyBase = '/api/aerial/cctv/stream-proxy?url=';

    const rewritten = text.replace(/^(?!#)(\S+)/gm, (line) => {
      if (line.startsWith('http://') || line.startsWith('https://')) {
        return `${proxyBase}${encodeURIComponent(line)}`;
      }
      return `${proxyBase}${encodeURIComponent(baseUrl + line)}`;
    });

    res.set({
      'Content-Type': 'application/vnd.apple.mpegurl',
      'Cache-Control': 'no-cache',
      'Access-Control-Allow-Origin': '*',
    });
    res.send(rewritten);
  } catch (err) {
    console.error('[aerial] KBS HLS 리졸버 오류:', err);
    res.status(502).json({ error: 'KBS HLS 스트림 리졸브 실패' });
  }
});

// ============================================================
// CCTV HLS 스트림 프록시 (CORS 우회)
// ============================================================

/** 허용 도메인 목록 */
const ALLOWED_STREAM_HOSTS = [
  'www.khoa.go.kr',
  'kbsapi.loomex.net',
  'kbscctv-cache.loomex.net',
];

// GET /api/aerial/cctv/stream-proxy — HLS 스트림 프록시 (호스트 화이트리스트로 보안)
router.get('/cctv/stream-proxy', async (req, res) => {
  try {
    const targetUrl = req.query.url as string | undefined;
    if (!targetUrl) {
      res.status(400).json({ error: 'url 파라미터가 필요합니다.' });
      return;
    }

    let parsed: URL;
    try {
      parsed = new URL(targetUrl);
    } catch {
      res.status(400).json({ error: '유효하지 않은 URL' });
      return;
    }

    if (!ALLOWED_STREAM_HOSTS.includes(parsed.hostname)) {
      res.status(403).json({ error: '허용되지 않은 스트림 호스트' });
      return;
    }

    const upstream = await fetch(targetUrl, {
      headers: { 'User-Agent': 'Mozilla/5.0 (compatible; WING-OPS/1.0)' },
    });

    if (!upstream.ok) {
      res.status(upstream.status).json({ error: `스트림 서버 응답: ${upstream.status}` });
      return;
    }

    const contentType = upstream.headers.get('content-type') || '';

    // .m3u8 매니페스트: 상대 URL을 프록시 URL로 재작성
    if (targetUrl.includes('.m3u8') || contentType.includes('mpegurl') || contentType.includes('m3u8')) {
      const text = await upstream.text();
      const baseUrl = targetUrl.substring(0, targetUrl.lastIndexOf('/') + 1);
      const proxyBase = '/api/aerial/cctv/stream-proxy?url=';

      const rewritten = text.replace(/^(?!#)(\S+)/gm, (line) => {
        if (line.startsWith('http://') || line.startsWith('https://')) {
          return `${proxyBase}${encodeURIComponent(line)}`;
        }
        return `${proxyBase}${encodeURIComponent(baseUrl + line)}`;
      });

      res.set({
        'Content-Type': 'application/vnd.apple.mpegurl',
        'Cache-Control': 'no-cache',
        'Access-Control-Allow-Origin': '*',
      });
      res.send(rewritten);
      return;
    }

    // .ts 세그먼트 등: 바이너리 스트리밍
    res.set({
      'Content-Type': contentType || 'video/mp2t',
      'Cache-Control': 'no-cache',
      'Access-Control-Allow-Origin': '*',
    });

    const buffer = Buffer.from(await upstream.arrayBuffer());
    res.send(buffer);
  } catch (err) {
    console.error('[aerial] CCTV 스트림 프록시 오류:', err);
    res.status(502).json({ error: '스트림 프록시 실패' });
  }
});

// ============================================================
// DRONE STREAM 라우트 (RTSP → HLS)
// ============================================================

// GET /api/aerial/drone/streams — 드론 스트림 목록 + 상태
router.get('/drone/streams', requireAuth, requirePermission('aerial', 'READ'), async (_req, res) => {
  try {
    const streams = listDroneStreams();
    res.json(streams);
  } catch (err) {
    console.error('[aerial] 드론 스트림 목록 오류:', err);
    res.status(500).json({ error: '드론 스트림 목록 조회 실패' });
  }
});

// POST /api/aerial/drone/streams/:id/start — 드론 스트림 시작 (RTSP→HLS 변환)
router.post('/drone/streams/:id/start', requireAuth, requirePermission('aerial', 'READ'), async (req, res) => {
  try {
    const result = startDroneStream(req.params.id as string);
    if (!result.success) {
      res.status(400).json({ error: result.error });
      return;
    }
    res.json(result);
  } catch (err) {
    console.error('[aerial] 드론 스트림 시작 오류:', err);
    res.status(500).json({ error: '드론 스트림 시작 실패' });
  }
});

// POST /api/aerial/drone/streams/:id/stop — 드론 스트림 중지
router.post('/drone/streams/:id/stop', requireAuth, requirePermission('aerial', 'READ'), async (req, res) => {
  try {
    const result = stopDroneStream(req.params.id as string);
    res.json(result);
  } catch (err) {
    console.error('[aerial] 드론 스트림 중지 오류:', err);
    res.status(500).json({ error: '드론 스트림 중지 실패' });
  }
});

// GET /api/aerial/drone/hls/:id/* — HLS 정적 파일 서빙 (.m3u8, .ts)
router.get('/drone/hls/:id/*', async (req, res) => {
  try {
    const id = req.params.id as string;
    const hlsDir = getHlsDirectory(id);
    if (!hlsDir) {
      res.status(404).json({ error: '스트림을 찾을 수 없습니다' });
      return;
    }

    // wildcard: req.params[0] contains the rest of the path
    // Cast through unknown because @types/express v5 types the wildcard key as string[]
    const rawParams = req.params as unknown as Record<string, string | string[]>;
    const wildcardRaw = rawParams['0'] ?? '';
    const wildcardParam = Array.isArray(wildcardRaw) ? wildcardRaw.join('/') : wildcardRaw;
    const filePath = path.join(hlsDir, wildcardParam);

    // Security: prevent path traversal
    if (!filePath.startsWith(hlsDir)) {
      res.status(403).json({ error: '접근 거부' });
      return;
    }

    const ext = path.extname(filePath).toLowerCase();
    const contentType = ext === '.m3u8' ? 'application/vnd.apple.mpegurl'
      : ext === '.ts' ? 'video/mp2t'
      : 'application/octet-stream';

    res.set({
      'Content-Type': contentType,
      'Cache-Control': 'no-cache',
      'Access-Control-Allow-Origin': '*',
    });
    res.sendFile(filePath);
  } catch (err) {
    console.error('[aerial] HLS 파일 서빙 오류:', err);
    res.status(404).json({ error: 'HLS 파일을 찾을 수 없습니다' });
  }
});

// ============================================================
// SAT_REQUEST 라우트
// ============================================================

// GET /api/aerial/satellite — 위성 촬영 요청 목록
router.get('/satellite', requireAuth, requirePermission('aerial', 'READ'), async (req, res) => {
  try {
    const { status } = req.query;
    const items = await listSatRequests({
      status: status as string | undefined,
    });
    res.json(items);
  } catch (err) {
    console.error('[aerial] 위성 요청 목록 오류:', err);
    res.status(500).json({ error: '위성 요청 목록 조회 실패' });
  }
});

// POST /api/aerial/satellite — 위성 촬영 요청 생성
router.post('/satellite', requireAuth, requirePermission('aerial', 'CREATE'), async (req, res) => {
  try {
    const {
      reqCd, acdntSn, lon, lat, zoneDc, coordDc, zoneAreaKm2,
      satNm, providerNm, resolution, purposeDc, reqstrNm, reqDtm, expectedRcvDtm,
    } = req.body;
    if (!reqCd) {
      res.status(400).json({ error: '요청코드는 필수입니다.' });
      return;
    }
    const result = await createSatRequest({
      reqCd, acdntSn, lon, lat, zoneDc, coordDc, zoneAreaKm2,
      satNm, providerNm, resolution, purposeDc, reqstrNm, reqDtm, expectedRcvDtm,
    });
    res.status(201).json(result);
  } catch (err) {
    console.error('[aerial] 위성 요청 생성 오류:', err);
    res.status(500).json({ error: '위성 요청 생성 실패' });
  }
});

// POST /api/aerial/satellite/:sn/status — 위성 요청 상태 변경
router.post('/satellite/:sn/status', requireAuth, requirePermission('aerial', 'CREATE'), async (req, res) => {
  try {
    const sn = parseInt(req.params.sn as string, 10);
    if (!isValidNumber(sn, 1, 999999)) {
      res.status(400).json({ error: '유효하지 않은 요청 번호' });
      return;
    }
    const { sttsCd } = req.body;
    if (!sttsCd || !isValidSatStatus(sttsCd)) {
      res.status(400).json({ error: '유효하지 않은 상태값 (PENDING/SHOOTING/COMPLETED/CANCELLED)' });
      return;
    }
    await updateSatRequestStatus(sn, sttsCd);
    res.json({ success: true });
  } catch (err) {
    console.error('[aerial] 위성 요청 상태 변경 오류:', err);
    res.status(500).json({ error: '위성 요청 상태 변경 실패' });
  }
});

// ============================================================
// UP42 위성 패스 조회 (실시간 위성 목록 + 궤도)
// ============================================================

/** 한국 주변 위성 패스 시뮬레이션 데이터 (UP42 API 연동 시 교체) */
function generateKoreaSatellitePasses() {
  const now = new Date();
  const passes = [
    {
      id: 'pass-kmp3a-1', satellite: 'KOMPSAT-3A', provider: 'KARI', type: 'optical',
      resolution: '0.5m', color: '#a855f7',
      startTime: new Date(now.getTime() + 2 * 3600000).toISOString(),
      endTime: new Date(now.getTime() + 2 * 3600000 + 14 * 60000).toISOString(),
      maxElevation: 72, direction: 'descending',
      orbit: [
        { lat: 42.0, lon: 126.5 }, { lat: 40.5, lon: 127.0 }, { lat: 39.0, lon: 127.4 },
        { lat: 37.5, lon: 127.8 }, { lat: 36.0, lon: 128.1 }, { lat: 34.5, lon: 128.4 },
        { lat: 33.0, lon: 128.6 }, { lat: 31.5, lon: 128.8 },
      ],
    },
    {
      id: 'pass-pneo-1', satellite: 'Pléiades Neo', provider: 'Airbus', type: 'optical',
      resolution: '0.3m', color: '#06b6d4',
      startTime: new Date(now.getTime() + 3.5 * 3600000).toISOString(),
      endTime: new Date(now.getTime() + 3.5 * 3600000 + 12 * 60000).toISOString(),
      maxElevation: 65, direction: 'ascending',
      orbit: [
        { lat: 30.0, lon: 130.0 }, { lat: 31.5, lon: 129.2 }, { lat: 33.0, lon: 128.5 },
        { lat: 34.5, lon: 127.8 }, { lat: 36.0, lon: 127.1 }, { lat: 37.5, lon: 126.4 },
        { lat: 39.0, lon: 125.8 }, { lat: 40.5, lon: 125.2 },
      ],
    },
    {
      id: 'pass-s1-1', satellite: 'Sentinel-1 SAR', provider: 'ESA', type: 'sar',
      resolution: '20m', color: '#f59e0b',
      startTime: new Date(now.getTime() + 5 * 3600000).toISOString(),
      endTime: new Date(now.getTime() + 5 * 3600000 + 18 * 60000).toISOString(),
      maxElevation: 58, direction: 'descending',
      orbit: [
        { lat: 43.0, lon: 124.0 }, { lat: 41.0, lon: 125.0 }, { lat: 39.0, lon: 126.0 },
        { lat: 37.0, lon: 126.8 }, { lat: 35.0, lon: 127.5 }, { lat: 33.0, lon: 128.0 },
        { lat: 31.0, lon: 128.5 },
      ],
    },
    {
      id: 'pass-wv3-1', satellite: 'Maxar WorldView-3', provider: 'Maxar', type: 'optical',
      resolution: '0.31m', color: '#3b82f6',
      startTime: new Date(now.getTime() + 8 * 3600000).toISOString(),
      endTime: new Date(now.getTime() + 8 * 3600000 + 10 * 60000).toISOString(),
      maxElevation: 80, direction: 'descending',
      orbit: [
        { lat: 41.0, lon: 129.5 }, { lat: 39.5, lon: 129.0 }, { lat: 38.0, lon: 128.5 },
        { lat: 36.5, lon: 128.0 }, { lat: 35.0, lon: 127.5 }, { lat: 33.5, lon: 127.0 },
        { lat: 32.0, lon: 126.5 },
      ],
    },
    {
      id: 'pass-skysat-1', satellite: 'SkySat', provider: 'Planet', type: 'optical',
      resolution: '0.5m', color: '#22c55e',
      startTime: new Date(now.getTime() + 12 * 3600000).toISOString(),
      endTime: new Date(now.getTime() + 12 * 3600000 + 8 * 60000).toISOString(),
      maxElevation: 55, direction: 'ascending',
      orbit: [
        { lat: 31.0, lon: 127.0 }, { lat: 32.5, lon: 126.5 }, { lat: 34.0, lon: 126.0 },
        { lat: 35.5, lon: 125.5 }, { lat: 37.0, lon: 125.0 }, { lat: 38.5, lon: 124.5 },
        { lat: 40.0, lon: 124.0 },
      ],
    },
    {
      id: 'pass-s2-1', satellite: 'Sentinel-2', provider: 'ESA', type: 'optical',
      resolution: '10m', color: '#ec4899',
      startTime: new Date(now.getTime() + 18 * 3600000).toISOString(),
      endTime: new Date(now.getTime() + 18 * 3600000 + 20 * 60000).toISOString(),
      maxElevation: 62, direction: 'descending',
      orbit: [
        { lat: 42.0, lon: 128.0 }, { lat: 40.0, lon: 128.0 }, { lat: 38.0, lon: 128.0 },
        { lat: 36.0, lon: 128.0 }, { lat: 34.0, lon: 128.0 }, { lat: 32.0, lon: 128.0 },
      ],
    },
  ];
  return passes;
}

// GET /api/aerial/satellite/passes — 한국 주변 실시간 위성 패스 목록 (UP42 API 연동 준비)
router.get('/satellite/passes', requireAuth, requirePermission('aerial', 'READ'), async (_req, res) => {
  try {
    // TODO: UP42 API 연동 시 아래 코드를 실제 API 호출로 교체
    // const token = await getUp42Token()
    // const passes = await fetchUp42Catalog(token, { bbox: [124, 33, 132, 39] })
    const passes = generateKoreaSatellitePasses();
    res.json({ passes, source: 'simulation', note: 'UP42 API 연동 시 실제 데이터로 교체 예정' });
  } catch (err) {
    console.error('[aerial] 위성 패스 조회 오류:', err);
    res.status(500).json({ error: '위성 패스 조회 실패' });
  }
});

// ============================================================
// OIL INFERENCE 라우트
// ============================================================

// POST /api/aerial/oil-detect — 오일 유출 감지 (GPU 추론 서버 프록시)
// base64 이미지 전송을 위해 3MB JSON 파서 적용
router.post('/oil-detect', express.json({ limit: '3mb' }), requireAuth, requirePermission('aerial', 'READ'), async (req, res) => {
  try {
    const { image } = req.body;
    if (!image || typeof image !== 'string') {
      res.status(400).json({ error: 'image (base64) 필드가 필요합니다' });
      return;
    }

    // base64 크기 제한 (약 2MB 이미지)
    if (image.length > 3_000_000) {
      res.status(400).json({ error: '이미지 크기가 너무 큽니다 (최대 2MB)' });
      return;
    }

    const result = await requestOilInference(image);
    res.json(result);
  } catch (err) {
    const message = err instanceof Error ? err.message : String(err);
    if (message.includes('abort') || message.includes('timeout')) {
      console.error('[aerial] 추론 서버 타임아웃:', message);
      res.status(504).json({ error: '추론 서버 응답 시간 초과' });
      return;
    }
    console.error('[aerial] 오일 감지 오류:', err);
    res.status(503).json({ error: '추론 서버 연결 불가' });
  }
});

// ============================================================
// STITCH (이미지 합성) 라우트
// ============================================================

// POST /api/aerial/stitch — 여러 이미지를 합성하여 JPEG 반환
router.post(
  '/stitch',
  requireAuth,
  requirePermission('aerial', 'READ'),
  stitchUpload.array('files', 6),
  async (req, res) => {
    try {
      const files = req.files as Express.Multer.File[];
      if (!files || files.length < 2) {
        res.status(400).json({ error: '이미지를 최소 2장 이상 선택해주세요.' });
        return;
      }
      const fileId = `stitch_${Date.now()}`;
      const buffer = await stitchImages(files, fileId);
      res.type('image/jpeg').send(buffer);
    } catch (err) {
      const message = err instanceof Error ? err.message : String(err);
      if (message.includes('abort') || message.includes('timeout')) {
        console.error('[aerial] 스티칭 서버 타임아웃:', message);
        res.status(504).json({ error: '이미지 합성 서버 응답 시간 초과' });
        return;
      }
      console.error('[aerial] 이미지 합성 오류:', err);
      res.status(503).json({ error: '이미지 합성 서버 연결 불가' });
    }
  }
);

// GET /api/aerial/oil-detect/health — 추론 서버 상태 확인
router.get('/oil-detect/health', requireAuth, async (_req, res) => {
  const health = await checkInferenceHealth();
  res.json(health);
});

export default router;
