/**
 * SSR dehydration helper for Multideal HydratedIsland pattern.
 *
 * Usage in Astro frontmatter (Cloudflare Worker):
 *
 *   const { dehydratedState } = await dehydrateForIsland([
 *     (qc) => qc.prefetchQuery({ queryKey: qk.cart(), queryFn: loadCart }),
 *   ]);
 *
 * Each prefetch fn receives a fresh per-request QueryClient.
 * The client is NEVER reused across requests.
 */

import { dehydrate, type DehydratedState } from '@tanstack/react-query';
import { createServerQueryClient } from './client';
import type { DrizzleDb } from '@/server/db/client';
import * as directoryQueries from '@/server/db/queries/vendorDirectory.js';
import type { StoresResponse } from '@/features/stores/useStores';
import type { StoresUrlState } from '@/lib/url/codecs/storesCodec';

export type PrefetchFn = (qc: ReturnType<typeof createServerQueryClient>) => Promise<void>;

/**
 * Build a per-request QueryClient, run all prefetch fns in parallel,
 * then return the dehydrated state for island hydration.
 *
 * Safe to call with an empty array — returns empty dehydrated state.
 */
export async function dehydrateForIsland(
  prefetchFns: PrefetchFn[],
): Promise<{ dehydratedState: DehydratedState }> {
  if (prefetchFns.length === 0) return { dehydratedState: { mutations: [], queries: [] } };
  const qc = createServerQueryClient();
  await Promise.all(prefetchFns.map((fn) => fn(qc)));
  return { dehydratedState: dehydrate(qc) };
}

/**
 * Prefetch stores page data (page 1, no filters, perPage=12 matching Stores.tsx).
 * Returns a PrefetchFn bound to the given Drizzle client.
 */
export function makePrefetchStoresData(db: DrizzleDb, state: StoresUrlState): PrefetchFn {
  const filters = {
    ...(state.query ? { query: state.query } : {}),
    ...(state.city ? { city: state.city } : {}),
    ...(state.businessTypeId ? { businessTypeId: state.businessTypeId } : {}),
    hours: state.hours,
    sortBy: state.sortBy,
  };
  return async (qc) => {
    await qc.prefetchQuery({
      queryKey: ['stores', filters, state.page, 12],
      queryFn: async (): Promise<StoresResponse> => {
        const [{ vendors, nextCursor, totalCount, totalPages }, cities, businessTypes] =
          await Promise.all([
            directoryQueries.listForDirectory(db, {
              ...filters,
              page: state.page,
              limit: 12,
            }),
            directoryQueries.getDistinctCities(db),
            directoryQueries.getActiveBusinessTypes(db),
          ]);
        return {
          ok: true,
          stores: vendors,
          nextCursor,
          totalCount,
          totalPages,
          filters: { cities, businessTypes },
        };
      },
    });
  };
}
