import { NextResponse as o, NextRequest as g } from "next/server";
import { FrankAuth as y } from "@frank-auth/sdk";
const m = {
  apiUrl: "http://localhost:8990",
  sessionCookieName: "frank_sid",
  storageKeyPrefix: "frank_auth_",
  publicPaths: ["/sign-in", "/sign-up", "/forgot-password", "/verify-email", "/reset-password"],
  privatePaths: [],
  allPathsPrivate: !0,
  // Default to all paths being private
  signInPath: "/sign-in",
  signUpPath: "/sign-up",
  afterSignInPath: "/dashboard",
  afterSignUpPath: "/dashboard",
  afterSignOutPath: "/",
  orgSelectionPath: "/select-organization",
  debug: !1,
  enableOrgRouting: !1,
  ignorePaths: ["/api", "/_next", "/favicon.ico", "/images", "/static", "/_vercel"],
  cookieOptions: {
    secure: process.env.NODE_ENV === "production",
    httpOnly: !0,
    sameSite: "lax",
    maxAge: 60 * 60 * 24 * 7
    // 7 days
  }
};
function p(r, e) {
  return e.some((t) => {
    if (t === r) return !0;
    if (t.endsWith("*")) {
      const s = t.slice(0, -1);
      return r.startsWith(s);
    }
    return t.startsWith("/") && t.endsWith("/") ? new RegExp(t.slice(1, -1)).test(r) : !1;
  });
}
function b(r, e) {
  const t = r.cookies.get(e.sessionCookieName)?.value;
  if (t) return t;
  const s = r.headers.get("authorization");
  return s?.startsWith("Bearer ") ? s.slice(7) : null;
}
async function k(r, e, t) {
  const s = new y({
    apiUrl: e.apiUrl,
    publishableKey: e.publishableKey,
    sessionCookieName: e.sessionCookieName,
    storageKeyPrefix: e.storageKeyPrefix,
    enableDevMode: e.debug,
    userType: e.userType ?? "end_user",
    projectId: e.projectId,
    secretKey: e.secretKey
  });
  try {
    const n = {
      Authorization: `Bearer ${r}`,
      "X-Publishable-Key": e.publishableKey,
      "Content-Type": "application/json",
      "X-Org-ID": e.projectId,
      "X-User-Type": e.userType ?? "end_user"
    };
    e.secretKey && (n["X-API-Key"] = e.secretKey);
    const l = t.headers.get("cookie");
    l && (n.Cookie = l);
    const c = t.headers.get("user-agent");
    c && (n["User-Agent"] = c);
    const i = t.headers.get("x-forwarded-for"), a = t.headers.get("x-real-ip");
    i && (n["X-Forwarded-For"] = i), a && (n["X-Real-IP"] = a), u(e, "Validating session token:", { token: r, headers: n });
    const d = await s.getAuthStatus({
      credentials: "include",
      headers: n
    });
    return {
      isAuthenticated: d.isAuthenticated,
      user: d.user || null,
      session: d.session || null,
      organizationId: d.organizationId || null,
      error: null
    };
  } catch (n) {
    return u(e, "Validating session error:", n), {
      isAuthenticated: !1,
      user: null,
      session: null,
      organizationId: null,
      error: n
    };
  }
}
async function A(r, e, t) {
  const s = new y({
    apiUrl: e.apiUrl,
    publishableKey: e.publishableKey,
    sessionCookieName: e.sessionCookieName,
    storageKeyPrefix: e.storageKeyPrefix,
    enableDevMode: e.debug,
    userType: e.userType ?? "end_user",
    projectId: e.projectId,
    secretKey: e.secretKey
  });
  try {
    const n = {
      "X-Publishable-Key": e.publishableKey,
      "Content-Type": "application/json",
      "X-Org-ID": e.projectId,
      "X-User-Type": e.userType ?? "end_user"
    };
    e.secretKey && (n["X-API-Key"] = e.secretKey);
    const l = t.headers.get("cookie");
    l && (n.Cookie = l);
    const c = await s.refreshSession(r, {
      credentials: "include",
      headers: n
    });
    return c ? {
      accessToken: c.accessToken,
      refreshToken: c.refreshToken ?? ""
    } : null;
  } catch {
    return null;
  }
}
function w(r, e) {
  if (!e.enableOrgRouting) return null;
  const t = r.nextUrl.hostname;
  if (e.customDomain && t === e.customDomain)
    return r.nextUrl.searchParams.get("org") || null;
  const s = t.split(".");
  return s.length > 2 ? s[0] : null;
}
function u(r, e, t) {
  r.debug && console.log(`[FrankAuth Middleware] ${e}`, t || "");
}
async function x(r, e) {
  const t = r.nextUrl.pathname;
  if (u(e, `Processing request: ${t}`), p(t, e.ignorePaths))
    return u(e, `Ignoring path: ${t}`), o.next();
  if (e.hooks?.beforeAuth) {
    const h = await e.hooks.beforeAuth(r);
    if (h instanceof o) return h;
    h instanceof g && (r = h);
  }
  const s = p(t, e.publicPaths), n = t === e.signInPath || t === e.signUpPath;
  let l;
  e.allPathsPrivate ? l = !s && !n : l = p(t, e.privatePaths), u(e, "Path analysis:", {
    isPublicPath: s,
    isPrivatePath: l,
    isAuthPath: n,
    allPathsPrivate: e.allPathsPrivate
  });
  const c = b(r, e);
  let i = {
    isAuthenticated: !1,
    user: null,
    session: null,
    organizationId: null,
    error: null
  };
  if (u(e, "Session Cookie:", { sessionToken: c }), c && (i = await k(c, e, r), !i.isAuthenticated && i.error)) {
    const h = r.cookies.get(`${e.storageKeyPrefix}refresh_token`)?.value;
    if (h) {
      const P = await A(h, e, r);
      if (P && (i = await k(P.accessToken, e, r), i.isAuthenticated)) {
        const f = o.next();
        return f.cookies.set(e.sessionCookieName, P.accessToken, e.cookieOptions), f.cookies.set(`${e.storageKeyPrefix}refresh_token`, P.refreshToken, e.cookieOptions), f;
      }
    }
  }
  u(e, "Auth result:", {
    isAuthenticated: i.isAuthenticated,
    hasUser: !!i.user,
    organizationId: i.organizationId
  });
  const d = await I({
    req: r,
    config: e,
    auth: i,
    path: t,
    isPublicPath: s,
    isPrivatePath: l,
    isAuthPath: n
  });
  if (e.hooks?.afterAuth) {
    const h = await e.hooks.afterAuth(r, d, i);
    if (h instanceof o) return h;
  }
  return d;
}
async function I(r) {
  const { req: e, config: t, auth: s, path: n, isPublicPath: l, isPrivatePath: c, isAuthPath: i } = r;
  try {
    if (s.isAuthenticated && s.user) {
      if (u(t, "User is authenticated"), t.hooks?.onAuthenticated && s.session) {
        const a = await t.hooks.onAuthenticated(e, s.user, s.session);
        if (a instanceof o) return a;
      }
      if (i) {
        const a = e.nextUrl.searchParams.get("redirect_url") || t.afterSignInPath;
        return u(t, `Redirecting authenticated user from auth page to: ${a}`), o.redirect(new URL(a, e.url));
      }
      if (t.enableOrgRouting && !s.organizationId && n !== t.orgSelectionPath) {
        if (u(t, "Organization required but not selected"), t.hooks?.onOrganizationRequired) {
          const a = await t.hooks.onOrganizationRequired(e, s.user);
          if (a instanceof o) return a;
        }
        return o.redirect(new URL(t.orgSelectionPath, e.url));
      }
      return o.next();
    }
    if (u(t, "User is not authenticated"), t.hooks?.onUnauthenticated) {
      const a = await t.hooks.onUnauthenticated(e);
      if (a instanceof o) return a;
    }
    if (l || i)
      return u(t, "Allowing access to public/auth path"), o.next();
    if (c) {
      const a = new URL(t.signInPath, e.url);
      return a.searchParams.set("redirect_url", e.nextUrl.pathname + e.nextUrl.search), u(t, `Redirecting to sign in: ${a.toString()}`), o.redirect(a);
    }
    return o.next();
  } catch (a) {
    if (u(t, "Error in authentication handling:", a), t.hooks?.onError) {
      const h = await t.hooks.onError(e, a);
      if (h instanceof o) return h;
    }
    const d = new URL(t.signInPath, e.url);
    return d.searchParams.set("error", "auth_error"), o.redirect(d);
  }
}
function R(r) {
  const e = { ...m, ...r };
  if (!e.publishableKey)
    throw new Error("publishableKey is required for Frank Auth middleware");
  return u(e, "Frank Auth middleware initialized with config:", {
    publicPaths: e.publicPaths,
    privatePaths: e.privatePaths,
    allPathsPrivate: e.allPathsPrivate,
    signInPath: e.signInPath,
    enableOrgRouting: e.enableOrgRouting
  }), async function(s) {
    return x(s, e);
  };
}
function T(r) {
  return function(t) {
    return r.custom ? r.custom(t) : r.exclude && p(t, r.exclude) ? !1 : !!(r.include && p(t, r.include));
  };
}
async function v(r, e, t) {
  const s = b(r, t);
  if (!s) return !1;
  try {
    const n = await fetch(`${t.apiUrl}/api/v1/auth/permissions/check`, {
      method: "POST",
      credentials: "include",
      headers: {
        Authorization: `Bearer ${s}`,
        "X-Publishable-Key": t.publishableKey,
        "Content-Type": "application/json",
        Cookie: r.headers.get("cookie") || ""
      },
      body: JSON.stringify({ permission: e })
    });
    return n.ok ? (await n.json()).hasPermission === !0 : !1;
  } catch {
    return !1;
  }
}
function O(r, e) {
  return w(r, e);
}
export {
  v as checkPermission,
  R as createFrankAuthMiddleware,
  T as createMatcher,
  O as getOrganizationFromRequest
};
//# sourceMappingURL=index.js.map
