/**
 * ConfigurationForm - Dynamic form component for workflow element configuration
 * 
 * Renders form fields based on a schema provided by the backend.
 * Supports various field types including text, textarea, select, checkboxes,
 * and rich text fields with token support.
 */

import React, { useState, useCallback, useMemo } from 'react';
import { useStore } from '../store/store';
import { sanitizeHtml } from '../utils/sanitize';
import { t } from '../utils/translation';
import ContentEditableField from './ContentEditableField';

interface FormField {
  key: string;
  type: string;
  title?: string;
  description?: string;
  placeholder?: string;
  required?: boolean;
  default_value?: any;
  min?: number;
  max?: number;
  step?: number;
  options?: Record<string, string>;
  markup?: string;
  token_support?: boolean;
}

interface ConfigurationFormProps {
  form?: FormField[] | null;
  configuration?: Record<string, any> | null;
  onChange?: (values: Record<string, any>) => void;
  disabled?: boolean;
}

/**
 * Render a single form field based on its type
 */
const FormFieldRenderer: React.FC<{
  field: FormField;
  value: any;
  onChange: (value: any) => void;
  disabled: boolean;
  acceptsTokens: boolean;
  isTokenDragging: boolean;
}> = ({ field, value, onChange, disabled, acceptsTokens, isTokenDragging }) => {
  const currentValue = value ?? field.default_value ?? '';

  switch (field.type) {
    case 'textfield':
    case 'email':
    case 'url':
      return (
        <ContentEditableField
          value={currentValue}
          onChange={onChange}
          className="form-control"
          placeholder={field.placeholder || t('Enter @field...', { '@field': field.title || field.type })}
          disabled={disabled}
          multiline={false}
          acceptsTokens={acceptsTokens}
          isTokenDragging={isTokenDragging}
        />
      );

    case 'textarea':
      return (
        <ContentEditableField
          value={currentValue}
          onChange={onChange}
          className="form-control"
          placeholder={field.placeholder || t('Enter @field...', { '@field': field.title || t('text') })}
          disabled={disabled}
          multiline={true}
          acceptsTokens={acceptsTokens}
          isTokenDragging={isTokenDragging}
        />
      );

    case 'number':
      return (
        <input
          id={`config-field-${field.key}`}
          type="number"
          value={currentValue}
          onChange={(e) => onChange(e.target.value)}
          className="form-control"
          min={field.min}
          max={field.max}
          step={field.step}
          required={field.required}
          disabled={disabled}
        />
      );

    case 'checkbox':
      return (
        <label className="checkbox-wrapper">
          <input
            type="checkbox"
            checked={!!currentValue}
            onChange={(e) => onChange(e.target.checked)}
            required={field.required}
            disabled={disabled}
          />
          <span className="checkbox-label">{field.title}</span>
        </label>
      );

    case 'select':
      return (
        <select
          id={`config-field-${field.key}`}
          value={currentValue}
          onChange={(e) => onChange(e.target.value)}
          className="form-control"
          required={field.required}
          disabled={disabled}
        >
          <option value="">{t('- Select -')}</option>
          {field.options && Object.entries(field.options).map(([optionKey, optionLabel]) => (
            <option key={optionKey} value={optionKey}>
              {optionLabel}
            </option>
          ))}
        </select>
      );

    case 'radios':
      return (
        <div className="radio-group">
          {field.options && Object.entries(field.options).map(([optionKey, optionLabel]) => (
            <label key={optionKey} className="radio-wrapper">
              <input
                type="radio"
                name={field.key}
                value={optionKey}
                checked={currentValue === optionKey}
                onChange={(e) => onChange(e.target.value)}
                required={field.required}
                disabled={disabled}
              />
              <span className="radio-label">{optionLabel}</span>
            </label>
          ))}
        </div>
      );

    case 'checkboxes': {
      const checkboxValues = Array.isArray(currentValue) ? currentValue : [];
      return (
        <div className="checkbox-group">
          {field.options && Object.entries(field.options).map(([optionKey, optionLabel]) => (
            <label key={optionKey} className="checkbox-wrapper">
              <input
                type="checkbox"
                value={optionKey}
                checked={checkboxValues.includes(optionKey)}
                onChange={(e) => {
                  const newValues = e.target.checked
                    ? [...checkboxValues, optionKey]
                    : checkboxValues.filter((v: string) => v !== optionKey);
                  onChange(newValues);
                }}
                disabled={disabled}
              />
              <span className="checkbox-label">{optionLabel}</span>
            </label>
          ))}
        </div>
      );
    }

    case 'markup':
      return (
        <div className="markup-content" dangerouslySetInnerHTML={{ __html: sanitizeHtml(field.markup) }} />
      );

    default:
      return (
        <input
          id={`config-field-${field.key}`}
          type="text"
          value={currentValue}
          onChange={(e) => onChange(e.target.value)}
          className="form-control"
          required={field.required}
          disabled={disabled}
        />
      );
  }
};

const ConfigurationForm: React.FC<ConfigurationFormProps> = ({
  form,
  configuration,
  onChange,
  disabled = false
}) => {
  // Initialize state with configuration
  const [values, setValues] = useState<Record<string, any>>(configuration || {});
  const isTokenDragging = useStore(s => s.isTokenDragging);

  const handleFieldChange = useCallback((fieldKey: string, value: any) => {
    const newValues = { ...values, [fieldKey]: value };
    setValues(newValues);
    if (onChange) {
      onChange(newValues);
    }
  }, [values, onChange]);

  // Determine whether all fields accept tokens (when replace_tokens checkbox is checked)
  const replaceTokensEnabled = useMemo(() => {
    if (!form || !Array.isArray(form)) return false;
    const replaceTokensField = form.find(
      (f) => f.key === 'replace_tokens' && f.type === 'checkbox'
    );
    if (!replaceTokensField) return false;
    return !!values.replace_tokens;
  }, [form, values.replace_tokens]);

  if (!form || !Array.isArray(form)) {
    return <div className="no-configuration">{t('No configuration available')}</div>;
  }

  return (
    <div className="configuration-form">
      {form.map((field) => {
        // A field accepts tokens if replace_tokens is checked globally,
        // or if the field has token_support set to true
        const fieldAcceptsTokens = replaceTokensEnabled || !!field.token_support;

        return (
          <div
            key={field.key}
            className={`form-field ${isTokenDragging && !fieldAcceptsTokens ? 'token-drop-disabled' : ''} ${isTokenDragging && fieldAcceptsTokens ? 'token-drop-enabled' : ''}`}
          >
            {field.type !== 'checkbox' && field.type !== 'markup' && field.title && (
              <label className="field-label" htmlFor={`config-field-${field.key}`}>
                {field.title}
                {field.required && <span className="required">*</span>}
              </label>
            )}

            {field.type === 'markup' && field.title && (
              <h4 className="markup-title">{field.title}</h4>
            )}

            <div className="field-input">
              <FormFieldRenderer
                field={field}
                value={values[field.key]}
                onChange={(value) => handleFieldChange(field.key, value)}
                disabled={disabled}
                acceptsTokens={fieldAcceptsTokens}
                isTokenDragging={isTokenDragging}
              />
            </div>

            {field.description && (
              <div className="field-description" dangerouslySetInnerHTML={{ __html: sanitizeHtml(field.description) }} />
            )}
          </div>
        );
      })}
    </div>
  );
};

export default ConfigurationForm;
