import React, { type ComponentType, type ReactNode } from 'react';
import {
  Text,
  TextSmall,
  Image,
  ImageSmall,
  SquareRatioChecked,
  SquareRatioCheckedSmall,
  Number,
  NumberSmall,
  Date,
  DateSmall,
  DateAndTime,
  DateAndTimeSmall,
  Time,
  TimeSmall,
  Article,
  ArticleSmall,
  RichText,
  RichTextSmall,
  Reference,
  ReferenceSmall,
  Multireference,
  MultireferenceSmall,
  Link,
  LinkSmall,
  Document,
  DocumentSmall,
  DocDuplicate,
  Music,
  MusicSmall,
  Location,
  LocationSmall,
  Tag,
  TagSmall,
  CodeObject,
  CodeObjectSmall,
  ProGalleries,
  ProGalleriesSmall,
  Email,
  EmailSmall,
  Database,
  DatabaseSmall,
} from '@wix/wix-ui-icons-common';
import type { PatternsFieldType } from '@wix/bex-core';

/**
 * Canonical field type keys (UPPER_SNAKE_CASE).
 * The map is keyed by these values; incoming camelCase strings
 * are normalised before lookup.
 */
export type FieldType =
  | 'SHORT_TEXT'
  | 'LONG_TEXT'
  | 'NUMBER'
  | 'BOOLEAN'
  | 'DATE'
  | 'DATE_TIME'
  | 'DATETIME'
  | 'TIME'
  | 'URL'
  | 'EMAIL'
  | 'IMAGE'
  | 'MEDIA_GALLERY'
  | 'AUDIO'
  | 'DOCUMENT'
  | 'MULTI_DOCUMENT'
  | 'RICH_TEXT'
  | 'RICH_CONTENT'
  | 'REFERENCE'
  | 'MULTI_REFERENCE'
  | 'OBJECT'
  | 'ARRAY'
  | 'ADDRESS'
  | 'COLOR'
  | 'INTEGER'
  | 'DECIMAL'
  | 'CHECKBOX'
  | 'DROPDOWN'
  | 'FILES'
  | 'MULTI_SELECT';

/**
 * Converts any casing (camelCase, snake_case, etc.) to a canonical FieldType.
 * e.g. "shortText" → "SHORT_TEXT", "dateTime" → "DATE_TIME".
 * Already UPPER_SNAKE_CASE strings pass through unchanged.
 */
export function toFieldType(value: string): FieldType {
  return value.replace(/([a-z])([A-Z])/g, '$1_$2').toUpperCase() as FieldType;
}

interface FieldPrefixIconEntry {
  small: ComponentType;
  medium: ComponentType;
}

/**
 * Maps canonical UPPER_SNAKE_CASE field types to icon components (small + medium).
 */
const FIELD_TYPE_ICON_MAP: Partial<
  Record<FieldType | PatternsFieldType, FieldPrefixIconEntry>
> = {
  SHORT_TEXT: { small: TextSmall, medium: Text },
  LONG_TEXT: { small: TextSmall, medium: Text },
  NUMBER: { small: NumberSmall, medium: Number },
  BOOLEAN: { small: SquareRatioCheckedSmall, medium: SquareRatioChecked },
  DATE: { small: DateSmall, medium: Date },
  DATE_TIME: { small: DateAndTimeSmall, medium: DateAndTime },
  DATETIME: { small: DateAndTimeSmall, medium: DateAndTime },
  TIME: { small: TimeSmall, medium: Time },
  URL: { small: LinkSmall, medium: Link },
  EMAIL: { small: EmailSmall, medium: Email },
  IMAGE: { small: ImageSmall, medium: Image },
  MEDIA_GALLERY: { small: ProGalleriesSmall, medium: ProGalleries },
  AUDIO: { small: MusicSmall, medium: Music },
  DOCUMENT: { small: DocumentSmall, medium: Document },
  MULTI_DOCUMENT: { small: DocumentSmall, medium: DocDuplicate },
  RICH_TEXT: { small: RichTextSmall, medium: RichText },
  RICH_CONTENT: { small: ArticleSmall, medium: Article },
  REFERENCE: { small: ReferenceSmall, medium: Reference },
  MULTI_REFERENCE: { small: MultireferenceSmall, medium: Multireference },
  OBJECT: { small: CodeObjectSmall, medium: CodeObject },
  ARRAY: { small: TagSmall, medium: Tag },
  ADDRESS: { small: LocationSmall, medium: Location },
  INTEGER: { small: NumberSmall, medium: Number },
  DECIMAL: { small: NumberSmall, medium: Number },
  CHECKBOX: { small: SquareRatioCheckedSmall, medium: SquareRatioChecked },
  FILES: { small: DocumentSmall, medium: Document },
  MULTI_SELECT: { small: TagSmall, medium: Tag },
};

/**
 * Returns an icon ReactNode for the given field type string and size.
 * Accepts both UPPER_SNAKE_CASE and camelCase input.
 * If the field type is not mapped (or undefined), returns an info fallback icon.
 *
 * @param fieldType - The field type string
 * @param size - 'small' (default, for column headers / customize panel) or 'medium' (for filters)
 */
const ICON_STYLE: React.CSSProperties = {
  display: 'flex',
  alignItems: 'center',
};

export function getFieldTypeIcon({
  fieldType,
  size = 'small',
}: {
  fieldType?: FieldType | PatternsFieldType;
  size?: 'small' | 'medium';
}): ReactNode {
  const Fallback = size === 'medium' ? Database : DatabaseSmall;

  if (!fieldType) {
    return (
      <span style={ICON_STYLE}>
        <Fallback />
      </span>
    );
  }

  const entry = FIELD_TYPE_ICON_MAP[fieldType];

  if (!entry) {
    return (
      <span style={ICON_STYLE}>
        <Fallback />
      </span>
    );
  }

  const Icon = size === 'medium' ? entry.medium : entry.small;
  return (
    <span style={ICON_STYLE}>
      <Icon />
    </span>
  );
}
