import React, { useMemo, useState } from 'react';
import {
  Adapt,
  Button,
  Input,
  Paragraph,
  Select,
  Separator,
  Sheet,
  Switch,
  Text,
  TextArea,
  XStack,
  YStack
} from 'tamagui';
import { getIcon } from './IconMapper.jsx';
import { ColorPickerPopup, DateTimePickerPopup } from './FieldControlPickers.jsx';
import { getTypographyRoleProps } from '../styles/index.js';
import { pickFile } from '../../platform/compat.js';

const ChevronDown = getIcon('chevron-down');
const ChevronUp = getIcon('chevron-up');
const CheckIcon = getIcon('check');

function helperTextColor(error) {
  return error ? '$danger' : '$textMuted';
}

function fieldChrome(orientation, error, border) {
  const embedded = orientation === 'embedded';
  const borderless = border === 0;
  return {
    position: embedded ? 'relative' : 'static',
    borderWidth: embedded && !borderless ? 1 : 0,
    borderColor: error ? '$danger' : '$lineSubtle',
    borderRadius: embedded ? '$radiusMd' : '$0',
    backgroundColor: embedded && !borderless ? '$bgPanel' : 'transparent',
    paddingTop: embedded && !borderless ? '$3.5' : '$0',
    paddingRight: embedded && !borderless ? '$3' : '$0',
    paddingBottom: embedded && !borderless ? '$3' : '$0',
    paddingLeft: embedded && !borderless ? '$3' : '$0',
    gap: embedded ? '$2' : '$1.5'
  };
}

function inputChrome(orientation, error, border) {
  const embedded = orientation === 'embedded';
  const borderless = border === 0;
  return {
    backgroundColor: embedded || borderless ? 'transparent' : '$bgPanel',
    borderColor: embedded || borderless ? 'transparent' : (error ? '$danger' : '$lineSubtle'),
    borderWidth: embedded || borderless ? 0 : 1,
    paddingHorizontal: embedded ? '$0' : undefined,
    paddingVertical: embedded ? '$0' : undefined,
    focusStyle: embedded
      ? { borderColor: 'transparent', outlineWidth: 0 }
      : { borderColor: error ? '$danger' : '$accent' }
  };
}

function renderHelper(error, hint) {
  if (!error && !hint) {
    return null;
  }
  return (
    <Paragraph color={helperTextColor(error)} fontSize="$3">
      {error || hint}
    </Paragraph>
  );
}

function parseAreaPlacement(value, fallback = 'inside') {
  const raw = String(value || fallback)
    .split(',')
    .map((part) => part.trim())
    .filter(Boolean);
  const hints = new Set(raw.length ? raw : [fallback]);
  return {
    mode: hints.has('outside') ? 'outside' : 'inside',
    hints,
  };
}

function renderActionNode(action, context, fallbackColor = '$textMuted') {
  if (!action) {
    return null;
  }

  if (React.isValidElement(action)) {
    return action;
  }

  if (typeof action === 'function') {
    const rendered = action(context);
    if (React.isValidElement(rendered)) {
      return rendered;
    }
    const ActionComponent = action;
    return <ActionComponent size="sm" color={fallbackColor} {...context} />;
  }

  if (typeof action === 'string') {
    const IconComponent = getIcon(action);
    return IconComponent ? <IconComponent size="sm" color={fallbackColor} /> : null;
  }

  if (action && typeof action === 'object' && action.icon) {
    const IconComponent = typeof action.icon === 'string' ? getIcon(action.icon) : action.icon;
    return IconComponent ? <IconComponent size="sm" color={action.color || fallbackColor} weight={action.weight} /> : null;
  }

  return null;
}

function chipProps(selected, disabled) {
  return selected
    ? {
        backgroundColor: '$accentBg',
        color: '$accent',
        borderColor: '$accent',
        borderWidth: 1,
        hoverStyle: { backgroundColor: '$accentBgHover' },
        pressStyle: { backgroundColor: '$accentBgHover' },
        disabled,
      }
    : {
        backgroundColor: '$bgPanel',
        color: '$textPrimary',
        borderColor: '$lineSubtle',
        borderWidth: 1,
        hoverStyle: { backgroundColor: '$bgPage', borderColor: '$lineStrong' },
        pressStyle: { backgroundColor: '$bgPage' },
        disabled,
      };
}

function DropdownControl({ value, options, onValueChange, placeholder, disabled, error, inputProps = {}, fieldProps = {} }) {
  return (
    <Select value={value ?? ''} onValueChange={onValueChange} disabled={disabled}>
      <Select.Trigger
        {...inputProps}
        {...fieldProps}
        iconAfter={ChevronDown ? <ChevronDown size="sm" color="$textSecondary" /> : undefined}
        backgroundColor={inputProps.backgroundColor ?? '$bgPanel'}
        borderColor={inputProps.borderColor ?? (error ? '$danger' : '$lineSubtle')}
        borderWidth={inputProps.borderWidth ?? 1}
        focusStyle={inputProps.focusStyle ?? { borderColor: error ? '$danger' : '$accent' }}
      >
        <Select.Value placeholder={placeholder || 'Select'} />
      </Select.Trigger>

      <Adapt when="sm" platform="touch">
        <Sheet modal dismissOnSnapToBottom snapPoints={[55]}>
          <Sheet.Frame backgroundColor="$bgPanel">
            <Sheet.ScrollView>
              <Adapt.Contents />
            </Sheet.ScrollView>
          </Sheet.Frame>
          <Sheet.Overlay backgroundColor="$scrim" />
        </Sheet>
      </Adapt>

      <Select.Content zIndex={200000}>
        <Select.ScrollUpButton alignItems="center" justifyContent="center" position="relative" width="100%" height="$3">
          <YStack zIndex={10}>
            {ChevronUp ? <ChevronUp size="sm" color="$textSecondary" /> : null}
          </YStack>
        </Select.ScrollUpButton>

        <Select.Viewport minWidth={220}>
          <Select.Group>
            {options.map((option, index) => (
              <Select.Item key={String(option.value)} index={index} value={String(option.value)}>
                <Select.ItemText>{option.label}</Select.ItemText>
                <Select.ItemIndicator marginLeft="auto">
                  {CheckIcon ? <CheckIcon size="sm" color="$accent" /> : null}
                </Select.ItemIndicator>
              </Select.Item>
            ))}
          </Select.Group>
        </Select.Viewport>

        <Select.ScrollDownButton alignItems="center" justifyContent="center" position="relative" width="100%" height="$3">
          <YStack zIndex={10}>
            {ChevronDown ? <ChevronDown size="sm" color="$textSecondary" /> : null}
          </YStack>
        </Select.ScrollDownButton>
      </Select.Content>
    </Select>
  );
}

function ColorSwatch({ value }) {
  const normalized = String(value || '').trim();
  const isHex = /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(normalized);
  return (
    <YStack
      width={28}
      height={28}
      borderRadius="$radiusSm"
      borderWidth={1}
      borderColor="$lineSubtle"
      backgroundColor={isHex ? normalized : '$bgPanelElev'}
    />
  );
}

function EmbeddedLabel({ label, required = false }) {
  if (!label) return null;
  return (
    <YStack
      position="absolute"
      top={-9}
      left="$3"
      zIndex={2}
      paddingHorizontal="$1.5"
      backgroundColor="$bgPanel"
      pointerEvents="none"
    >
      <Text {...getTypographyRoleProps('fieldLabel', { fontSize: '$2', color: '$textSecondary' })}>
        {label}{required ? ' *' : ''}
      </Text>
    </YStack>
  );
}

function resolveOptionLabel(options, value) {
  const match = (options || []).find((option) => String(option.value) === String(value ?? ''));
  return match ? match.label : String(value ?? '');
}

function StaticTextValue({ value, fieldProps = {}, multiline = false }) {
  const textValue = value == null || value === '' ? '—' : String(value);
  return (
    <Text color="$textPrimary" whiteSpace={multiline ? 'pre-wrap' : undefined} {...fieldProps}>
      {textValue}
    </Text>
  );
}

async function handleFilePick(controlId, emitValue, props = {}) {
  const selection = await pickFile({
    accept: props.accept || '*',
    readAs: props.readAs || null,
  });

  if (!selection?.file) {
    return;
  }

  emitValue(selection.file, selection);
}

export function FieldControl({
  name,
  id,
  label,
  value,
  onChange,
  onValueChange,
  placeholder = '',
  hint = '',
  helperText = '',
  error = '',
  orientation = 'vertical',
  type = 'text',
  format = '',
  options = [],
  rows = 4,
  cols = -1,
  readOnly = false,
  locked = false,
  disabled = false,
  active = true,
  visible = true,
  border,
  render = null,
  fieldProps = {},
  required = false,
  children = null,
  accept,
  readAs,
  leftAction = null,
  rightAction = null,
  leftAreaPlacement = 'inside',
  rightAreaPlacement = 'inside',
  leftActionOnPress = null,
  rightActionOnPress = null,
  leftIcon = null,
  rightIcon = null,
  leftIconPlacement = 'inside',
  rightIconPlacement = 'inside',
  leftIconOnPress = null,
  rightIconOnPress = null
}) {
  if (!visible) {
    return null;
  }

  if (type === 'select') {
    type = 'dropdown';
  }

  const controlId = id || name || label || 'field';
  const chrome = fieldChrome(orientation, error, border);
  const commonInputProps = inputChrome(orientation, error, border);
  const normalizedValue = value ?? '';
  const embedded = orientation === 'embedded';
  const borderless = border === 0;
  const staticMode = readOnly || locked || !active;
  const [showPassword, setShowPassword] = useState(false);
  const [autocompleteOpen, setAutocompleteOpen] = useState(false);
  const [colorPickerOpen, setColorPickerOpen] = useState(false);
  const [dateTimePickerOpen, setDateTimePickerOpen] = useState(false);
  const isDateLike = type === 'date' || type === 'time' || type === 'date-time';
  const effectiveLeftAction = leftAction || leftIcon;
  const effectiveRightAction = type === 'password'
    ? (rightAction || rightIcon || (showPassword ? 'visibility-off' : 'visibility'))
    : (isDateLike
      ? (rightAction || rightIcon || (type === 'time' ? 'clock' : 'calendar'))
      : (rightAction || rightIcon));
  const effectiveLeftActionOnPress = leftActionOnPress || leftIconOnPress;
  const effectiveRightActionOnPress = type === 'password'
    ? (rightActionOnPress || rightIconOnPress || (() => setShowPassword((state) => !state)))
    : (isDateLike
      ? (rightActionOnPress || rightIconOnPress || (() => setDateTimePickerOpen((open) => !open)))
      : (rightActionOnPress || rightIconOnPress));
  const normalizedLeftPlacement = parseAreaPlacement(leftAreaPlacement || leftIconPlacement, 'inside');
  const normalizedRightPlacement = parseAreaPlacement(rightAreaPlacement || rightIconPlacement, 'inside');
  const hasInsideLeftAction = Boolean(effectiveLeftAction) && normalizedLeftPlacement.mode === 'inside';
  const hasInsideRightAction = Boolean(effectiveRightAction) && normalizedRightPlacement.mode === 'inside';
  const emitValue = (nextValue, eventLike = undefined) => {
    if (typeof onChange === 'function') {
      onChange(controlId, nextValue, eventLike);
      return;
    }
    if (typeof onValueChange === 'function') {
      onValueChange(nextValue, eventLike);
    }
  };
  const decoratedInputProps = {
    ...commonInputProps,
    paddingLeft: hasInsideLeftAction ? '$8' : commonInputProps.paddingLeft,
    paddingRight: hasInsideRightAction ? '$8' : commonInputProps.paddingRight,
  };

  const renderActionArea = (action, side, placement, onPress) => {
    const actionContext = {
      id: controlId,
      name: controlId,
      side,
      placement: placement.mode,
      placementHints: placement.hints,
      value: normalizedValue,
      disabled,
      readOnly,
      locked,
      active,
      error,
      orientation,
      onPress,
      showPassword,
      setShowPassword,
    };
    const actionNode = renderActionNode(action, actionContext);
    if (!actionNode) {
      return null;
    }

    const button = typeof onPress === 'function' ? (
      <Button
        chromeless
        size="$2"
        paddingHorizontal="$1.5"
        paddingVertical="$1"
        backgroundColor="transparent"
        color="$textMuted"
        hoverStyle={{ backgroundColor: '$accentBg', color: '$textSecondary' }}
        pressStyle={{ backgroundColor: '$accentBgHover', color: '$textPrimary' }}
        disabled={disabled}
        onPress={onPress}
      >
        {actionNode}
      </Button>
    ) : actionNode;

    if (placement.mode === 'outside') {
      return button;
    }

    return (
      <YStack
        position="absolute"
        top={0}
        bottom={0}
        justifyContent="center"
        {...(side === 'left' ? { left: '$1.5' } : { right: '$1.5' })}
      >
        {button}
      </YStack>
    );
  };

  const wrapControlWithIcons = (node, multiline = false) => {
    const leftOutside = effectiveLeftAction && normalizedLeftPlacement.mode === 'outside'
      ? renderActionArea(effectiveLeftAction, 'left', normalizedLeftPlacement, effectiveLeftActionOnPress)
      : null;
    const rightOutside = effectiveRightAction && normalizedRightPlacement.mode === 'outside'
      ? renderActionArea(effectiveRightAction, 'right', normalizedRightPlacement, effectiveRightActionOnPress)
      : null;
    const leftInside = effectiveLeftAction && normalizedLeftPlacement.mode === 'inside'
      ? renderActionArea(effectiveLeftAction, 'left', normalizedLeftPlacement, effectiveLeftActionOnPress)
      : null;
    const rightInside = effectiveRightAction && normalizedRightPlacement.mode === 'inside'
      ? renderActionArea(effectiveRightAction, 'right', normalizedRightPlacement, effectiveRightActionOnPress)
      : null;

    const inner = leftInside || rightInside ? (
      <YStack position="relative" flex={1} minWidth={0}>
        {node}
        {leftInside}
        {rightInside}
      </YStack>
    ) : node;

    if (leftOutside || rightOutside) {
      return (
        <XStack gap="$2" alignItems={multiline ? 'flex-start' : 'center'}>
          {leftOutside}
          {inner}
          {rightOutside}
        </XStack>
      );
    }

    return inner;
  };

  if (type === 'divider') {
    return <Separator borderColor="$lineSubtle" />;
  }

  if (type === 'title') {
    return (
      <YStack gap="$1">
        <Text {...getTypographyRoleProps('pageTitle', { color: '$textPrimary' })}>
          {label}
        </Text>
        {hint ? (
          <Paragraph color="$textMuted">
            {hint}
          </Paragraph>
        ) : null}
      </YStack>
    );
  }

  const control = useMemo(() => {
    if (type === 'custom') {
      return children || null;
    }

    if (typeof render === 'function') {
      return render({
        id: controlId,
        name: controlId,
        value: normalizedValue,
        placeholder,
        disabled,
        readOnly,
        locked,
        active,
        error,
        orientation,
        inputProps: commonInputProps,
        onChange: emitValue,
        onValueChange: emitValue
      });
    }

    if (type === 'dropdown') {
      if (staticMode) {
        return (
          <StaticTextValue
            value={normalizedValue == null || normalizedValue === '' ? '—' : resolveOptionLabel(options, normalizedValue)}
            fieldProps={fieldProps}
          />
        );
      }
      return (
        <DropdownControl
          value={String(normalizedValue)}
          options={options}
          onValueChange={emitValue}
          placeholder={placeholder}
          disabled={disabled}
          error={error}
          inputProps={decoratedInputProps}
          fieldProps={fieldProps}
        />
      );
    }

    if (type === 'autocomplete') {
      if (staticMode) {
        return <StaticTextValue value={normalizedValue} fieldProps={fieldProps} />;
      }
      const filteredOptions = String(normalizedValue || '').trim()
        ? options.filter((option) => option.label.toLowerCase().includes(String(normalizedValue).toLowerCase()))
        : options;
      return (
        <YStack position="relative" minWidth={0}>
          {wrapControlWithIcons(
            <Input
              {...decoratedInputProps}
              {...fieldProps}
              placeholder={placeholder}
              value={String(normalizedValue)}
              readOnly={readOnly}
              disabled={disabled}
              required={required}
              onFocus={() => setAutocompleteOpen(true)}
              onBlur={() => {
                setTimeout(() => {
                  setAutocompleteOpen(false);
                }, 120);
              }}
              onChangeText={emitValue}
            />
          )}
          {autocompleteOpen && filteredOptions.length ? (
            <YStack
              position="absolute"
              top="100%"
              left={0}
              right={0}
              zIndex={30}
              marginTop="$1.5"
              padding="$1.5"
              gap="$1"
              backgroundColor="$bgPanel"
              borderWidth={1}
              borderColor="$lineSubtle"
                borderRadius="$radiusMd"
              elevation="$2"
              shadowColor="$shadowColor"
            >
              {filteredOptions.slice(0, 8).map((option) => (
                <Button
                  key={String(option.value)}
                  size="$2"
                  chromeless
                  justifyContent="flex-start"
                  onPress={() => {
                    emitValue(String(option.value));
                    setAutocompleteOpen(false);
                  }}
                >
                  {option.label}
                </Button>
              ))}
            </YStack>
          ) : null}
        </YStack>
      );
    }

    if (type === 'number') {
      if (staticMode) {
        return <StaticTextValue value={normalizedValue} fieldProps={fieldProps} />;
      }
      return (
        <Input
          {...decoratedInputProps}
          {...fieldProps}
            placeholder={placeholder}
            value={String(normalizedValue)}
            readOnly={readOnly}
            disabled={disabled}
            keyboardType="number-pad"
            required={required}
          onChangeText={(nextValue) => emitValue(nextValue === '' ? '' : Number(nextValue))}
        />
      );
      }

    if (type === 'email') {
      if (staticMode) {
        return <StaticTextValue value={normalizedValue} fieldProps={fieldProps} />;
      }
      return (
        <Input
          {...decoratedInputProps}
          {...fieldProps}
          placeholder={placeholder}
            value={String(normalizedValue)}
            readOnly={readOnly}
            disabled={disabled}
            autoCapitalize="none"
            required={required}
            onChangeText={emitValue}
          />
        );
      }

    if (type === 'password') {
      if (staticMode) {
        return <StaticTextValue value={showPassword ? normalizedValue : '********'} fieldProps={fieldProps} />;
      }
      return wrapControlWithIcons(
        <Input
          {...decoratedInputProps}
          {...fieldProps}
          placeholder={placeholder}
          value={String(normalizedValue)}
          readOnly={readOnly}
          disabled={disabled}
          autoCapitalize="none"
          required={required}
          secureTextEntry={!showPassword}
          type={showPassword ? 'text' : 'password'}
          onChangeText={emitValue}
        />
      );
    }

    if (type === 'date' || type === 'time' || type === 'date-time') {
      if (staticMode) {
        return <StaticTextValue value={normalizedValue} fieldProps={fieldProps} />;
      }
      const defaultPlaceholder = type === 'time'
        ? 'HH:MM'
        : (type === 'date-time' ? 'YYYY-MM-DDTHH:MM' : 'YYYY-MM-DD');
      return (
        <YStack position="relative" minWidth={0}>
          {wrapControlWithIcons(
            <Input
              {...decoratedInputProps}
              {...fieldProps}
              placeholder={placeholder || defaultPlaceholder}
              value={String(normalizedValue)}
              readOnly={readOnly}
              disabled={disabled}
              required={required}
              autoCapitalize="none"
              onChangeText={emitValue}
            />
          )}
          {dateTimePickerOpen ? (
            <DateTimePickerPopup
              type={type}
              value={String(normalizedValue)}
              onChange={(nextValue) => emitValue(nextValue)}
              onClose={() => setDateTimePickerOpen(false)}
            />
          ) : null}
        </YStack>
      );
    }

    if (type === 'color') {
      if (staticMode) {
        return (
          <YStack position="relative" flex={1} minWidth={0}>
            <StaticTextValue value={normalizedValue} fieldProps={{ ...fieldProps, paddingRight: '$9' }} />
            <YStack
              position="absolute"
              top={0}
              bottom={0}
              right="$1.5"
              justifyContent="center"
              pointerEvents="none"
            >
              <ColorSwatch value={normalizedValue} />
            </YStack>
          </YStack>
        );
      }
      return (
        <YStack position="relative" flex={1} minWidth={0}>
          <Input
            flex={1}
            {...decoratedInputProps}
            {...fieldProps}
            paddingRight="$9"
            placeholder={placeholder || '#RRGGBB'}
            value={String(normalizedValue)}
            readOnly={readOnly}
            disabled={disabled}
            autoCapitalize="none"
            required={required}
            onChangeText={emitValue}
          />
          <Button
            chromeless
            position="absolute"
            top={0}
            bottom={0}
            right="$1"
            justifyContent="center"
            paddingHorizontal="$1"
            backgroundColor="transparent"
            hoverStyle={{ backgroundColor: '$accentBg' }}
            pressStyle={{ backgroundColor: '$accentBgHover' }}
            onPress={() => setColorPickerOpen((open) => !open)}
          >
            <ColorSwatch value={normalizedValue} />
          </Button>
          {colorPickerOpen ? (
            <ColorPickerPopup
              value={String(normalizedValue || '#000000')}
              onChange={(nextValue) => emitValue(String(nextValue).toUpperCase())}
              onClose={() => setColorPickerOpen(false)}
            />
          ) : null}
        </YStack>
      );
    }

    if (type === 'checkbox') {
      return (
        <XStack alignItems="center" gap="$3">
          <Switch
            id={controlId}
            size="$3"
            checked={Boolean(normalizedValue)}
            disabled={disabled || staticMode}
            onCheckedChange={(next) => emitValue(next)}
            backgroundColor={normalizedValue ? '$accent' : '$lineStrong'}
            borderColor={error ? '$danger' : 'transparent'}
            borderWidth={error ? 1 : 0}
          >
            <Switch.Thumb animation="quick" backgroundColor="$bgPanel" />
          </Switch>
          <Text color="$textSecondary" fontSize="$3">
            {normalizedValue ? 'Enabled' : 'Disabled'}
          </Text>
        </XStack>
      );
    }

    if (type === 'radio') {
      const selectedValue = String(normalizedValue ?? '');
      return (
        <XStack gap="$2" flexWrap="wrap">
          {options.map((option) => {
            const selected = selectedValue === String(option.value);
            return (
              <Button
                key={String(option.value)}
                size="$3"
                {...chipProps(selected, disabled || staticMode)}
                onPress={() => emitValue(option.value)}
              >
                {option.label}
              </Button>
            );
          })}
        </XStack>
      );
    }

    if (type === 'multiselect') {
      const selectedValues = Array.isArray(normalizedValue) ? normalizedValue.map(String) : [];
      return (
        <XStack gap="$2" flexWrap="wrap">
          {options.map((option) => {
            const selected = selectedValues.includes(String(option.value));
            return (
              <Button
                key={String(option.value)}
                size="$3"
                {...chipProps(selected, disabled || staticMode)}
                onPress={() => {
                  const nextValues = selected
                    ? selectedValues.filter((item) => item !== String(option.value))
                    : [...selectedValues, String(option.value)];
                  emitValue(nextValues);
                }}
              >
                {option.label}
              </Button>
            );
          })}
        </XStack>
      );
    }

    if (type === 'file') {
      return (
        <XStack alignItems="center" gap="$3" flexWrap="wrap">
          <Button
            size="$3"
            chromeless
            backgroundColor="$bgPanel"
            borderColor="$lineSubtle"
            borderWidth={1}
            disabled={disabled || staticMode}
            onPress={() => handleFilePick(controlId, emitValue, { accept, readAs })}
          >
            {normalizedValue?.name ? 'Replace File' : 'Choose File'}
          </Button>
          <Text color="$textMuted">
            {normalizedValue?.name || 'No file selected'}
          </Text>
        </XStack>
      );
    }

    if (type === 'textarea') {
      if (staticMode) {
        return <StaticTextValue value={normalizedValue} fieldProps={fieldProps} multiline />;
      }
      return (
        <TextArea
          {...decoratedInputProps}
          {...fieldProps}
          placeholder={placeholder}
          value={String(normalizedValue)}
          readOnly={readOnly}
          disabled={disabled}
          minHeight={rows > 0 ? Math.max(88, rows * 24) : 120}
          required={required}
          onChangeText={emitValue}
        />
      );
    }

    if (staticMode) {
      return wrapControlWithIcons(<StaticTextValue value={normalizedValue} fieldProps={fieldProps} />);
    }

    return wrapControlWithIcons(
      <Input
        {...decoratedInputProps}
        {...fieldProps}
        placeholder={placeholder}
        value={String(normalizedValue)}
        readOnly={readOnly}
        disabled={disabled}
        required={required}
        onChangeText={emitValue}
      />
    );
  }, [
    accept,
    active,
    children,
    cols,
    controlId,
    decoratedInputProps,
    disabled,
    emitValue,
    effectiveLeftAction,
    effectiveLeftActionOnPress,
    effectiveRightAction,
    effectiveRightActionOnPress,
    error,
    fieldProps,
    format,
    locked,
    normalizedValue,
    normalizedLeftPlacement,
    normalizedRightPlacement,
    options,
    orientation,
    placeholder,
    readAs,
    readOnly,
    required,
    render,
    rows,
    autocompleteOpen,
    colorPickerOpen,
    dateTimePickerOpen,
    showPassword,
    type
  ]);

  if (embedded) {
    return (
      <YStack gap="$1.5" flex={1} minWidth={0} marginTop="$2">
        <YStack {...chrome} minWidth={0}>
          {borderless ? (
            label ? (
              <Text {...getTypographyRoleProps('fieldLabel', { fontSize: '$2', color: '$textSecondary' })}>
                {label}
              </Text>
            ) : null
          ) : (
            <EmbeddedLabel label={label} required={required} />
          )}
          {control}
        </YStack>
        {renderHelper(error, error ? '' : (hint || helperText))}
      </YStack>
    );
  }

  if (orientation === 'horizontal') {
    return (
      <YStack gap="$1.5" width="100%">
        <XStack gap="$4" alignItems="flex-start" width="100%">
          <Text {...getTypographyRoleProps('fieldLabel')} width={180} paddingTop="$2">
            {label}{required ? ' *' : ''}
          </Text>
          <YStack flex={1} minWidth={0} gap="$1.5">
            {control}
          </YStack>
        </XStack>
        {renderHelper(error, error ? '' : (hint || helperText))}
      </YStack>
    );
  }

  return (
    <YStack gap="$1.5" width="100%">
      {label ? (
        <Text {...getTypographyRoleProps('fieldLabel')}>
          {label}{required ? ' *' : ''}
        </Text>
      ) : null}
      {control}
      {renderHelper(error, error ? '' : (hint || helperText))}
    </YStack>
  );
}

export default FieldControl;
