"use client";

/**
 * MIRROR of main frontend `frontend/src/components/auth/RouteGuard.tsx` —
 * keep in sync manually.
 *
 * Особенность tradein-mvp: Next.js basePath=/trade-in (см. `next.config.ts`).
 * `usePathname()` возвращает путь БЕЗ basePath — например на странице
 * `gendsgn.ru/trade-in/scrapers/avito` хук вернёт `/scrapers/avito`.
 * RBAC config (`auth/roles.yaml`) использует абсолютные пути сайта
 * (`/trade-in/**`, `/trade-in/api/v1/admin/**`), поэтому перед проверкой
 * isPathAllowed мы префиксим pathname через NEXT_PUBLIC_BASE_PATH.
 */

import { usePathname } from "next/navigation";

import { NoAccessScreen } from "@/components/auth/NoAccessScreen";
import { HTTPError } from "@/lib/api";
import { isPathAllowed } from "@/lib/isPathAllowed";
import { useMe } from "@/lib/useMe";

const BASE_PATH = process.env.NEXT_PUBLIC_BASE_PATH ?? "";
// #801: dev/CI-only preview-маршрут (a11y/lighthouse) рендерится оффлайн без RBAC.
const ENABLE_PREVIEW = process.env.NEXT_PUBLIC_ENABLE_PREVIEW === "1";

interface RouteGuardProps {
  children: React.ReactNode;
}

export function RouteGuard({ children }: RouteGuardProps) {
  const rawPath = usePathname() ?? "/";
  // Абсолютный путь сайта: BASE_PATH + rawPath. Аккуратно с двойным слэшем
  // на `/`: `BASE_PATH = "/trade-in"` + `"/"` → `/trade-in/` (ок).
  const absolutePath = BASE_PATH
    ? `${BASE_PATH}${rawPath === "/" ? "/" : rawPath}`
    : rawPath;
  const { data, isLoading, error } = useMe();

  // #801: preview-страница самодостаточна (свой QueryClient с фейковым me),
  // RBAC к ней не применяем. Только под флагом — в проде по умолчанию выключено.
  if (ENABLE_PREVIEW && rawPath.startsWith("/ui-preview")) {
    return <>{children}</>;
  }

  if (isLoading) return null;

  if (error instanceof HTTPError && error.status === 401) {
    // Dev without Caddy: 401 is normal, mount the app so local dev works.
    // Prod: mounting children on 401 causes TanStack Query re-subscribe storm
    // (each new observer on errored query triggers a refetch). Show session screen
    // instead — prevents the subtree from mounting, kills the loop.
    if (process.env.NODE_ENV !== "production") return <>{children}</>;
    return <NoAccessScreen variant="session" />;
  }

  if (error instanceof HTTPError && error.status === 403) {
    return <NoAccessScreen variant="user" />;
  }

  if (error) {
    return <NoAccessScreen variant="user" />;
  }

  if (!data) return null;

  // Пробный доступ закончился (#praktika): role=expired → спец-экран, а не generic path-deny.
  if (data.role === "expired") {
    return <NoAccessScreen variant="trial" />;
  }

  if (!isPathAllowed(data.allowed_paths, data.deny_paths, absolutePath)) {
    return <NoAccessScreen variant="path" path={absolutePath} />;
  }

  return <>{children}</>;
}
