import type { IslandMode, VaryDimension } from './render-mode.js';
import type { ImageSlotContract } from './image.js';
import type { z } from 'zod';

export interface ComponentRenderModes {
  canStatic: boolean;
  canSSR: boolean;
  canClientIsland: boolean;
}

/**
 * A CMS-registered component — sync or async (server components).
 * Accepts content props derived from the Zod schema.
 */
type CmsComponentFn<TProps = any> =
  | ((props: TProps) => import('react').ReactElement | null)
  | ((props: TProps) => Promise<import('react').ReactElement | null>);

/**
 * Infers the props type from a schema.
 * If TSchema is a Zod type, returns z.infer<TSchema>.
 * Otherwise returns Record<string, unknown>.
 */
type InferContentProps<TSchema> = TSchema extends z.ZodType<infer T> ? T : Record<string, unknown>;

export interface ComponentDefinition<TSchema = unknown> {
  name: string;
  /**
   * The React component that renders this CMS block.
   * Accepts at least the schema-derived props, but may accept additional
   * composition params (className, etc.) passed by parent sections.
   */
  component?: CmsComponentFn<any>;
  schema: TSchema;
  renderModes?: ComponentRenderModes;
  render?: ComponentRenderModes;
  defaultIslandMode?: IslandMode;
  varyDimensions?: VaryDimension[];
  vary?: VaryDimension[];
  imageSlots?: Record<string, ImageSlotContract>;
}

export interface ComponentContract<TSchema = unknown> {
  name: string;
  component?: CmsComponentFn<any>;
  schema: TSchema;
  renderModes: ComponentRenderModes;
  render: ComponentRenderModes;
  defaultIslandMode?: IslandMode;
  varyDimensions?: VaryDimension[];
  vary?: VaryDimension[];
  imageSlots?: Record<string, ImageSlotContract>;
}

export type InferComponentProps<TContract> = TContract extends ComponentContract<infer TSchema>
  ? InferContentProps<TSchema>
  : Record<string, unknown>;

export type { CmsComponentFn, InferContentProps };
