import type { Express, RequestHandler } from "express";
import type { AuthenticatedRequest } from "../../../types/index.js";
import { createCurrentProxmoxNodeHistoryRepository } from "../../database/repositories/factory.js";
import { statsLogger } from "../../utils/logger.js";
import type { HostAction } from "../../utils/permission-manager.js";

type ProxmoxStatsHistoryRoutesDeps = {
  validateHostId: RequestHandler;
  canAccessHost: (
    userId: string,
    hostId: number,
    level: HostAction,
  ) => Promise<boolean>;
};

const RANGE_OFFSETS: Record<string, number> = {
  "1h": 1 * 60 * 60 * 1000,
  "6h": 6 * 60 * 60 * 1000,
  "24h": 24 * 60 * 60 * 1000,
  "7d": 7 * 24 * 60 * 60 * 1000,
  "30d": 30 * 24 * 60 * 60 * 1000,
};

export function registerProxmoxStatsHistoryRoutes(
  app: Express,
  { validateHostId, canAccessHost }: ProxmoxStatsHistoryRoutesDeps,
): void {
  /**
   * @openapi
   * /proxmox-stats/history/{hostId}:
   *   get:
   *     summary: Get historical Proxmox node stats for a host
   *     tags:
   *       - Proxmox Stats
   *     parameters:
   *       - in: path
   *         name: hostId
   *         required: true
   *         schema:
   *           type: integer
   *       - in: query
   *         name: range
   *         schema:
   *           type: string
   *           enum: [1h, 6h, 24h, 7d, 30d]
   *       - in: query
   *         name: from
   *         schema:
   *           type: string
   *           format: date-time
   *       - in: query
   *         name: to
   *         schema:
   *           type: string
   *           format: date-time
   *     responses:
   *       200:
   *         description: Array of node history rows.
   *       403:
   *         description: Access denied.
   */
  app.get(
    "/proxmox-stats/history/:hostId",
    validateHostId,
    async (req, res) => {
      const hostId = Number(req.params.hostId);
      const userId = (req as AuthenticatedRequest).userId;

      try {
        const hasAccess = await canAccessHost(userId, hostId, "connect");
        if (!hasAccess) {
          return res.status(403).json({ error: "Access denied" });
        }

        const { range, from, to } = req.query as Record<
          string,
          string | undefined
        >;

        let fromTs: string;
        let toTs: string = new Date().toISOString();

        if (range) {
          const offsetMs = RANGE_OFFSETS[range];
          if (!offsetMs) {
            return res
              .status(400)
              .json({ error: "Invalid range. Use 1h, 6h, 24h, 7d, or 30d" });
          }
          fromTs = new Date(Date.now() - offsetMs).toISOString();
        } else if (from && to) {
          const fromDate = new Date(from);
          const toDate = new Date(to);
          if (isNaN(fromDate.getTime()) || isNaN(toDate.getTime())) {
            return res
              .status(400)
              .json({ error: "Invalid from/to date format" });
          }
          fromTs = fromDate.toISOString();
          toTs = toDate.toISOString();
        } else {
          fromTs = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString();
        }

        const toSqlite = (iso: string) =>
          iso.replace("T", " ").replace(/\.\d{3}Z$/, "");
        const rows = (
          await createCurrentProxmoxNodeHistoryRepository().listRange(
            hostId,
            toSqlite(fromTs),
            toSqlite(toTs),
          )
        ).map((row) => ({
          ts: row.ts,
          cpu_percent: row.cpuPercent,
          mem_percent: row.memPercent,
          disk_percent: row.diskPercent,
          net_rx_bytes: row.netRxBytes,
          net_tx_bytes: row.netTxBytes,
        }));

        res.json({ rows, fromTs, toTs });
      } catch (error) {
        statsLogger.error("Failed to fetch proxmox stats history", {
          operation: "proxmox_stats_history_fetch_error",
          hostId,
          error: error instanceof Error ? error.message : String(error),
        });
        res
          .status(500)
          .json({ error: "Failed to fetch proxmox stats history" });
      }
    },
  );
}
