/**
 * useConstructorData Hook
 *
 * Orchestrates all data fetching for the constructor page using React Query.
 * Replaces the manual loadData function with cached, deduplicated queries.
 */

import { useMemo } from 'react';
import { useProjectQuery } from './queries/useProjectQuery';
import { usePagesQuery } from './queries/usePagesQuery';
import { useAssetsQuery } from './queries/useAssetsQuery';
import { useElementDefaultsQuery } from './queries/useElementDefaultsQuery';
import { extractPageLinksAndElements } from '../lib/extractPageLinks';
import type { TourPage, Asset } from '../types/entities';
import type { CanvasElementType, CanvasElement } from '../types/constructor';
import type { PreloadPageLink, PreloadElement } from '../types/preload';

interface UseConstructorDataParams {
  projectId: string | undefined;
  isAuthReady: boolean;
}

// Stable empty references to prevent infinite loops from identity changes
const EMPTY_ELEMENT_DEFAULTS: Partial<
  Record<CanvasElementType, Partial<CanvasElement>>
> = {};
const EMPTY_PAGES: TourPage[] = [];
const EMPTY_ASSETS: Asset[] = [];

interface UseConstructorDataResult {
  // Project
  project: { name: string } | null;
  projectName: string;

  // Pages
  pages: TourPage[];
  pageLinks: PreloadPageLink[];
  allPagesPreloadElements: PreloadElement[];

  // Assets
  assets: Asset[];

  // Element Defaults
  uiElementDefaultsByType: Partial<
    Record<CanvasElementType, Partial<CanvasElement>>
  >;

  // Loading state
  isLoading: boolean;
  isError: boolean;
  error: Error | null;

  // Refetch function
  refetch: () => Promise<void>;
}

export function useConstructorData({
  projectId,
  isAuthReady,
}: UseConstructorDataParams): UseConstructorDataResult {
  // Enable queries only when we have projectId and auth is ready
  const enabled = Boolean(projectId) && isAuthReady;

  // Fetch project
  const projectQuery = useProjectQuery(enabled ? projectId : undefined);

  // Fetch pages (dev environment for constructor)
  const pagesQuery = usePagesQuery(enabled ? projectId : undefined, 'dev');

  // Fetch assets
  const assetsQuery = useAssetsQuery(enabled ? projectId : undefined, {
    limit: 500,
  });

  // Fetch element defaults
  const elementDefaultsQuery = useElementDefaultsQuery(
    enabled ? projectId : undefined,
  );

  // Extract page links and preload elements from pages
  const { pageLinks, allPagesPreloadElements } = useMemo(() => {
    if (!pagesQuery.data || pagesQuery.data.length === 0) {
      return {
        pageLinks: [] as PreloadPageLink[],
        allPagesPreloadElements: [] as PreloadElement[],
      };
    }
    const { pageLinks: links, preloadElements: elements } =
      extractPageLinksAndElements(pagesQuery.data as TourPage[]);
    return { pageLinks: links, allPagesPreloadElements: elements };
  }, [pagesQuery.data]);

  // Combine loading states
  const isLoading =
    projectQuery.isLoading ||
    pagesQuery.isLoading ||
    assetsQuery.isLoading ||
    elementDefaultsQuery.isLoading;

  // Combine error states
  const isError =
    projectQuery.isError ||
    pagesQuery.isError ||
    assetsQuery.isError ||
    elementDefaultsQuery.isError;

  const error =
    projectQuery.error ||
    pagesQuery.error ||
    assetsQuery.error ||
    elementDefaultsQuery.error;

  // Refetch all queries
  const refetch = async () => {
    await Promise.all([
      projectQuery.refetch(),
      pagesQuery.refetch(),
      assetsQuery.refetch(),
      elementDefaultsQuery.refetch(),
    ]);
  };

  return {
    // Project
    project: projectQuery.data || null,
    projectName: projectQuery.data?.name || '',

    // Pages
    pages: (pagesQuery.data as TourPage[]) || EMPTY_PAGES,
    pageLinks,
    allPagesPreloadElements,

    // Assets
    assets: (assetsQuery.data as Asset[]) || EMPTY_ASSETS,

    // Element Defaults
    uiElementDefaultsByType:
      elementDefaultsQuery.data || EMPTY_ELEMENT_DEFAULTS,

    // Loading state
    isLoading,
    isError,
    error: error instanceof Error ? error : null,

    // Refetch
    refetch,
  };
}

export default useConstructorData;
