import { getProfile } from "../../db/profile";
import {
  findActiveDeviceLock,
  bindDeviceToUser,
  isLockingPlan,
  markDeviceLockNotified,
} from "../../db/devices";
import {
  isLockNotifyRateLimited,
  sendDeviceLockEmail,
} from "../../utils/device-lock-email";

export default defineEventHandler(async (event) => {
  const { username, password } = await readBody(event);

  if (!username || !password) {
    throw createError({
      statusCode: 400,
      message: "username und password erforderlich",
    });
  }

  // ─── Device-Lock-Check (vor Auth) ──────────────────────────────────────────
  // Wenn x-device-id Header gesetzt und das Device an einen anderen Pro/Legend-
  // User gebunden ist → 409 DEVICE_LOCKED. Login wird NICHT durchgeführt.
  //
  // Warum vor Auth: wir brauchen nicht zu wissen ob die Credentials korrekt sind.
  // Das würde nur Timing-Side-Channel für Account-Enumeration öffnen.
  const incomingDeviceId = getHeader(event, "x-device-id");

  if (incomingDeviceId) {
    // Wir brauchen die user-id des einlogenden Users für den Check —
    // aber wir haben noch keinen eingeloggten User. Wir übergeben eine
    // Dummy-UUID die nie matcht, da wir hier nur prüfen ob das Device an
    // irgendwen (außer NULL) gebunden ist. findActiveDeviceLock matched
    // "deviceId + NOT userId", also matcht die Dummy-UUID nie auf eine Row.
    const DUMMY_REQUESTING_USER = "00000000-0000-0000-0000-000000000000";

    const lock = await findActiveDeviceLock(incomingDeviceId, DUMMY_REQUESTING_USER);

    if (lock) {
      // Async: Mail-Notification an Original-User (Rate-Limited auf 6h)
      if (!isLockNotifyRateLimited(lock.lockNotifiedAt)) {
        // Original-User-Profil laden für Mail-Details
        // Alle Ressourcen hier im äußeren Scope cachen (kein async-after-response)
        const config = useRuntimeConfig(event);
        const supabaseCfg = (config as any).public?.supabase ?? (config as any).supabase;
        const resendApiKey = (config as any).resendApiKey as string | undefined;
        const supabaseServiceKey = (config as any).supabaseServiceKey as string | undefined;

        void (async () => {
          try {
            const { getProfile: gp } = await import("../../db/profile");
            const ownerProfile = await gp(lock.userId);
            if (ownerProfile && resendApiKey && supabaseServiceKey) {
              const { createClient } = await import("@supabase/supabase-js");
              const adminClient = createClient(
                supabaseCfg.url as string,
                supabaseServiceKey,
              );
              const { data: adminUser } = await adminClient.auth.admin.getUserById(lock.userId);
              const ownerEmail = adminUser?.user?.email;

              if (ownerEmail) {
                await sendDeviceLockEmail({
                  recipientNickname: ownerProfile.nickname ?? ownerProfile.username ?? "Nutzer",
                  recipientEmail: ownerEmail,
                  deviceRowId: lock.id,
                  deviceName: lock.name,
                  lockNotifiedAt: lock.lockNotifiedAt,
                  resendApiKey,
                });
                await markDeviceLockNotified(lock.id);
              }
            }
          } catch (mailErr: any) {
            console.error("[login] device-lock mail failed:", mailErr?.message ?? mailErr);
          }
        })();
      }

      // lockedUntil: release_requested_at + 24h, oder "unbestimmt" wenn kein Request
      const lockedUntil = lock.releaseRequestedAt
        ? new Date(lock.releaseRequestedAt.getTime() + 24 * 60 * 60 * 1000).toISOString()
        : null;

      throw createError({
        statusCode: 409,
        statusMessage: "DEVICE_LOCKED",
        data: {
          error: "DEVICE_LOCKED",
          lockedUntil,
          releaseRequestable: true,
        },
      });
    }
  }

  // ─── Normaler Auth-Flow ─────────────────────────────────────────────────────
  const email = `${username.toLowerCase()}@rebreak.internal`;
  const supabase = serverSupabaseClient(event);

  const { data, error } = await supabase.auth.signInWithPassword({
    email,
    password,
  });
  if (error) throw createError({ statusCode: 401, message: error.message });

  const dbProfile = await getProfile(data.user.id);
  const normalizedPlan = (
    dbProfile?.plan === "premium"
      ? "legend"
      : dbProfile?.plan === "standard"
        ? "pro"
        : dbProfile?.plan ?? "free"
  ) as "free" | "pro" | "legend";

  // ─── Device-Binding nach erfolgreichem Login ────────────────────────────────
  // Wenn Pro/Legend-User einloggt und Device-ID bekannt → Device binden.
  // Free-User binden nicht (isLockingPlan filtert).
  if (incomingDeviceId && isLockingPlan(dbProfile?.plan ?? "free")) {
    // Fire-and-forget — Login soll nicht wegen Binding-Fehler blockieren
    void bindDeviceToUser(data.user.id, incomingDeviceId, dbProfile?.plan ?? "free")
      .catch((err: any) => {
        console.error("[login] device-bind failed:", err?.message ?? err);
      });
  }

  return {
    session: {
      access_token: data.session.access_token,
      refresh_token: data.session.refresh_token,
      expires_at: data.session.expires_at,
    },
    profile: {
      id: data.user.id,
      email: data.user.email ?? "",
      username: dbProfile?.username ?? "",
      nickname: dbProfile?.nickname ?? null,
      avatar: dbProfile?.avatar ?? null,
      plan: normalizedPlan,
      streak: dbProfile?.streak ?? 0,
      created_at: dbProfile?.createdAt?.toISOString() ?? data.user.created_at,
    },
  };
});
