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

import { getTenantFonts, type TenantFont, type TenantFontVariant } from '../api';

const fontLoaders = new Map<string, Promise<void>>();

export function useTenantFonts() {
  const { data, isLoading, isFetching, refetch } = useQuery({
    queryKey: ['tenant', 'fonts'],
    queryFn: getTenantFonts,
    staleTime: 6 * 60 * 60 * 1000,
  });

  return {
    fonts: data ?? [],
    isLoading: isLoading || isFetching,
    refetch,
  };
}

export function ensureFontLoaded(font: TenantFont, preferred?: { weight?: number; style?: string }): Promise<void> {
  if (typeof document === 'undefined' || typeof window === 'undefined') {
    return Promise.resolve();
  }

  const variant = pickVariant(font, preferred);
  if (!variant) {
    return Promise.resolve();
  }

  const key = `${font.family}-${variant.weight}-${variant.style}`;

  if (document.fonts?.check(`1rem "${font.family}"`)) {
    return Promise.resolve();
  }

  if (! fontLoaders.has(key)) {
    const loader = new FontFace(font.family, `url(${variant.url})`, {
      weight: String(variant.weight ?? ''),
      style: variant.style ?? 'normal',
      display: 'swap',
    })
      .load()
      .then((fontFace) => {
        document.fonts.add(fontFace);
      })
      .catch((error) => {
        console.warn('[fonts] failed to load font', font.family, variant, error);
        fontLoaders.delete(key);
      });

    fontLoaders.set(key, loader);
  }

  return fontLoaders.get(key) ?? Promise.resolve();
}

function pickVariant(font: TenantFont, preferred?: { weight?: number; style?: string }): TenantFontVariant | null {
  const variants = font.variants ?? [];
  if (! variants.length) {
    return null;
  }

  if (preferred?.weight || preferred?.style) {
    const found = variants.find((variant) => {
      const matchesWeight = preferred.weight ? Number(variant.weight) === Number(preferred.weight) : true;
      const matchesStyle = preferred.style ? variant.style === preferred.style : true;
      return matchesWeight && matchesStyle;
    });
    if (found) {
      return found;
    }
  }

  return variants[0];
}

