import { clerkMiddleware, createRouteMatcher, clerkClient } from '@clerk/astro/server';
import 'dotenv/config';
 
declare global {
  namespace App {
    interface Locals {
      canAddInventory: boolean;
    }
  }
}
 
const isProtectedRoute = createRouteMatcher(['/pokemon']);
const isAdminRoute = createRouteMatcher(['/admin', '/api/reindex', '/api/preload-tcgplayer']);

const TARGET_ORG_ID = "org_3Baav9czkRLLlC7g89oJWqRRulK";
const ADMIN_ORG_IDS = new Set([
  "org_3Baav9czkRLLlC7g89oJWqRRulK",
  "org_3ABdwuK3qD7Saq590ZMQWY7AvVz",
]);
 
export const onRequest = clerkMiddleware(async (auth, context, next) => {
  const { isAuthenticated, userId, redirectToSignIn, has } = auth();
 
  if (!isAuthenticated && isProtectedRoute(context.request)) {
    return redirectToSignIn();
  }
 
  // ── Inventory visibility check ──────────────────────────────────────────────
  // Resolves to true if the user belongs to the target org OR has the feature
  const canAddInventory = process.env.INVENTORY_ACCESS === 'true' ||
    (
      isAuthenticated &&
      userId &&
      (
        !!has({ permission: "org:feature:inventory_add" }) ||   // Clerk feature flag
        (await getUserOrgIds(context, userId)).includes(TARGET_ORG_ID)
      )
    );
 
  // Expose the flag to your Astro pages via locals
  context.locals.canAddInventory = Boolean(canAddInventory);
 
  // ── Admin route guard ───────────────────────────────────────────
  if (isAdminRoute(context.request)) {
    if (!isAuthenticated || !userId) {
      return redirectToSignIn();
    }
 
    try {
      const client = await clerkClient(context);
      const userOrgIds = await getUserOrgIds(context, userId);
      const matchingOrgIds = userOrgIds.filter((id) => ADMIN_ORG_IDS.has(id));
 
      if (matchingOrgIds.length === 0) {
        return new Response(null, { status: 404 });
      }
 
      const membershipLists = await Promise.all(
        matchingOrgIds.map((orgId) =>
          client.organizations.getOrganizationMembershipList({ organizationId: orgId })
        )
      );
 
      const isAdmin = membershipLists.some((list) =>
        list.data.some(
          (m) => m.publicUserData?.userId === userId && m.role === "org:admin"
        )
      );
 
      if (!isAdmin) {
        return new Response(null, { status: 404 });
      }
    } catch (e) {
      console.error("Clerk membership check failed:", e);
      return context.redirect("/");
    }
  }
 
  return next();
});
 
// ── Helper: fetch all org IDs the current user belongs to ───────────────────
async function getUserOrgIds(context: any, userId: string): Promise<string[]> {
  try {
    const client = await clerkClient(context);
    const memberships = await client.users.getOrganizationMembershipList({ userId });
    return memberships.data.map((m) => m.organization.id);
  } catch (e) {
    console.error("Failed to fetch user org memberships:", e);
    return [];
  }
}