import {
  Router,
  type Request,
  type Response,
  type Router as RouterType,
} from "express";

import { detailedMetrics } from "../detailed-metrics.js";
import { metrics } from "../metrics.js";
import { ENDPOINT_LABELS, ENDPOINT_IDS } from "../providers/types.js";
import type { EndpointId } from "../providers/types.js";
import {
  getAvailableStrategies,
  getStrategyDescription,
} from "../rate-limiting/index.js";
import { registry } from "../registry.js";
import { adminWebSocket } from "./websocket.js";

const router: RouterType = Router();

/**
 * GET /api/health - Admin API health check
 */
router.get("/health", (_req: Request, res: Response) => {
  res.json({
    status: "ok",
    wsClients: adminWebSocket.getClientCount(),
    timestamp: new Date().toISOString(),
  });
});

/**
 * GET /api/metrics - Current metrics snapshot
 */
router.get("/metrics", (_req: Request, res: Response) => {
  res.json(metrics.getSnapshot());
});

/**
 * GET /api/metrics/latency/:endpoint - Latency percentiles for endpoint
 */
router.get("/metrics/latency/:endpoint", (req: Request, res: Response) => {
  const endpoint = req.params.endpoint as EndpointId;

  if (!ENDPOINT_LABELS[endpoint]) {
    res.status(400).json({ error: `Unknown endpoint: ${endpoint}` });
    return;
  }

  res.json({
    endpoint,
    p50: metrics.getLatencyPercentile(endpoint, 50),
    p90: metrics.getLatencyPercentile(endpoint, 90),
    p99: metrics.getLatencyPercentile(endpoint, 99),
  });
});

/**
 * POST /api/metrics/reset - Reset all metrics
 */
router.post("/metrics/reset", (_req: Request, res: Response) => {
  metrics.reset();
  res.json({ status: "ok", message: "Metrics reset" });
});

/**
 * GET /api/config - Current configuration
 */
router.get("/config", (_req: Request, res: Response) => {
  res.json(registry.getFullConfig());
});

/**
 * PATCH /api/config/global - Update global configuration
 */
router.patch("/config/global", (req: Request, res: Response) => {
  const updates = req.body;

  if (!updates || typeof updates !== "object") {
    res.status(400).json({ error: "Request body must be an object" });
    return;
  }

  registry.updateGlobalConfig(updates);
  res.json(registry.getFullConfig());
});

/**
 * GET /api/config/endpoints - List all endpoints with their config
 */
router.get("/config/endpoints", (_req: Request, res: Response) => {
  const endpoints: Record<
    string,
    { label: string; config: unknown; rateLimiterState: unknown }
  > = {};

  for (const id of ENDPOINT_IDS) {
    const rateLimiter = registry.getRateLimiter(id);
    endpoints[id] = {
      label: ENDPOINT_LABELS[id],
      config: registry.getEndpointConfig(id),
      rateLimiterState: rateLimiter.getState(),
    };
  }

  res.json(endpoints);
});

/**
 * PATCH /api/config/endpoints/:endpoint - Update endpoint-specific configuration
 */
router.patch("/config/endpoints/:endpoint", (req: Request, res: Response) => {
  const endpoint = req.params.endpoint as EndpointId;
  const updates = req.body;

  if (!ENDPOINT_LABELS[endpoint]) {
    res.status(400).json({ error: `Unknown endpoint: ${endpoint}` });
    return;
  }

  if (!updates || typeof updates !== "object") {
    res.status(400).json({ error: "Request body must be an object" });
    return;
  }

  registry.updateEndpointConfig(endpoint, updates);
  res.json({
    endpoint,
    config: registry.getEndpointConfig(endpoint),
  });
});

/**
 * DELETE /api/config/endpoints/:endpoint - Clear endpoint overrides
 */
router.delete("/config/endpoints/:endpoint", (req: Request, res: Response) => {
  const endpoint = req.params.endpoint as EndpointId;

  if (!ENDPOINT_LABELS[endpoint]) {
    res.status(400).json({ error: `Unknown endpoint: ${endpoint}` });
    return;
  }

  registry.clearEndpointOverrides(endpoint);
  res.json({
    endpoint,
    config: registry.getEndpointConfig(endpoint),
    message: "Endpoint overrides cleared, using global config",
  });
});

/**
 * POST /api/config/reset - Reset to initial configuration
 */
router.post("/config/reset", (_req: Request, res: Response) => {
  registry.reset();
  res.json({
    status: "ok",
    message: "Configuration reset",
    config: registry.getFullConfig(),
  });
});

/**
 * POST /api/rate-limit/reset - Reset all rate limiter states
 */
router.post("/rate-limit/reset", (_req: Request, res: Response) => {
  registry.resetAllRateLimiters();
  res.json({ status: "ok", message: "All rate limiter states reset" });
});

/**
 * POST /api/rate-limit/reset/:endpoint - Reset rate limiter for specific endpoint
 */
router.post("/rate-limit/reset/:endpoint", (req: Request, res: Response) => {
  const endpoint = req.params.endpoint as EndpointId;

  if (!ENDPOINT_LABELS[endpoint]) {
    res.status(400).json({ error: `Unknown endpoint: ${endpoint}` });
    return;
  }

  registry.resetRateLimiter(endpoint);
  res.json({ status: "ok", message: `Rate limiter reset for ${endpoint}` });
});

/**
 * GET /api/rate-limit/strategies - List available rate limiting strategies
 */
router.get("/rate-limit/strategies", (_req: Request, res: Response) => {
  const strategies = getAvailableStrategies().map((strategy) => ({
    id: strategy,
    description: getStrategyDescription(strategy),
  }));
  res.json(strategies);
});

// =============================================================================
// Detailed Metrics
// =============================================================================

/**
 * GET /api/detailed-metrics - Full detailed metrics snapshot
 */
router.get("/detailed-metrics", (_req: Request, res: Response) => {
  res.json(detailedMetrics.getSnapshot());
});

/**
 * GET /api/detailed-metrics/export/json - Export detailed metrics as JSON
 */
router.get("/detailed-metrics/export/json", (_req: Request, res: Response) => {
  res.setHeader("Content-Type", "application/json");
  res.setHeader(
    "Content-Disposition",
    "attachment; filename=detailed-metrics.json"
  );
  res.send(detailedMetrics.exportJSON());
});

/**
 * GET /api/detailed-metrics/export/csv - Export time series as CSV
 */
router.get("/detailed-metrics/export/csv", (_req: Request, res: Response) => {
  res.setHeader("Content-Type", "text/csv");
  res.setHeader(
    "Content-Disposition",
    "attachment; filename=detailed-metrics.csv"
  );
  res.send(detailedMetrics.exportCSV());
});

/**
 * POST /api/detailed-metrics/reset - Reset detailed metrics
 */
router.post("/detailed-metrics/reset", (_req: Request, res: Response) => {
  detailedMetrics.reset();
  res.json({ status: "ok", message: "Detailed metrics reset" });
});

/**
 * GET /api/failure-modes - List available failure modes
 */
router.get("/failure-modes", (_req: Request, res: Response) => {
  res.json([
    {
      id: "timeout",
      description: "Request hangs indefinitely (client times out)",
    },
    { id: "server_error", description: "Returns 500 Internal Server Error" },
    { id: "bad_request", description: "Returns 400 Bad Request" },
    {
      id: "slow_response",
      description: "Adds 5-10 second delay before response",
    },
    {
      id: "connection_reset",
      description: "Abruptly closes the connection (TCP RST)",
    },
  ]);
});

export const adminRoutes = router;
