import React, { useMemo } from 'react';
import { Button, XStack, YStack } from 'tamagui';
import { SidePanelShell } from './SidePanelShell.jsx';
import { FormField } from './FormField.jsx';
import { getIcon } from './IconMapper.jsx';

function defaultExpressionEvaluator(template, form) {
  return template.replace(/\{\{(\w+)\}\}/g, (_match, fieldName) => form[fieldName] || '');
}

function renderAction(action, index, fallbackHandler) {
  const IconComponent = action?.icon ? getIcon(action.icon) : null;
  return {
    id: action?.id || action?.label || `action-${index}`,
    label: action?.label,
    icon: action?.icon,
    disabled: action?.disabled,
    theme: action?.theme,
    chromeless: action?.chromeless,
    onPress: action?.onPress || fallbackHandler,
    iconComponent: IconComponent
  };
}

export function FormView({
  open = false,
  onClose = null,
  title = 'Edit Record',
  toolbar = [],
  fields = [],
  values = {},
  onChange = () => {},
  onSubmit = () => {},
  onReset = () => {},
  buttons = [],
  loading = false,
  errors = {},
  children = null,
  hideButtons = false,
  width = 460
}) {
  const processedFields = useMemo(() => {
    return fields.map((field) => {
      if (!field.expression) {
        return field;
      }

      const expressionFunction = typeof field.expression === 'string'
        ? (form) => defaultExpressionEvaluator(field.expression, form)
        : field.expression;

      return {
        ...field,
        expressionFunction,
        readOnly: true
      };
    });
  }, [fields]);

  const computedValues = useMemo(() => {
    return processedFields.reduce((accumulator, field) => {
      if (field.expressionFunction) {
        accumulator[field.id] = field.expressionFunction(values);
      }
      return accumulator;
    }, {});
  }, [processedFields, values]);

  const mergedValues = {
    ...values,
    ...computedValues
  };

  const footerActions = useMemo(() => {
    if (hideButtons) {
      return [];
    }

    const sourceButtons = buttons.length > 0
      ? buttons
      : [
          { label: 'Reset', chromeless: true, onPress: onReset },
          { label: 'Save', theme: 'active', onPress: onSubmit }
        ];

    return sourceButtons.map((button, index) => renderAction(button, index, index === 0 ? onReset : onSubmit));
  }, [buttons, hideButtons, onReset, onSubmit]);

  const renderField = (field, index) => (
    <FormField
      key={field.id || `${field.type || 'field'}-${index}`}
      {...field}
      value={mergedValues[field.id]}
      onChange={onChange}
      error={errors[field.id]}
      disabled={field.disabled || loading}
    />
  );

  const renderChildren = () => {
    if (!children) {
      return null;
    }

    return React.Children.map(children, (child) => {
      if (React.isValidElement(child) && child.type === FormField) {
        const fieldId = child.props.id;
        return React.cloneElement(child, {
          value: mergedValues[fieldId],
          onChange,
          error: errors[fieldId],
          disabled: child.props.disabled || loading
        });
      }
      return child;
    });
  };

  return (
    <SidePanelShell
      open={open}
      onClose={onClose}
      title={title}
      toolbar={toolbar}
      footerActions={footerActions}
      width={width}
    >
      <YStack gap="$4">
        {processedFields.map(renderField)}
        {children ? (
          <YStack gap="$4">
            {renderChildren()}
          </YStack>
        ) : null}
        {loading ? (
          <XStack justifyContent="flex-end">
            <Button disabled>Saving...</Button>
          </XStack>
        ) : null}
      </YStack>
    </SidePanelShell>
  );
}

export default FormView;
