import React, { Suspense } from 'react';
import { Box, Text } from '@wix/design-system';
import type { Field, PatternsFieldType } from '@wix/bex-core';
import type { Control } from '@wix/bex-core/form';
import { EntityPageReferenceField } from './EntityPageReferenceField';
import {
  FormShortText,
  FormLongText,
  FormNumber,
  FormCheckbox,
  FormDateInput,
  FormDateTime,
  FormTime,
  FormUrl,
  FormEmail,
  FormColor,
  FormImageInput,
  FormVideo,
} from '@wix/patterns-fields';

// Heavy renderers pull large editors (Ricos, draft-js) and media SDKs
// (@wix/media). Loading them lazily keeps that weight out of the @wix/patterns
// main bundle — it moves into an async chunk fetched only when an entity page
// first renders a field of that type. @wix/patterns-fields is side-effect-free,
// so a dynamic import of one heavy export splits into its own chunk even though
// the light renderers above are imported statically from the same package.
// FormDocument, FormMediaGallery, and FormRichContent are not on the package
// main entry — they ship from their own subpaths. Mirrors the FieldCell.tsx
// pattern.
function lazyField<P extends object>(
  load: () => Promise<{ default: React.ComponentType<P> }>,
) {
  const Lazy = React.lazy(load);
  return function LazyField(props: P) {
    return (
      <Suspense fallback={null}>
        <Lazy {...props} />
      </Suspense>
    );
  };
}

const FormAudio = lazyField(async () => ({
  default: (await import('@wix/patterns-fields')).FormAudio,
}));
const FormRichText = lazyField(async () => ({
  default: (await import('@wix/patterns-fields')).FormRichText,
}));
const FormMultiDocument = lazyField(async () => ({
  default: (await import('@wix/patterns-fields')).FormMultiDocument,
}));
const FormDocument = lazyField(async () => ({
  default: (await import('@wix/patterns-fields/form-document-field'))
    .FormDocument,
}));
const FormMediaGallery = lazyField(async () => ({
  default: (await import('@wix/patterns-fields/form-media-gallery-field'))
    .FormMediaGallery,
}));
const FormRichContent = lazyField(async () => ({
  default: (await import('@wix/patterns-fields/form-rich-content-input'))
    .FormRichContent,
}));

// Reference / MultiReference have no form renderer in @wix/patterns-fields yet,
// so those types are still skipped (see remaining-issues.md #2).
const FIELD_INPUTS: Partial<
  Record<PatternsFieldType, React.ComponentType<any>>
> = {
  SHORT_TEXT: FormShortText,
  UNKNOWN: FormShortText,
  LONG_TEXT: FormLongText,
  NUMBER: FormNumber,
  BOOLEAN: FormCheckbox,
  DATE: FormDateInput,
  DATETIME: FormDateTime,
  TIME: FormTime,
  URL: FormUrl,
  EMAIL: FormEmail,
  COLOR: FormColor,
  IMAGE: FormImageInput,
  VIDEO: FormVideo,
  AUDIO: FormAudio,
  MEDIA_GALLERY: FormMediaGallery,
  RICH_TEXT: FormRichText,
  RICH_CONTENT: FormRichContent,
  DOCUMENT: FormDocument,
  MULTI_DOCUMENT: FormMultiDocument,
};

export interface EntityPageFieldProps {
  field: Field;
  formControl: Control<any>;
  /** The entity, used by each renderer to seed its form default value. */
  data: Record<string, unknown>;
}

// Each renderer owns its own react-hook-form wiring (useController keyed on
// field.id), so this only needs to pick the renderer and pass the field.
export function EntityPageField({
  field,
  formControl,
  data,
}: EntityPageFieldProps) {
  // Reference fields need referenced-collection data, so they go through a
  // wrapper (resolves the referenced source, fetches items) rather than the
  // uniform dispatcher below.
  const isReference =
    field.type === 'REFERENCE' || field.type === 'MULTI_REFERENCE';
  const FieldInput = FIELD_INPUTS[field.type];


  if (!isReference && !FieldInput) {
    return null;
  }

  const ScalarInput = FieldInput as React.ComponentType<any>;
  const inner = isReference ? (
    <EntityPageReferenceField
      field={field}
      formControl={formControl}
      data={data}
    />
  ) : (
    <ScalarInput
      field={field}
      formControl={formControl}
      data={data}
      dataHook={`entity-page-field-${field.id}`}
    />
  );

  return (
    <Box direction="vertical" gap="SP1" width="100%">
      {inner}
      {field.helpText && (
        <Text
          size="small"
          secondary
          dataHook={`entity-page-field-${field.id}-help-text`}
        >
          {field.helpText}
        </Text>
      )}
    </Box>
  );
}
