import { usePage } from '@inertiajs/react';
import { useCallback, useRef } from 'react';
import type { PageProps } from '@/types';

type BackgroundTarget = 'admin' | 'teacher';

type BackgroundEntry = {
  id?: number;
  preview_path?: string | null;
};

type BackgroundPayload = {
  props?: {
    backgrounds?: BackgroundEntry[];
  };
};

const PREFETCH_COUNT = 3;

const TARGET_CONFIG: Record<
  BackgroundTarget,
  {
    url: string;
    component: string;
    partialData: string;
  }
> = {
  admin: {
    url: '/admin/settings/background',
    component: 'Admin/Settings/Background',
    partialData: 'backgrounds',
  },
  teacher: {
    url: '/settings/background',
    component: 'Teacher/Settings/Background',
    partialData: 'backgrounds',
  },
};

const sanitizePreviewPath = (value?: string | null): string | null => {
  if (typeof value !== 'string') return null;
  const trimmed = value.trim();
  return trimmed.length > 0 ? trimmed : null;
};

export function useBackgroundPrefetch() {
  const { version } = usePage<PageProps>();
  const fetchedTargetsRef = useRef<Set<BackgroundTarget>>(new Set());
  const prefetchedImagesRef = useRef<Set<string>>(new Set());

  const queueImage = useCallback((src: string) => {
    if (prefetchedImagesRef.current.has(src)) {
      return Promise.resolve();
    }

    prefetchedImagesRef.current.add(src);

    return new Promise<void>((resolve) => {
      const img = new Image();
      img.onload = () => resolve();
      img.onerror = () => resolve();
      img.src = src;
    });
  }, []);

  const prefetchBackgroundImages = useCallback(
    async (target: BackgroundTarget) => {
      const config = TARGET_CONFIG[target];
      if (!config) return;
      if (fetchedTargetsRef.current.has(target)) return;

      fetchedTargetsRef.current.add(target);
      try {
        const headers: Record<string, string> = {
          Accept: 'application/json',
          'X-Requested-With': 'XMLHttpRequest',
          'X-Inertia': 'true',
          'X-Inertia-Partial-Component': config.component,
          'X-Inertia-Partial-Data': config.partialData,
        };

        if (version) {
          headers['X-Inertia-Version'] = String(version);
        }

        const response = await fetch(config.url, {
          method: 'GET',
          credentials: 'same-origin',
          headers,
        });

        if (response.status === 409) {
          window.location.reload();
          return;
        }

        if (!response.ok) {
          throw new Error(`Failed to prefetch backgrounds for ${target}: ${response.status}`);
        }

        const payload = (await response.json()) as BackgroundPayload;
        const backgrounds = payload?.props?.backgrounds ?? [];
        const urls = backgrounds
          .slice(0, PREFETCH_COUNT)
          .map((bg) => sanitizePreviewPath(bg?.preview_path))
          .filter((url): url is string => typeof url === 'string');

        await Promise.all(urls.map((src) => queueImage(src)));
      } catch (error) {
        console.warn(`[BackgroundPrefetch] Unable to preload backgrounds for ${target}`, error);
        fetchedTargetsRef.current.delete(target);
      }
    },
    [queueImage, version]
  );

  return { prefetchBackgroundImages };
}
