/**
 * Server-side module registry — config + loadData ONLY.
 *
 * SSR / API handlers only read `configSchema` (for zod validation) and
 * `loadData` (for hydration). They never read `Component` or `ConfigEditor`
 * — those are React island concerns and live in `client-registry.ts`.
 *
 * Eager-loading `Component.tsx` + `ConfigEditor.tsx` here pulled React, the
 * full UI library, lucide icons, and feature code into the SSR worker bundle
 * for every module, ballooning per-request eval cost. Cache-miss home
 * renders consistently exceeded the Cloudflare Worker per-request CPU
 * budget → error 1102. Trimming the eager glob to the two files the server
 * actually consumes keeps the cache-miss render path under budget.
 *
 * Never import this file from React islands — `loadData` pulls
 * `cloudflare:workers` via `@/server/db`. Use `client-registry.ts` instead.
 *
 * NOTE: Explicit static imports replace the former `import.meta.glob` calls.
 * `import.meta.glob` is a Vite-only API; the now-merged web-do worker used to
 * bundle with plain wrangler/esbuild (no Vite), so the glob blew up at runtime
 * (error 10021: `glob is not a function`). Static imports remain portable
 * regardless of bundler.
 */
import type { z } from 'zod';
import type { DrizzleClient } from '@/server/db/client';
import type { LoadCtx } from './types';

type ConfigMod = {
  type: string;
  category: 'deal-row' | 'banner' | 'vendor-spotlight' | 'static' | 'custom' | 'content';
  labelKey: string;
  defaultConfig: unknown;
  configSchema: z.ZodType<unknown>;
};
type LoadDataMod = {
  loadData: (db: DrizzleClient, config: unknown, ctx: LoadCtx) => Promise<unknown>;
};

/**
 * Server-only module definition. Strictly smaller than `ModuleDef` (which
 * also carries React Component + ConfigEditor for client use).
 */
export interface ServerModuleDef<TConfig> {
  type: string;
  category: ConfigMod['category'];
  labelKey: string;
  defaultConfig: TConfig;
  configSchema: z.ZodType<TConfig>;
  loadData: (db: DrizzleClient, config: TConfig, ctx: LoadCtx) => Promise<unknown>;
}

// ---------------------------------------------------------------------------
// Explicit static imports (replaces import.meta.glob — portable across
// bundlers, see NOTE above).
// ---------------------------------------------------------------------------

import * as bannerConfig from './modules/banner/config';
import * as bannerLoad from './modules/banner/loadData';

import * as categoryChipsConfig from './modules/category-chips/config';
import * as categoryChipsLoad from './modules/category-chips/loadData';

import * as clubStoriesConfig from './modules/club-stories/config';
import * as clubStoriesLoad from './modules/club-stories/loadData';

import * as dealGridConfig from './modules/deal-grid/config';
import * as dealGridLoad from './modules/deal-grid/loadData';

import * as dealRowAutoScrollConfig from './modules/deal-row-auto-scroll/config';
import * as dealRowAutoScrollLoad from './modules/deal-row-auto-scroll/loadData';

import * as dealRowCategoryConfig from './modules/deal-row-category/config';
import * as dealRowCategoryLoad from './modules/deal-row-category/loadData';

import * as dealRowCustomQueryConfig from './modules/deal-row-custom-query/config';
import * as dealRowCustomQueryLoad from './modules/deal-row-custom-query/loadData';

import * as dealRowAffinityConfig from './modules/deal-row-affinity/config';
import * as dealRowAffinityLoad from './modules/deal-row-affinity/loadData';

import * as dealRowForYouConfig from './modules/deal-row-for-you/config';
import * as dealRowForYouLoad from './modules/deal-row-for-you/loadData';

import * as dealRowGroupDealsConfig from './modules/deal-row-group-deals/config';
import * as dealRowGroupDealsLoad from './modules/deal-row-group-deals/loadData';

import * as dealRowHotDealsConfig from './modules/deal-row-hot-deals/config';
import * as dealRowHotDealsLoad from './modules/deal-row-hot-deals/loadData';

import * as dealRowNearYouConfig from './modules/deal-row-near-you/config';
import * as dealRowNearYouLoad from './modules/deal-row-near-you/loadData';

import * as dealRowWhatsLeftConfig from './modules/deal-row-whats-left/config';
import * as dealRowWhatsLeftLoad from './modules/deal-row-whats-left/loadData';

import * as greetingBarConfig from './modules/greeting-bar/config';
import * as greetingBarLoad from './modules/greeting-bar/loadData';

import * as heroStaticPageConfig from './modules/hero-static-page/config';
import * as heroStaticPageLoad from './modules/hero-static-page/loadData';

import * as merchantGridConfig from './modules/merchant-grid/config';
import * as merchantGridLoad from './modules/merchant-grid/loadData';

import * as merchantScrollConfig from './modules/merchant-scroll/config';
import * as merchantScrollLoad from './modules/merchant-scroll/loadData';

import * as pageHeroConfig from './modules/page-hero/config';
import * as pageHeroLoad from './modules/page-hero/loadData';

import * as richTextContentConfig from './modules/rich-text-content/config';
import * as richTextContentLoad from './modules/rich-text-content/loadData';

import * as staticContentConfig from './modules/static-content/config';
import * as staticContentLoad from './modules/static-content/loadData';

import * as tickerStripConfig from './modules/ticker-strip/config';
import * as tickerStripLoad from './modules/ticker-strip/loadData';

import * as vendorSpotlightConfig from './modules/vendor-spotlight/config';
import * as vendorSpotlightLoad from './modules/vendor-spotlight/loadData';

// ---------------------------------------------------------------------------
// Registry construction
// ---------------------------------------------------------------------------

const MODULE_ENTRIES: Array<{ cfg: ConfigMod; load: LoadDataMod }> = [
  { cfg: bannerConfig as unknown as ConfigMod, load: bannerLoad as unknown as LoadDataMod },
  {
    cfg: categoryChipsConfig as unknown as ConfigMod,
    load: categoryChipsLoad as unknown as LoadDataMod,
  },
  {
    cfg: clubStoriesConfig as unknown as ConfigMod,
    load: clubStoriesLoad as unknown as LoadDataMod,
  },
  { cfg: dealGridConfig as unknown as ConfigMod, load: dealGridLoad as unknown as LoadDataMod },
  {
    cfg: dealRowAutoScrollConfig as unknown as ConfigMod,
    load: dealRowAutoScrollLoad as unknown as LoadDataMod,
  },
  {
    cfg: dealRowCategoryConfig as unknown as ConfigMod,
    load: dealRowCategoryLoad as unknown as LoadDataMod,
  },
  {
    cfg: dealRowCustomQueryConfig as unknown as ConfigMod,
    load: dealRowCustomQueryLoad as unknown as LoadDataMod,
  },
  {
    cfg: dealRowAffinityConfig as unknown as ConfigMod,
    load: dealRowAffinityLoad as unknown as LoadDataMod,
  },
  {
    cfg: dealRowForYouConfig as unknown as ConfigMod,
    load: dealRowForYouLoad as unknown as LoadDataMod,
  },
  {
    cfg: dealRowGroupDealsConfig as unknown as ConfigMod,
    load: dealRowGroupDealsLoad as unknown as LoadDataMod,
  },
  {
    cfg: dealRowHotDealsConfig as unknown as ConfigMod,
    load: dealRowHotDealsLoad as unknown as LoadDataMod,
  },
  {
    cfg: dealRowNearYouConfig as unknown as ConfigMod,
    load: dealRowNearYouLoad as unknown as LoadDataMod,
  },
  {
    cfg: dealRowWhatsLeftConfig as unknown as ConfigMod,
    load: dealRowWhatsLeftLoad as unknown as LoadDataMod,
  },
  {
    cfg: greetingBarConfig as unknown as ConfigMod,
    load: greetingBarLoad as unknown as LoadDataMod,
  },
  {
    cfg: heroStaticPageConfig as unknown as ConfigMod,
    load: heroStaticPageLoad as unknown as LoadDataMod,
  },
  {
    cfg: merchantGridConfig as unknown as ConfigMod,
    load: merchantGridLoad as unknown as LoadDataMod,
  },
  {
    cfg: merchantScrollConfig as unknown as ConfigMod,
    load: merchantScrollLoad as unknown as LoadDataMod,
  },
  { cfg: pageHeroConfig as unknown as ConfigMod, load: pageHeroLoad as unknown as LoadDataMod },
  {
    cfg: richTextContentConfig as unknown as ConfigMod,
    load: richTextContentLoad as unknown as LoadDataMod,
  },
  {
    cfg: staticContentConfig as unknown as ConfigMod,
    load: staticContentLoad as unknown as LoadDataMod,
  },
  {
    cfg: tickerStripConfig as unknown as ConfigMod,
    load: tickerStripLoad as unknown as LoadDataMod,
  },
  {
    cfg: vendorSpotlightConfig as unknown as ConfigMod,
    load: vendorSpotlightLoad as unknown as LoadDataMod,
  },
];

export const MODULE_REGISTRY: Record<string, ServerModuleDef<unknown>> = {};

for (const { cfg, load } of MODULE_ENTRIES) {
  MODULE_REGISTRY[cfg.type] = {
    type: cfg.type,
    category: cfg.category,
    labelKey: cfg.labelKey,
    defaultConfig: cfg.defaultConfig,
    configSchema: cfg.configSchema,
    loadData: load.loadData,
  };
}

export function getModule(type: string): ServerModuleDef<unknown> | undefined {
  return MODULE_REGISTRY[type];
}

/** Override/inject a module def at runtime. Used by tests for stub isolation. */
export function registerModule<T>(def: ServerModuleDef<T>): void {
  MODULE_REGISTRY[def.type] = {
    ...def,
    defaultConfig: def.defaultConfig,
    configSchema: def.configSchema as ServerModuleDef<unknown>['configSchema'],
    loadData: (db, config, ctx) => def.loadData(db, config as T, ctx),
  };
}
