/**
 * DynamicField Component
 * 
 * Renders form fields dynamically based on Frappe's field configuration.
 * Supports conditional visibility, mandatory, read-only states, and various field types.
 */

import React, { useMemo } from 'react';
import { type FieldConfig, evaluateFieldState, parseSelectOptions, getInputType } from '../utils/frappeExpressionEvaluator';
import LinkField from './LinkField';

interface DynamicFieldProps {
  fieldConfig: FieldConfig;
  value: any;
  onChange: (fieldname: string, value: any) => void;
  doc: Record<string, any>;
  disabled?: boolean;
  compact?: boolean;
  className?: string;
  error?: string;
}

const DynamicField: React.FC<DynamicFieldProps> = ({
  fieldConfig,
  value,
  onChange,
  doc,
  disabled = false,
  compact = false,
  className = '',
  error
}) => {
  // Evaluate field state based on current document
  const fieldState = useMemo(() => {
    return evaluateFieldState(fieldConfig, doc);
  }, [fieldConfig, doc]);

  // Don't render if field is not visible
  if (!fieldState.isVisible) {
    return null;
  }

  // Skip layout fields (Section Break, Column Break, Tab Break)
  if (['Section Break', 'Column Break', 'Tab Break', 'HTML'].includes(fieldConfig.fieldtype)) {
    return null;
  }

  const isDisabled = disabled || fieldState.isReadOnly;
  const isRequired = fieldState.isMandatory;
  const inputType = getInputType(fieldConfig.fieldtype);
  
  const labelClasses = compact 
    ? 'block text-[10px] font-medium text-gray-700 dark:text-gray-300 mb-0.5'
    : 'block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1';
  
  const inputClasses = compact
    ? `w-full px-2 py-1 text-xs border rounded focus:outline-none focus:ring-1 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white ${
        isDisabled ? 'bg-gray-100 dark:bg-gray-800 cursor-not-allowed' : ''
      } ${error ? 'border-red-500' : 'border-gray-300 dark:border-gray-600'}`
    : `w-full px-3 py-2 text-sm border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-white ${
        isDisabled ? 'bg-gray-100 dark:bg-gray-800 cursor-not-allowed' : ''
      } ${error ? 'border-red-500' : 'border-gray-300 dark:border-gray-600'}`;

  const handleChange = (newValue: any) => {
    onChange(fieldConfig.fieldname, newValue);
  };

  // Render based on field type
  const renderField = () => {
    switch (fieldConfig.fieldtype) {
      case 'Link':
        return (
          <LinkField
            label={fieldConfig.label || fieldConfig.fieldname}
            doctype={fieldConfig.options || ''}
            value={value || ''}
            onChange={handleChange}
            disabled={isDisabled}
            compact={compact}
            placeholder={`Select ${fieldConfig.label || fieldConfig.fieldname}`}
          />
        );

      case 'Select':
        const options = parseSelectOptions(fieldConfig.options);
        return (
          <div className={className}>
            <label className={labelClasses}>
              {fieldConfig.label || fieldConfig.fieldname}
              {isRequired && <span className="text-red-500 ml-1">*</span>}
            </label>
            <select
              value={value || ''}
              onChange={(e) => handleChange(e.target.value)}
              disabled={isDisabled}
              className={inputClasses}
            >
              <option value="">Select...</option>
              {options.map((opt) => (
                <option key={opt} value={opt}>{opt}</option>
              ))}
            </select>
            {error && <p className="text-red-500 text-xs mt-1">{error}</p>}
            {fieldConfig.description && !error && (
              <p className="text-gray-500 dark:text-gray-400 text-xs mt-1">{fieldConfig.description}</p>
            )}
          </div>
        );

      case 'Check':
        return (
          <div className={`flex items-center gap-2 ${className}`}>
            <input
              type="checkbox"
              checked={value === 1 || value === true}
              onChange={(e) => handleChange(e.target.checked ? 1 : 0)}
              disabled={isDisabled}
              className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
            />
            <label className="text-sm text-gray-700 dark:text-gray-300">
              {fieldConfig.label || fieldConfig.fieldname}
              {isRequired && <span className="text-red-500 ml-1">*</span>}
            </label>
          </div>
        );

      case 'Date':
        return (
          <div className={className}>
            <label className={labelClasses}>
              {fieldConfig.label || fieldConfig.fieldname}
              {isRequired && <span className="text-red-500 ml-1">*</span>}
            </label>
            <input
              type="date"
              value={value || ''}
              onChange={(e) => handleChange(e.target.value)}
              disabled={isDisabled}
              className={inputClasses}
            />
            {error && <p className="text-red-500 text-xs mt-1">{error}</p>}
          </div>
        );

      case 'Datetime':
        return (
          <div className={className}>
            <label className={labelClasses}>
              {fieldConfig.label || fieldConfig.fieldname}
              {isRequired && <span className="text-red-500 ml-1">*</span>}
            </label>
            <input
              type="datetime-local"
              value={value ? value.replace(' ', 'T').substring(0, 16) : ''}
              onChange={(e) => handleChange(e.target.value.replace('T', ' '))}
              disabled={isDisabled}
              className={inputClasses}
            />
            {error && <p className="text-red-500 text-xs mt-1">{error}</p>}
          </div>
        );

      case 'Int':
        return (
          <div className={className}>
            <label className={labelClasses}>
              {fieldConfig.label || fieldConfig.fieldname}
              {isRequired && <span className="text-red-500 ml-1">*</span>}
            </label>
            <input
              type="number"
              value={value ?? ''}
              onChange={(e) => handleChange(e.target.value ? parseInt(e.target.value) : null)}
              disabled={isDisabled}
              className={inputClasses}
              step="1"
            />
            {error && <p className="text-red-500 text-xs mt-1">{error}</p>}
          </div>
        );

      case 'Float':
      case 'Currency':
      case 'Percent':
        return (
          <div className={className}>
            <label className={labelClasses}>
              {fieldConfig.label || fieldConfig.fieldname}
              {isRequired && <span className="text-red-500 ml-1">*</span>}
            </label>
            <input
              type="number"
              value={value ?? ''}
              onChange={(e) => handleChange(e.target.value ? parseFloat(e.target.value) : null)}
              disabled={isDisabled}
              className={inputClasses}
              step="0.01"
            />
            {error && <p className="text-red-500 text-xs mt-1">{error}</p>}
          </div>
        );

      case 'Small Text':
      case 'Text':
      case 'Long Text':
        return (
          <div className={className}>
            <label className={labelClasses}>
              {fieldConfig.label || fieldConfig.fieldname}
              {isRequired && <span className="text-red-500 ml-1">*</span>}
            </label>
            <textarea
              value={value || ''}
              onChange={(e) => handleChange(e.target.value)}
              disabled={isDisabled}
              className={inputClasses}
              rows={fieldConfig.fieldtype === 'Long Text' ? 6 : 3}
            />
            {error && <p className="text-red-500 text-xs mt-1">{error}</p>}
          </div>
        );

      case 'Read Only':
        return (
          <div className={className}>
            <label className={labelClasses}>
              {fieldConfig.label || fieldConfig.fieldname}
            </label>
            <div className={`${inputClasses} bg-gray-50 dark:bg-gray-800`}>
              {value || '-'}
            </div>
          </div>
        );

      case 'Attach':
      case 'Attach Image':
        return (
          <div className={className}>
            <label className={labelClasses}>
              {fieldConfig.label || fieldConfig.fieldname}
              {isRequired && <span className="text-red-500 ml-1">*</span>}
            </label>
            {value && (
              <div className="mb-2">
                {fieldConfig.fieldtype === 'Attach Image' && value ? (
                  <img src={value} alt={fieldConfig.label} className="w-24 h-24 object-cover rounded" />
                ) : (
                  <a href={value} target="_blank" rel="noopener noreferrer" className="text-blue-600 hover:underline text-sm">
                    {value.split('/').pop()}
                  </a>
                )}
              </div>
            )}
            <input
              type="file"
              onChange={(e) => {
                // Handle file upload - you may need to implement actual upload logic
                const file = e.target.files?.[0];
                if (file) {
                  // For now, just store the file name
                  handleChange(file.name);
                }
              }}
              disabled={isDisabled}
              className={inputClasses}
            />
            {error && <p className="text-red-500 text-xs mt-1">{error}</p>}
          </div>
        );

      case 'Data':
      case 'Password':
      default:
        return (
          <div className={className}>
            <label className={labelClasses}>
              {fieldConfig.label || fieldConfig.fieldname}
              {isRequired && <span className="text-red-500 ml-1">*</span>}
            </label>
            <input
              type={fieldConfig.fieldtype === 'Password' ? 'password' : 'text'}
              value={value || ''}
              onChange={(e) => handleChange(e.target.value)}
              disabled={isDisabled}
              className={inputClasses}
              placeholder={fieldConfig.description || ''}
            />
            {error && <p className="text-red-500 text-xs mt-1">{error}</p>}
          </div>
        );
    }
  };

  return renderField();
};

export default DynamicField;

/**
 * DynamicForm Component
 * Renders a complete form based on DocType field configuration
 */
interface DynamicFormProps {
  fields: FieldConfig[];
  doc: Record<string, any>;
  onChange: (fieldname: string, value: any) => void;
  errors?: Record<string, string>;
  disabled?: boolean;
  compact?: boolean;
  columns?: 1 | 2 | 3 | 4;
  excludeFields?: string[];
  includeFields?: string[];
}

export const DynamicForm: React.FC<DynamicFormProps> = ({
  fields,
  doc,
  onChange,
  errors = {},
  disabled = false,
  compact = false,
  columns = 2,
  excludeFields = [],
  includeFields
}) => {
  // Filter and sort fields
  const visibleFields = useMemo(() => {
    let filtered = fields.filter(f => {
      // Skip layout fields
      if (['Section Break', 'Column Break', 'Tab Break'].includes(f.fieldtype)) {
        return false;
      }
      
      // Apply exclude filter
      if (excludeFields.includes(f.fieldname)) {
        return false;
      }
      
      // Apply include filter if specified
      if (includeFields && !includeFields.includes(f.fieldname)) {
        return false;
      }
      
      // Check visibility
      const state = evaluateFieldState(f, doc);
      return state.isVisible;
    });
    
    return filtered;
  }, [fields, doc, excludeFields, includeFields]);

  const gridClass = {
    1: 'grid-cols-1',
    2: 'grid-cols-1 md:grid-cols-2',
    3: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3',
    4: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-4'
  }[columns];

  return (
    <div className={`grid ${gridClass} gap-4`}>
      {visibleFields.map(field => (
        <DynamicField
          key={field.fieldname}
          fieldConfig={field}
          value={doc[field.fieldname]}
          onChange={onChange}
          doc={doc}
          disabled={disabled}
          compact={compact}
          error={errors[field.fieldname]}
        />
      ))}
    </div>
  );
};

