import React, { useMemo, useCallback } from 'react';
import DynamicFormField, { getWidthClass } from './DynamicFormField';

/**
 * DynamicRegistrationForm - Renders the entire registration form from schema
 *
 * Features:
 * - Renders steps and sections based on schema
 * - Handles conditional field visibility
 * - Supports step navigation
 * - Validates fields per step
 */
const DynamicRegistrationForm = ({
  schema,
  formData,
  onFormDataChange,
  currentStep,
  errors = {},
}) => {
  // Get current step data
  const stepData = useMemo(() => {
    const steps = schema?.steps || [];
    const sortedSteps = [...steps].sort((a, b) => a.order - b.order);
    return sortedSteps[currentStep - 1] || null;
  }, [schema, currentStep]);

  // Evaluate conditional rules to determine which fields are visible
  const hiddenFields = useMemo(() => {
    const rules = schema?.conditional_rules || [];
    const hidden = new Set();

    // First pass: collect fields that have "show" rules (hidden by default)
    for (const rule of rules) {
      if (rule.action === 'show') {
        rule.target_fields?.forEach((fieldId) => hidden.add(fieldId));
      }
    }

    // Second pass: evaluate rules and show/hide fields
    for (const rule of rules) {
      const {
        trigger_field,
        trigger_operator = 'equals',
        trigger_value,
        action,
        target_fields = [],
      } = rule;

      const fieldValue = formData[trigger_field];
      let conditionMet = false;

      switch (trigger_operator) {
        case 'equals':
          conditionMet = fieldValue === trigger_value;
          break;
        case 'not_equals':
          conditionMet = fieldValue !== trigger_value;
          break;
        case 'contains':
          conditionMet = Array.isArray(fieldValue)
            ? fieldValue.includes(trigger_value)
            : String(fieldValue || '').includes(trigger_value);
          break;
        case 'not_empty':
          conditionMet = Boolean(fieldValue);
          break;
        case 'empty':
          conditionMet = !Boolean(fieldValue);
          break;
        default:
          conditionMet = false;
      }

      if (conditionMet) {
        if (action === 'show') {
          target_fields.forEach((fieldId) => hidden.delete(fieldId));
        } else if (action === 'hide') {
          target_fields.forEach((fieldId) => hidden.add(fieldId));
        }
      }
    }

    return hidden;
  }, [schema, formData]);

  // Handle field change
  const handleFieldChange = useCallback(
    (fieldId, value) => {
      onFormDataChange((prev) => ({
        ...prev,
        [fieldId]: value,
      }));
    },
    [onFormDataChange]
  );

  // Check if a field is visible
  const isFieldVisible = useCallback(
    (fieldId) => {
      return !hiddenFields.has(fieldId);
    },
    [hiddenFields]
  );

  // Get errors for a specific field
  const getFieldErrors = useCallback(
    (fieldId) => {
      return errors[fieldId] || [];
    },
    [errors]
  );

  // Group fields by their width for rendering
  const groupFieldsByRow = (fields) => {
    const rows = [];
    let currentRow = [];
    let currentRowWidth = 0;

    const visibleFields = fields.filter((f) => isFieldVisible(f.id));

    for (const field of visibleFields) {
      const width = field.width || 'full';
      let widthValue = 1;

      if (width === 'half') widthValue = 0.5;
      else if (width === 'third') widthValue = 0.33;
      else if (width === 'two-thirds') widthValue = 0.67;

      if (currentRowWidth + widthValue > 1) {
        if (currentRow.length > 0) {
          rows.push(currentRow);
        }
        currentRow = [field];
        currentRowWidth = widthValue;
      } else {
        currentRow.push(field);
        currentRowWidth += widthValue;
      }
    }

    if (currentRow.length > 0) {
      rows.push(currentRow);
    }

    return rows;
  };

  if (!stepData) {
    return (
      <div className="text-center py-8 text-muted-foreground">
        No step data available
      </div>
    );
  }

  return (
    <div className="space-y-8">
      {/* Step Header */}
      {stepData.description && (
        <p
          className="text-brand-purple"
          style={{ fontFamily: "'Nunito Sans', sans-serif" }}
        >
          {stepData.description}
        </p>
      )}

      {/* Sections */}
      {stepData.sections
        ?.sort((a, b) => a.order - b.order)
        .map((section) => {
          const visibleFields = section.fields?.filter((f) =>
            isFieldVisible(f.id)
          );

          // Skip empty sections
          if (!visibleFields || visibleFields.length === 0) {
            return null;
          }

          const fieldRows = groupFieldsByRow(
            section.fields?.sort((a, b) => a.order - b.order) || []
          );

          return (
            <div key={section.id} className="space-y-4">
              {/* Section Title */}
              {section.title && (
                <h2
                  className="text-2xl font-semibold text-[var(--purple-ink)]"
                  style={{ fontFamily: "'Inter', sans-serif" }}
                >
                  {section.title}
                </h2>
              )}

              {/* Section Description */}
              {section.description && (
                <p className="text-muted-foreground">{section.description}</p>
              )}

              {/* Fields */}
              <div className="space-y-4">
                {fieldRows.map((row, rowIndex) => {
                  // Determine grid class based on field widths
                  const hasThird = row.some((f) => f.width === 'third');
                  const hasHalf = row.some((f) => f.width === 'half');
                  const gridCols = hasThird
                    ? 'grid md:grid-cols-3 gap-4'
                    : hasHalf
                    ? 'grid md:grid-cols-2 gap-4'
                    : '';

                  if (row.length === 1 && !hasHalf && !hasThird) {
                    // Single full-width field
                    const field = row[0];
                    return (
                      <DynamicFormField
                        key={field.id}
                        field={field}
                        value={formData[field.id]}
                        onChange={handleFieldChange}
                        errors={getFieldErrors(field.id)}
                        formData={formData}
                      />
                    );
                  }

                  return (
                    <div key={`row-${rowIndex}`} className={gridCols}>
                      {row.map((field) => (
                        <div
                          key={field.id}
                          className={getWidthClass(field.width)}
                        >
                          <DynamicFormField
                            field={field}
                            value={formData[field.id]}
                            onChange={handleFieldChange}
                            errors={getFieldErrors(field.id)}
                            formData={formData}
                          />
                        </div>
                      ))}
                    </div>
                  );
                })}
              </div>
            </div>
          );
        })}
    </div>
  );
};

/**
 * DynamicStepIndicator - Renders step progress indicator
 */
export const DynamicStepIndicator = ({ steps, currentStep }) => {
  const sortedSteps = [...steps].sort((a, b) => a.order - b.order);

  return (
    <div className="mb-8">
      <div className="flex items-center justify-between">
        {sortedSteps.map((step, index) => {
          const stepNumber = index + 1;
          const isActive = stepNumber === currentStep;
          const isCompleted = stepNumber < currentStep;

          return (
            <div key={step.id} className="flex items-center flex-1">
              {/* Step Circle */}
              <div className="flex flex-col items-center">
                <div
                  className={`w-10 h-10 rounded-full flex items-center justify-center text-lg font-medium transition-colors ${
                    isActive
                      ? 'bg-brand-purple text-white'
                      : isCompleted
                      ? 'bg-green-500 text-white'
                      : 'bg-[var(--neutral-800)] text-[var(--purple-ink)]'
                  }`}
                >
                  {isCompleted ? '✓' : stepNumber}
                </div>
                <span
                  className={`mt-2 text-sm text-center hidden md:block ${
                    isActive ? 'text-brand-purple font-medium' : 'text-muted-foreground'
                  }`}
                >
                  {step.title}
                </span>
              </div>

              {/* Connector Line */}
              {index < sortedSteps.length - 1 && (
                <div
                  className={`flex-1 h-1 mx-4 rounded ${
                    isCompleted
                      ? 'bg-green-500'
                      : 'bg-[var(--neutral-800)]'
                  }`}
                />
              )}
            </div>
          );
        })}
      </div>
    </div>
  );
};

/**
 * Validate a single step based on schema
 */
export const validateStep = (stepData, formData, hiddenFields) => {
  const errors = {};

  if (!stepData?.sections) return { isValid: true, errors };

  for (const section of stepData.sections) {
    // Check section-level validation (e.g., atLeastOne)
    const sectionValidation = section.validation || {};
    if (sectionValidation.atLeastOne) {
      const fieldIds = (section.fields || []).map((f) => f.id);
      const hasValue = fieldIds.some((id) => {
        if (hiddenFields.has(id)) return true; // Skip hidden fields
        const value = formData[id];
        return Boolean(value);
      });
      if (!hasValue) {
        // Add error to first field in section
        const firstFieldId = fieldIds[0];
        if (firstFieldId) {
          errors[firstFieldId] = [
            sectionValidation.message ||
              `At least one field in ${section.title || 'this section'} is required`,
          ];
        }
      }
    }

    // Check field-level validation
    for (const field of section.fields || []) {
      const { id, required, validation = {}, type, label } = field;

      // Skip hidden fields
      if (hiddenFields.has(id)) continue;

      // Skip client-only fields for server validation
      if (field.client_only && field.id !== 'confirmPassword') continue;

      const value = formData[id];

      // Required check
      if (required) {
        const isEmpty =
          value === undefined ||
          value === null ||
          value === '' ||
          (Array.isArray(value) && value.length === 0);

        if (isEmpty) {
          errors[id] = [`${label || id} is required`];
          continue;
        }
      }

      // Skip further validation if value is empty
      if (!value && value !== false) continue;

      // Type-specific validation
      const fieldErrors = [];

      if (type === 'email') {
        const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
        if (!emailRegex.test(value)) {
          fieldErrors.push('Please enter a valid email address');
        }
      }

      if (type === 'password') {
        if (validation.minLength && value.length < validation.minLength) {
          fieldErrors.push(
            `Password must be at least ${validation.minLength} characters`
          );
        }
      }

      if (type === 'text' || type === 'textarea') {
        if (validation.minLength && value.length < validation.minLength) {
          fieldErrors.push(
            `${label || id} must be at least ${validation.minLength} characters`
          );
        }
        if (validation.maxLength && value.length > validation.maxLength) {
          fieldErrors.push(
            `${label || id} must be at most ${validation.maxLength} characters`
          );
        }
      }

      // Match field validation (for confirmPassword)
      if (validation.matchField) {
        if (value !== formData[validation.matchField]) {
          fieldErrors.push('Passwords do not match');
        }
      }

      if (fieldErrors.length > 0) {
        errors[id] = fieldErrors;
      }
    }
  }

  return {
    isValid: Object.keys(errors).length === 0,
    errors,
  };
};

/**
 * Evaluate conditional rules to get hidden fields set
 */
export const evaluateConditionalRules = (schema, formData) => {
  const rules = schema?.conditional_rules || [];
  const hidden = new Set();

  // First pass: collect fields that have "show" rules (hidden by default)
  for (const rule of rules) {
    if (rule.action === 'show') {
      rule.target_fields?.forEach((fieldId) => hidden.add(fieldId));
    }
  }

  // Second pass: evaluate rules and show/hide fields
  for (const rule of rules) {
    const {
      trigger_field,
      trigger_operator = 'equals',
      trigger_value,
      action,
      target_fields = [],
    } = rule;

    const fieldValue = formData[trigger_field];
    let conditionMet = false;

    switch (trigger_operator) {
      case 'equals':
        conditionMet = fieldValue === trigger_value;
        break;
      case 'not_equals':
        conditionMet = fieldValue !== trigger_value;
        break;
      case 'contains':
        conditionMet = Array.isArray(fieldValue)
          ? fieldValue.includes(trigger_value)
          : String(fieldValue || '').includes(trigger_value);
        break;
      case 'not_empty':
        conditionMet = Boolean(fieldValue);
        break;
      case 'empty':
        conditionMet = !Boolean(fieldValue);
        break;
      default:
        conditionMet = false;
    }

    if (conditionMet) {
      if (action === 'show') {
        target_fields.forEach((fieldId) => hidden.delete(fieldId));
      } else if (action === 'hide') {
        target_fields.forEach((fieldId) => hidden.add(fieldId));
      }
    }
  }

  return hidden;
};

export default DynamicRegistrationForm;
