import { BadgeCheck, Cloud, Lock, Radar, Server, ShieldAlert, } from "lucide-react"; import { headers } from "next/headers"; import { redirect } from "next/navigation"; import { removeCloudflareRule, resetAntiddosSettings, saveAntiddosSettings, unbanAntiddosIp, verifyCloudflareConfiguration, verifyCrowdsecConfiguration, verifyCrowdsecReportingConfiguration, } from "@/actions/admin-antiddos"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { antiddosDefaultsFromEnv, getAntiddosConfig, } from "@/lib/antiddos-config"; import { resolveClientIp } from "@/lib/client-ip"; import { isCloudflareProxied, preferredClientIpHeader } from "@/lib/cloudflare"; import { type CloudflareBlockView, cloudflareEnabled, getLastCloudflareVerify, listCloudflareBlocks, sweepExpiredCloudflareBlocks, } from "@/lib/cloudflare-api"; import { CROWDSEC_BLOCK_SOURCE, type CrowdsecBlockMeta, crowdsecEnabled, getCrowdsecBlockMeta, getCrowdsecQuotaUsage, getLastCrowdsecVerify, } from "@/lib/crowdsec-api"; import { crowdsecReportEnabled, getLastCrowdsecReport, } from "@/lib/crowdsec-report"; import { type CrowdsecDailyStat, getCrowdsecStats } from "@/lib/crowdsec-stats"; import { db, WebsiteSetting } from "@/lib/db"; import { canAccess, getAdminContext, PERMS } from "@/lib/permissions"; import { redis } from "@/lib/redis"; function seconds(ttlMs: number): string { const s = Math.floor(ttlMs / 1000); if (s <= 0) return "–"; if (s < 60) return `${s}s`; if (s < 3600) return `${Math.floor(s / 60)}m${s % 60 ? ` ${s % 60}s` : ""}`; return `${Math.floor(s / 3600)}h ${Math.floor((s % 3600) / 60)}m`; } function BarSparkline({ values }: { values: number[] }) { if (values.length === 0) return null; const max = Math.max(...values, 1); return (