"use client";

/**
 * RouteGuard — клиентский гард, оборачивающий весь app в layout.tsx.
 *
 * Логика:
 *   - useMe() loading → null (короткое окно; основной UI вернётся когда
 *     /me ответит, обычно <50 ms из браузер-cache после первого захода)
 *   - useMe() 403 (юзер не в roles.yaml) → fullscreen NoAccessScreen("user")
 *   - useMe() 401 (dev без Caddy basic_auth) → пропускаем (dev escape-hatch).
 *     Это критично — без этого локально без Caddy фронт станет полностью
 *     белым. В проде Caddy всегда ставит X-Authenticated-User → 401 невозможен.
 *   - useMe() ok + pathname ∉ allowed_paths (или ∈ deny_paths) → fullscreen
 *     NoAccessScreen("path"). Не редиректим — у user намеренный direct-URL
 *     hit на /admin (например), и redirect замаскирует, что у него нет
 *     доступа. Прямо говорим «нет».
 *   - useMe() ok + pathname разрешён → пропускаем children.
 *
 * Backend всё равно сам блокирует /api/v1/* — этот гард только для UX
 * («не показывать ссылки и не позволять открыть страницу через URL»).
 */

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";

interface RouteGuardProps {
  children: React.ReactNode;
}

export function RouteGuard({ children }: RouteGuardProps) {
  const pathname = usePathname() ?? "/";
  const { data, isLoading, error } = useMe();

  // #801: dev/CI-only mock-render маршрут `/__preview/*` — намеренно БЕЗ
  // auth-gate. Без этого bypass `useMe()` без бэкенда падает network-fail'ом
  // → ветка `if (error)` ниже подменяет content на <NoAccessScreen>, и
  // axe / lighthouse аудируют экран «доступа нет» вместо «денежного экрана».
  // Сама preview-страница 404'ит вне dev/CI (NEXT_PUBLIC_ENABLE_PREVIEW),
  // и сам bypass дополнительно gated тем же env-условием — чтобы будущий
  // `/__preview/*` route не оказался без auth в prod (defense-in-depth).
  if (
    pathname.startsWith("/__preview") &&
    (process.env.NODE_ENV !== "production" ||
      process.env.NEXT_PUBLIC_ENABLE_PREVIEW === "true")
  ) {
    return <>{children}</>;
  }

  // Initial load — короткое окно, рендерим пустоту чтобы не моргать UI.
  if (isLoading) return null;

  // 401 — dev без Caddy basic_auth. Пропускаем как «нет RBAC, all allowed».
  if (error instanceof HTTPError && error.status === 401) {
    return <>{children}</>;
  }

  // 403 — юзер не в roles.yaml. Прям ничего не показываем кроме «доступа нет».
  if (error instanceof HTTPError && error.status === 403) {
    return <NoAccessScreen variant="user" />;
  }

  // Другая сетевая ошибка — fail-open в dev / показываем NoAccess в prod-like.
  // Безопаснее закрыть UI чем случайно пустить юзера на admin при transient
  // network fail. NoAccessScreen("user") универсальный fallback.
  if (error) {
    return <NoAccessScreen variant="user" />;
  }

  // Нет scope (теоретически unreachable — либо error либо data) — заглушка.
  if (!data) return null;

  // Path-level guard на прямой URL. Backend всё равно 403 на /api/v1/admin/*,
  // но мы не хотим показать «битый admin UI» — лучше сразу stop.
  if (!isPathAllowed(data.allowed_paths, data.deny_paths, pathname)) {
    // #799: pilot-only юзер (единственная доступная зона — trade-in) на
    // запрещённом пути главного фронта (корень `/` и пр.) → авто-redirect в
    // /trade-in/ вместо дед-энда «Доступа нет». Условия:
    //   - роль pilot (trade-in — её ЕДИНСТВЕННАЯ рабочая зона; paths scoped
    //     только на /trade-in/**). #1439: без этой проверки multi-zone роли
    //     (напр. analyst с paths="/**") на запрещённом /admin/* молча
    //     редиректились в /trade-in/ вместо честного NoAccessScreen;
    //   - текущий путь НЕ под /trade-in (иначе цикл; /trade-in — отдельный
    //     bundle за Caddy, этот гард его не обслуживает, но guard на всякий);
    //   - у роли есть доступ к /trade-in/ (т.е. trade-in — её рабочая зона).
    // admin / multi-scope с разрешённым `/` сюда не попадают (isPathAllowed=true).
    if (
      typeof window !== "undefined" &&
      data.role === "pilot" &&
      !pathname.startsWith("/trade-in") &&
      isPathAllowed(data.allowed_paths, data.deny_paths, "/trade-in/")
    ) {
      window.location.replace("/trade-in/");
      return null;
    }
    return <NoAccessScreen variant="path" path={pathname} />;
  }

  return <>{children}</>;
}
