import { and, eq, gte, sql } from "drizzle-orm";
import { db } from "@/db";
import { loginAttempts } from "@/db/schema";

/**
 * Login-Rate-Limit (Sliding Window) — greift im `authorize`-Callback und damit
 * für BEIDE Credentials-Login-Pfade. Liest/schreibt `login_attempts`
 * (Workstream-2-Schema, hier NICHT neu definiert).
 *
 * Querschnittsstandard 8 (Härtung): 5 Fehlversuche / 15 min pro `key`.
 */
export const RATE_LIMIT = {
  maxFails: 5,
  windowMs: 15 * 60 * 1000,
} as const;

/** Reine Policy-Funktion (DB-frei, testbar): innerhalb des Limits? */
export function isWithinLimit(failCount: number): boolean {
  return failCount < RATE_LIMIT.maxFails;
}

/**
 * Prüft, ob für `key` im aktuellen Fenster noch Versuche erlaubt sind.
 * Gibt `true` zurück, wenn der Login fortgesetzt werden darf.
 */
export async function checkRateLimit(key: string): Promise<boolean> {
  const since = new Date(Date.now() - RATE_LIMIT.windowMs);
  const [row] = await db
    .select({ count: sql<number>`count(*)::int` })
    .from(loginAttempts)
    .where(
      and(
        eq(loginAttempts.key, key),
        eq(loginAttempts.erfolg, false),
        gte(loginAttempts.zeitpunkt, since),
      ),
    );
  return isWithinLimit(row?.count ?? 0);
}

/** Protokolliert einen Login-Versuch. */
export async function recordAttempt(
  key: string,
  result: "ok" | "fail",
): Promise<void> {
  await db.insert(loginAttempts).values({ key, erfolg: result === "ok" });
}
