"use client";

/**
 * `useMe()` — TanStack-хук для GET /api/v1/me.
 *
 * Backend возвращает `UserScope` (см. `backend/app/core/auth.py`):
 *   { username, role: "admin"|"pilot"|"analyst", allowed_paths: string[], deny_paths: string[] }
 *
 * Failure modes:
 *   - 401 — нет X-Authenticated-User (локально без Caddy basic_auth). Фронт
 *     трактует это как «dev-режим» и в этом случае route-guard ничего не
 *     блокирует (см. RouteGuard).
 *   - 403 — header есть, но юзер не в `auth/roles.yaml`. Фронт показывает
 *     полноэкранный NoAccessScreen и больше ничего.
 *
 * Кешируем «вечно» (`staleTime: Infinity`, без рефетча): роль не меняется
 * в рамках сессии. Если basic_auth обновится — юзер перезагрузит страницу.
 */

import { useQuery } from "@tanstack/react-query";

import { apiFetchWithStatus, HTTPError } from "@/lib/api";

// Error type для useQuery: либо `HTTPError` (от apiFetchWithStatus при 4xx/5xx),
// либо обычный `Error` (network fail, fetch reject). RouteGuard / TopNav проверяют
// статус через `error instanceof HTTPError` — это работает в runtime независимо
// от type-level decl.

// Должен совпадать с `Role` в `backend/app/core/auth.py` (Literal["admin", "pilot", "analyst"]).
// Источник правды — `auth/roles.yaml`; при добавлении новой роли расширить тут и
// `ROLE_LABELS` в `components/auth/UserMenu.tsx`.
export type Role = "admin" | "pilot" | "analyst";

export interface UserScope {
  username: string;
  role: Role;
  allowed_paths: string[];
  deny_paths: string[];
}

export const ME_QUERY_KEY = ["auth", "me"] as const;

async function fetchMe(): Promise<UserScope> {
  const { body } = await apiFetchWithStatus<UserScope>("/api/v1/me");
  return body;
}

export function useMe() {
  return useQuery<UserScope, Error>({
    queryKey: ME_QUERY_KEY,
    queryFn: fetchMe,
    staleTime: Infinity,
    gcTime: Infinity,
    refetchOnWindowFocus: false,
    refetchOnReconnect: false,
    refetchOnMount: false,
    // 401 (dev без Caddy) и 403 (unknown user) — финальные состояния,
    // ретраить бесполезно. Ретраим только сетевые сбои.
    retry: (failureCount, error) => {
      if (error instanceof HTTPError && (error.status === 401 || error.status === 403)) {
        return false;
      }
      return failureCount < 2;
    },
  });
}
