import { useQuery } from '@tanstack/react-query'
import { useAuth } from 'react-oidc-context'
import { apiClient } from '@/api/client'

/**
 * Lookup user display info по UUID (JWT sub). Backed by backend in-memory
 * cache (заполняется на каждом authenticated request через
 * JwtUserCaptureFilter). Returns null если sub не в кэше — frontend
 * fallback'нёт на short UUID.
 *
 * <p>Stale-while-revalidate: TanStack Query кэширует 5 минут, refetch
 * on focus. Cheap — endpoint = O(1) hash lookup, no DB hit.
 *
 * <p>404 → данных нет; не считаем error (через retry: false + handle null).
 */
type UserDisplayInfo = {
  sub: string
  preferredUsername?: string | null
  name?: string | null
  email?: string | null
  updatedAt: string
}

const useResolveUserDisplay = (uuid: string | null | undefined) =>
  useQuery({
    queryKey: ['user-display', uuid] as const,
    enabled: Boolean(uuid),
    staleTime: 5 * 60 * 1000,
    retry: false,
    queryFn: async (): Promise<UserDisplayInfo | null> => {
      if (!uuid) return null
      try {
        const { data } = await apiClient.get<UserDisplayInfo>(
          `/admin/users/${encodeURIComponent(uuid)}/display`,
        )
        return data
      } catch (e: unknown) {
        const status = (e as { response?: { status?: number } })?.response?.status
        // 404 = user не в кэше; 403 = у actor'а scope insufficient — оба
        // не error, просто нет данных. Frontend fallback'нёт на short UUID.
        if (status === 404 || status === 403) return null
        throw e
      }
    },
  })

/**
 * Resolve UUID sub claim (Keycloak {@code sub} → makerId / userId) к
 * human-friendly display string.
 *
 * <p>Cases:
 * <ul>
 *   <li><b>uuid matches current user</b> → {@code "Я • <preferred_username>"}
 *       (или just {@code "Я"} если profile неполный).</li>
 *   <li><b>different user, cached на backend</b> → preferred_username из кэша.
 *       Full ID + email + name доступны через extended fields.</li>
 *   <li><b>different user, не cached</b> → first 8 chars of UUID. Full ID в
 *       {@code fullId} чтобы consumer мог положить в {@code title=...}.</li>
 *   <li><b>null/undefined uuid</b> → {@code "anonymous"}.</li>
 * </ul>
 *
 * <p>Backend endpoint: {@code GET /api/v1/admin/users/{sub}/display} — backed
 * by in-memory cache (заполняется JwtUserCaptureFilter на каждом authenticated
 * request). Если backend pod restart'нулся, кэш пуст — postepenно заполняется
 * обратно. Frontend gracefully fallback'ит на short UUID.
 *
 * <p>Используется везде где UI показывает actor: AUTHOR в таблицах
 * /reviews (record + schema), USER в /audit log, AUTHOR в schema draft
 * drawer.
 */
export function useUserDisplay(uuid: string | null | undefined): {
  display: string
  isMe: boolean
  fullId: string
  preferredUsername?: string | null
  name?: string | null
  email?: string | null
} {
  const auth = useAuth()
  const fullId = uuid ?? ''
  const resolved = useResolveUserDisplay(fullId)
  if (!fullId) {
    return { display: 'anonymous', isMe: false, fullId: '' }
  }
  const currentSub = auth.user?.profile?.sub
  const isMe = Boolean(currentSub) && currentSub === fullId
  if (isMe) {
    const me =
      (auth.user?.profile?.preferred_username as string | undefined) ||
      (auth.user?.profile?.name as string | undefined) ||
      (auth.user?.profile?.email as string | undefined)
    return { display: me ? `Я • ${me}` : 'Я', isMe, fullId }
  }
  const info = resolved.data
  if (info?.preferredUsername || info?.name) {
    return {
      display: info.preferredUsername || info.name || fullId.substring(0, 8),
      isMe,
      fullId,
      preferredUsername: info.preferredUsername,
      name: info.name,
      email: info.email,
    }
  }
  // Fallback — кэш empty или user ещё не появлялся на этом backend'е.
  return { display: fullId.substring(0, 8), isMe, fullId }
}

/**
 * UserCell — convenience component для тех мест где нужен readonly displaу
 * с tooltip. Используется в таблицах.
 *
 * <p>Tooltip содержит full UUID + email + name (если есть в кэше) для
 * disambiguation: short UUID prefix может collide между users.
 */
export function UserCell({ uuid }: { uuid: string | null | undefined }) {
  const { display, isMe, fullId, name, email } = useUserDisplay(uuid)
  if (!fullId) return <span className="text-mute italic">anonymous</span>
  const tooltip = [fullId, name, email].filter(Boolean).join('\n')
  return (
    <span
      className={isMe ? 'text-ink' : 'font-mono text-ink-2'}
      title={tooltip || fullId}
    >
      {display}
    </span>
  )
}
