import type { z } from 'zod';
import type { DrizzleClient } from '@/server/db/client';
import type { Locale } from '@/lib/i18n';
import type React from 'react';
import type { DealRow } from '@/features/feed/FeedDataLoader';

export interface LocalizedText {
  he: string;
  en: string;
}

export interface ModuleVisibility {
  guests: boolean;
  loggedIn: boolean;
}

export interface LayoutModule<TConfig = unknown> {
  instanceId: string;
  type: string;
  config: TConfig;
  visibility: ModuleVisibility;
}

export interface LayoutBody {
  mobile: LayoutModule[];
  desktop: LayoutModule[];
}

export interface LoadCtx {
  userId?: string;
  isGuest: boolean;
  locale: Locale;
  /** Request-level geo hint from the edge (Cloudflare `request.cf`). */
  geo?: { lat: number; lng: number; country: string };
  /** Pre-fetched once per request to avoid N duplicate DB subrequests. */
  hotDealThreshold?: number;
  /** Route-level dynamic params (e.g. { slug: 'food' } from /category/[slug]). Passed by the
   *  Astro route shell so that module loadData can read e.g. ctx.routeParams?.slug. */
  routeParams?: Record<string, string>;
  /**
   * Pre-fetched pool of active deals (top 200, ordered by recency).
   * Injected by the loader for guest pages so that deal-row modules can
   * filter in-memory instead of firing individual Neon HTTP round-trips.
   * User-specific modules (near-you, hot-deals velocity, per-user wishlist)
   * ignore this field and query directly.
   */
  prefetchedDeals?: DealRow[];
  /**
   * Request-level cache for resolved category slugs.
   * Populated lazily by deal-row:category loadData to avoid N+1 Neon queries
   * when multiple category rows target the same category on one page.
   */
  resolvedCategorySlugs?: Map<string, string>;
}

export interface ClientModuleDef<TConfig> {
  type: string;
  category: 'deal-row' | 'banner' | 'vendor-spotlight' | 'static' | 'custom' | 'content';
  labelKey: string;
  defaultConfig: TConfig;
  configSchema: z.ZodType<TConfig>;
  ConfigEditor: React.FC<{ instanceId?: string; config: TConfig; onChange: (c: TConfig) => void }>;
  Component: React.FC<{ config: TConfig; data: unknown; demo?: boolean }>;
}

export interface ModuleDef<TConfig> extends ClientModuleDef<TConfig> {
  loadData: (db: DrizzleClient, config: TConfig, ctx: LoadCtx) => Promise<unknown>;
}
