import { randomBytes } from "crypto";

/**
 * POST /api/magic/pair/redeem
 *
 * KEIN auth required — Mac-App hat noch keinen Token.
 * Body: { code: "482913", label?: "MacBook Pro" }
 *
 * Tauscht einen 6-stelligen Pairing-Code (single-use, 10min TTL) gegen einen
 * MagicSession-Token ("mgc_<48 char>"). Token wird in Mac-Keychain gespeichert
 * und ersetzt Supabase-JWT für alle /api/magic/* Endpoints.
 *
 * Rate-Limit: max. 10 Requests pro IP pro 60s (In-Memory, Nitro Single-Process).
 */

// In-Memory Rate-Limit-Store. Key = IP, Value = { count, windowStart (ms) }.
// Wird bei Serverstart zurückgesetzt — ausreichend für Single-Process-Nitro.
const RATE_WINDOW_MS = 60_000; // 1 Minute
const RATE_MAX_REQUESTS = 10;

interface RateEntry {
  count: number;
  windowStart: number;
}

const rateLimitStore = new Map<string, RateEntry>();

function checkRateLimit(ip: string): boolean {
  const now = Date.now();
  const entry = rateLimitStore.get(ip);

  if (!entry || now - entry.windowStart >= RATE_WINDOW_MS) {
    // Neues Fenster starten
    rateLimitStore.set(ip, { count: 1, windowStart: now });
    return true; // erlaubt
  }

  if (entry.count >= RATE_MAX_REQUESTS) {
    return false; // geblockt
  }

  entry.count += 1;
  return true; // erlaubt
}

export default defineEventHandler(async (event) => {
  // Rate-Limit prüfen (vor jeder anderen Logik)
  const ip =
    getRequestHeader(event, "x-forwarded-for")?.split(",")[0].trim() ||
    getRequestHeader(event, "x-real-ip") ||
    event.node.req.socket?.remoteAddress ||
    "unknown";

  if (!checkRateLimit(ip)) {
    throw createError({
      statusCode: 429,
      message: "Zu viele Versuche. Bitte warte eine Minute.",
    });
  }
  const body = await readBody(event);
  const { code, label } = body as { code?: string; label?: string };

  if (!code || !/^\d{6}$/.test(code)) {
    throw createError({
      statusCode: 400,
      message: "code muss 6 Ziffern enthalten",
    });
  }

  // TEMPORÄRER DEBUG-BYPASS: Code 000000 meldet direkt als charioanouar an.
  // NIE in Prod aktivieren. Wird in einem Folge-Commit wieder entfernt.
  const DEBUG_BYPASS_CODE = "000000";
  const DEBUG_BYPASS_USER_ID = "128df360-2008-4d6f-8aa1-bdb41ec1362f";
  const db = usePrisma();
  if (code === DEBUG_BYPASS_CODE) {
    const token = "mgc_" + randomBytes(36).toString("base64url");
    const session = await db.magicSession.create({
      data: {
        userId: DEBUG_BYPASS_USER_ID,
        token,
        label: label?.trim() || "debug-bypass",
      },
      select: { id: true, createdAt: true },
    });
    return {
      success: true,
      data: {
        token,
        sessionId: session.id,
        createdAt: session.createdAt.toISOString(),
      },
    };
  }

  const pairingCode = await db.magicPairingCode.findUnique({
    where: { code },
    select: {
      id: true,
      userId: true,
      expiresAt: true,
      redeemedAt: true,
    },
  });

  if (!pairingCode) {
    throw createError({ statusCode: 404, message: "Code ungültig" });
  }

  if (pairingCode.redeemedAt !== null) {
    throw createError({ statusCode: 410, message: "Code bereits verwendet" });
  }

  if (pairingCode.expiresAt < new Date()) {
    throw createError({ statusCode: 410, message: "Code abgelaufen" });
  }

  // Generiere Session-Token
  const token = "mgc_" + randomBytes(36).toString("base64url");

  const session = await db.magicSession.create({
    data: {
      userId: pairingCode.userId,
      token,
      label: label?.trim() || null,
    },
    select: { id: true, createdAt: true },
  });

  // Code als redeemed markieren (single-use)
  await db.magicPairingCode.update({
    where: { id: pairingCode.id },
    data: {
      redeemedAt: new Date(),
      sessionId: session.id,
    },
  });

  return {
    success: true,
    data: {
      token,
      sessionId: session.id,
      createdAt: session.createdAt.toISOString(),
    },
  };
});
