import { useEffect, type ReactNode } from "react";
import { useNavigate, useParams, useRouterState } from "@tanstack/react-router";

// ---------------------------------------------------------------------------
// Org-slug URL canonicalization for org-scoped hosts (cloud, self-host,
// cloudflare). Console routes live under an optional `{-$orgSlug}` segment, so
// the same tree serves `/policies` and `/acme/policies`; this gate, mounted
// inside the authenticated shell, pins the URL to the active org's slug:
//
//   - bare URL                  → replace with `/<active-slug>/…` (canonicalize)
//   - active slug already in URL → render
//   - any other slug in URL     → replace with `/<active-slug>/…` (canonicalize)
//
// The URL slug is the request SCOPE, not just a label: every API call carries
// it (the `x-executor-organization` header), and the server re-checks live
// membership and resolves data for that org — same as the MCP URL-pinned org.
// So a foreign slug never reaches this gate as "active" on a multi-org host:
// the server returns no organization for an org the caller can't see, and the
// shell 404s upstream. The host is what enforces that — it must not build this
// subtree until the authenticated answer NAMES the slug in the URL, or an
// optimistic answer about the session's own org (cloud's auth-hint cookie)
// would mount the shell under a foreign address before the server ever
// replies. That makes two browser tabs on different orgs fully
// independent — no shared "active org" to steal. On a single-org host (e.g.
// self-host) every slug resolves to the same org server-side, so a bogus slug
// (e.g. `/totally-bogus`) would otherwise fuzzy-match a route and render
// under the wrong URL forever; canonicalizing it here fixes the URL instead.
//
// A genuinely unmatched path is neither of the above: it has no `orgSlug`
// param (nothing below root matched) but isn't a bare URL either, so it must
// NOT canonicalize — doing so would silently rewrite a bad URL into a valid
// one instead of letting the not-found page render.
// ---------------------------------------------------------------------------

export interface OrgSlugGateProps {
  /** The active organization's slug (from `useAuth().organization`). */
  readonly activeSlug: string;
  readonly children: ReactNode;
}

export function OrgSlugGate(props: OrgSlugGateProps) {
  const { activeSlug } = props;
  const params = useParams({ strict: false }) as { orgSlug?: string };
  const urlSlug = params.orgSlug ?? null;
  const navigate = useNavigate();

  // Skip canonicalization whenever the router is currently sitting on a
  // not-found match — see the file header for why.
  const isNotFound = useRouterState({
    select: (state) => state.matches.some((match) => match._notFound),
  });

  const needsCanonicalize = urlSlug !== activeSlug && !isNotFound;

  useEffect(() => {
    if (!needsCanonicalize) return;
    // Re-target the CURRENT route with the active slug. `to: "."` +
    // `search: true` keeps path and query (deep links like
    // `/integrations/add/mcp?url=…` canonicalize in place); only the orgSlug
    // param changes.
    void navigate({
      to: ".",
      params: (previous: Record<string, string>) => ({ ...previous, orgSlug: activeSlug }),
      search: true,
      replace: true,
    });
  }, [needsCanonicalize, activeSlug, navigate]);

  // Render through while canonicalizing — the target is the same route, so
  // withholding children would only flash the page.
  return <>{props.children}</>;
}
