import { serve } from "https://deno.land/std@0.203.0/http/server.ts";
import { createClient } from "https://esm.sh/@supabase/supabase-js@2";

// CORS: allow browser-based web clients (adjust origin in production)
// Permit headers the supabase-js client sends (e.g. `apikey`, `x-client-info`) so
// browser preflight requests succeed. Keep origin wide for dev; in production
// prefer echoing the request origin and enabling credentials only when needed.
const CORS_HEADERS: Record<string, string> = {
  "Access-Control-Allow-Origin": "*",
  "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
  "Access-Control-Allow-Headers": "Content-Type, Authorization, apikey, x-client-info, x-requested-with, Origin, Accept",
  "Access-Control-Max-Age": "3600",
};

const jsonResponse = (body: unknown, status = 200) =>
  new Response(JSON.stringify(body), {
    status,
    headers: { "Content-Type": "application/json", ...CORS_HEADERS },
  });

serve(async (req) => {
  // Handle CORS preflight quickly so browsers can call this function from localhost/dev
  if (req.method === "OPTIONS") {
    return new Response(null, { status: 204, headers: CORS_HEADERS });
  }

  if (req.method != "POST") {
    return jsonResponse({ error: "Method not allowed" }, 405);
  }

  const supabaseUrl = Deno.env.get("SUPABASE_URL") ?? "";
  const anonKey = Deno.env.get("SUPABASE_ANON_KEY") ?? "";
  const serviceKey = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") ?? "";
  if (!supabaseUrl || !anonKey || !serviceKey) {
    return jsonResponse({ error: "Missing env configuration" }, 500);
  }

  const authHeader = req.headers.get("Authorization") ?? "";
  const token = authHeader.replace("Bearer ", "").trim();
  if (!token) {
    return jsonResponse({ error: "Missing access token" }, 401);
  }

  const authClient = createClient(supabaseUrl, anonKey, {
    global: { headers: { Authorization: `Bearer ${token}` } },
  });
  const { data: authData, error: authError } =
    await authClient.auth.getUser();

  // DEBUG: log auth results to help diagnose intermittent 401s from the
  // gateway / auth service. Remove these logs before deploying to production.
  console.log("admin_user_management: token-snippet", token.slice(0, 16));
  console.log("admin_user_management: authData", JSON.stringify(authData));
  console.log("admin_user_management: authError", JSON.stringify(authError));

  if (authError || !authData?.user) {
    // Extract token header (kid/alg) for debugging without revealing the full
    // token. This helps confirm which key the gateway/runtime attempted to
    // verify against.
    let tokenHeader: unknown = null;
    try {
      const headerB64 = token.split(".")[0] ?? "";
      tokenHeader = JSON.parse(atob(headerB64));
    } catch (e) {
      tokenHeader = { parseError: (e as Error).message };
    }

    return jsonResponse(
      {
        error: "Unauthorized",
        debug: {
          authError: authError?.message ?? null,
          tokenHeader,
          authDataUser: authData?.user
            ? {
                id: authData.user.id,
                email: authData.user.email ?? null,
                banned_until: authData.user.banned_until ?? null,
              }
            : null,
        },
      },
      401,
    );
  }

  const adminClient = createClient(supabaseUrl, serviceKey);
  const { data: profile, error: profileError } = await adminClient
    .from("profiles")
    .select("role")
    .eq("id", authData.user.id)
    .maybeSingle();
  const role = (profile?.role ?? "").toString().toLowerCase();
  if (profileError || role != "admin") {
    return jsonResponse({ error: "Forbidden" }, 403);
  }

  let payload: Record<string, unknown> = {};
  try {
    payload = await req.json();
  } catch (_) {
    return jsonResponse({ error: "Invalid JSON" }, 400);
  }

  const action = payload.action as string | undefined;
  const userId = payload.userId as string | undefined;
  if (!action) {
    return jsonResponse({ error: "Missing action" }, 400);
  }
  // `list_users` does not require a target userId; other actions do.
  if (action !== "list_users" && !userId) {
    return jsonResponse({ error: "Missing userId" }, 400);
  }

  if (action === "list_users") {
    const offset = Number(payload.offset ?? 0);
    const limit = Number(payload.limit ?? 50);
    const searchQuery = (payload.searchQuery ?? "").toString().trim();

    // Fetch paginated profiles first (enforce server-side pagination)
    let profilesQuery = adminClient
      .from("profiles")
      .select("id, full_name, role")
      .order("id", { ascending: true })
      .range(offset, offset + limit - 1);

    if (searchQuery.length > 0) {
      profilesQuery = adminClient
        .from("profiles")
        .select("id, full_name, role")
        .ilike("full_name", `%${searchQuery}%`)
        .order("id", { ascending: true })
        .range(offset, offset + limit - 1);
    }

    const { data: profiles, error: profilesError } = await profilesQuery;
    if (profilesError) return jsonResponse({ error: profilesError.message }, 500);

    const users = [];
    for (const p of (profiles ?? [])) {
      const { data: userResp } = await adminClient.auth.admin.getUserById(p.id);
      users.push({
        id: p.id,
        full_name: p.full_name ?? null,
        role: p.role ?? null,
        email: userResp?.user?.email ?? null,
        bannedUntil: userResp?.user?.banned_until ?? null,
      });
    }

    return jsonResponse({ users });
  }

  if (action == "get_user") {
    const { data, error } = await adminClient.auth.admin.getUserById(userId);
    if (error) {
      return jsonResponse({ error: error.message }, 400);
    }
    return jsonResponse({ user: data.user });
  }

  if (action == "set_password") {
    const password = payload.password as string | undefined;
    if (!password || password.length < 8) {
      return jsonResponse({ error: "Password must be at least 8 characters" }, 400);
    }
    const { error } = await adminClient.auth.admin.updateUserById(userId, {
      password,
    });
    if (error) {
      return jsonResponse({ error: error.message }, 400);
    }
    return jsonResponse({ ok: true });
  }

  if (action == "set_lock") {
    const locked = Boolean(payload.locked);
    const { error } = await adminClient.auth.admin.updateUserById(userId, {
      ban_duration: locked ? "100y" : "0s",
    });
    if (error) {
      return jsonResponse({ error: error.message }, 400);
    }
    return jsonResponse({ ok: true });
  }

  return jsonResponse({ error: "Unknown action" }, 400);
});
