import React, { useState, useCallback, useMemo } from 'react';
import { Card, Button, Badge, Input, Select, DatePicker } from '../../ui';
import type { 
  FilterPanelProps, 
  AnalyticsFilter, 
  FilterOption, 
  AppliedFilter, 
  FilterPreset, 
  FilterType 
} from './types';

const FILTER_TYPE_ICONS: Record<FilterType, string> = {
  date: '📅',
  select: '📋',
  multiselect: '☑️',
  range: '↔️',
  text: '🔍',
  number: '#️⃣',
  boolean: '✓',
};

export const FilterPanel: React.FC<FilterPanelProps> = ({
  panel,
  appliedFilters = [],
  onFiltersChange,
  onPresetSelect,
  onPresetSave,
  onPresetDelete,
  onReset,
  loading = false,
  disabled = false,
  compact = false,
  showPresets = true,
  showReset = true,
  className = '',
}) => {
  const [isCollapsed, setIsCollapsed] = useState(panel.default_collapsed);
  const [localFilters, setLocalFilters] = useState<Record<string, any>>({});
  const [isPresetModalOpen, setIsPresetModalOpen] = useState(false);
  const [newPresetName, setNewPresetName] = useState('');
  const [newPresetDescription, setNewPresetDescription] = useState('');
  const [validationErrors, setValidationErrors] = useState<Record<string, string>>({});

  const appliedFiltersMap = useMemo(() => {
    const map: Record<string, AppliedFilter> = {};
    appliedFilters.forEach(filter => {
      map[filter.filter_id] = filter;
    });
    return map;
  }, [appliedFilters]);

  const getFilterValue = useCallback((filter: AnalyticsFilter) => {
    const applied = appliedFiltersMap[filter.id];
    if (applied) {
      return applied.value;
    }
    
    const local = localFilters[filter.id];
    if (local !== undefined) {
      return local;
    }
    
    return filter.default_value;
  }, [appliedFiltersMap, localFilters]);

  const updateFilterValue = useCallback((filterId: string, value: any) => {
    setLocalFilters(prev => ({ ...prev, [filterId]: value }));
    
    // Clear validation error for this filter
    setValidationErrors(prev => {
      const newErrors = { ...prev };
      delete newErrors[filterId];
      return newErrors;
    });
  }, []);

  const validateFilter = useCallback((filter: AnalyticsFilter, value: any): string | null => {
    if (!filter.validation_rules) return null;
    
    for (const rule of filter.validation_rules) {
      switch (rule.rule) {
        case 'required':
          if (!value || (Array.isArray(value) && value.length === 0)) {
            return rule.message;
          }
          break;
        case 'min':
          if (typeof value === 'number' && value < rule.value) {
            return rule.message;
          }
          if (typeof value === 'string' && value.length < rule.value) {
            return rule.message;
          }
          break;
        case 'max':
          if (typeof value === 'number' && value > rule.value) {
            return rule.message;
          }
          if (typeof value === 'string' && value.length > rule.value) {
            return rule.message;
          }
          break;
        case 'pattern':
          if (typeof value === 'string' && !new RegExp(rule.value).test(value)) {
            return rule.message;
          }
          break;
      }
    }
    
    return null;
  }, []);

  const applyFilters = useCallback(() => {
    const errors: Record<string, string> = {};
    const newAppliedFilters: AppliedFilter[] = [];

    panel.filters.forEach(filter => {
      const value = getFilterValue(filter);
      
      // Validate the filter
      const validationError = validateFilter(filter, value);
      if (validationError) {
        errors[filter.id] = validationError;
        return;
      }

      // Skip if no value and not required
      if ((value === undefined || value === null || value === '') && !filter.required) {
        return;
      }

      // Create applied filter
      const appliedFilter: AppliedFilter = {
        filter_id: filter.id,
        field: filter.field,
        operator: getOperatorForFilterType(filter.type),
        value,
        display_value: formatDisplayValue(filter, value),
      };

      newAppliedFilters.push(appliedFilter);
    });

    setValidationErrors(errors);

    if (Object.keys(errors).length === 0 && onFiltersChange) {
      onFiltersChange(newAppliedFilters);
    }
  }, [panel.filters, getFilterValue, validateFilter, onFiltersChange]);

  const resetFilters = useCallback(() => {
    setLocalFilters({});
    setValidationErrors({});
    if (onReset) {
      onReset();
    }
  }, [onReset]);

  const getOperatorForFilterType = (type: FilterType): string => {
    switch (type) {
      case 'select':
      case 'boolean':
        return 'eq';
      case 'multiselect':
        return 'in';
      case 'range':
        return 'between';
      case 'text':
        return 'like';
      case 'number':
      case 'date':
        return 'eq';
      default:
        return 'eq';
    }
  };

  const formatDisplayValue = (filter: AnalyticsFilter, value: any): string => {
    if (value === undefined || value === null) return '';
    
    switch (filter.type) {
      case 'select':
      case 'multiselect':
        if (filter.options) {
          const options = Array.isArray(value) ? value : [value];
          return options
            .map(v => filter.options?.find(opt => opt.value === v)?.label || v)
            .join(', ');
        }
        return Array.isArray(value) ? value.join(', ') : String(value);
      case 'boolean':
        return value ? 'Sí' : 'No';
      case 'date':
        return new Date(value).toLocaleDateString('es-ES');
      case 'range':
        return Array.isArray(value) ? `${value[0]} - ${value[1]}` : String(value);
      default:
        return String(value);
    }
  };

  const handlePresetSelect = (presetId: string) => {
    const preset = panel.presets.find(p => p.id === presetId);
    if (preset) {
      setLocalFilters(preset.values);
      if (onPresetSelect) {
        onPresetSelect(presetId);
      }
      // Auto-apply filters when preset is selected
      setTimeout(applyFilters, 0);
    }
  };

  const handlePresetSave = () => {
    if (!newPresetName.trim()) return;

    const currentValues: Record<string, any> = {};
    panel.filters.forEach(filter => {
      const value = getFilterValue(filter);
      if (value !== undefined && value !== null && value !== '') {
        currentValues[filter.id] = value;
      }
    });

    const newPreset: Omit<FilterPreset, 'id'> = {
      name: newPresetName.trim(),
      description: newPresetDescription.trim() || undefined,
      is_default: false,
      is_public: false,
      values: currentValues,
    };

    if (onPresetSave) {
      onPresetSave(newPreset);
    }

    setIsPresetModalOpen(false);
    setNewPresetName('');
    setNewPresetDescription('');
  };

  const renderFilter = (filter: AnalyticsFilter) => {
    const value = getFilterValue(filter);
    const error = validationErrors[filter.id];
    const isDisabled = disabled || loading;

    const commonProps = {
      disabled: isDisabled,
      className: error ? 'border-red-300 focus:border-red-500' : '',
    };

    let filterInput: React.ReactNode;

    switch (filter.type) {
      case 'text':
        filterInput = (
          <Input
            type="text"
            placeholder={filter.placeholder}
            value={value || ''}
            onChange={(e) => updateFilterValue(filter.id, e.target.value)}
            {...commonProps}
          />
        );
        break;

      case 'number':
        filterInput = (
          <Input
            type="number"
            placeholder={filter.placeholder}
            value={value || ''}
            onChange={(e) => updateFilterValue(filter.id, parseFloat(e.target.value) || null)}
            {...commonProps}
          />
        );
        break;

      case 'select':
        filterInput = (
          <Select
            value={value || ''}
            onChange={(e) => updateFilterValue(filter.id, e.target.value)}
            {...commonProps}
          >
            <option value="">Seleccionar...</option>
            {filter.options?.map((option) => (
              <option 
                key={option.value} 
                value={option.value}
                disabled={option.disabled}
              >
                {option.icon} {option.label}
              </option>
            ))}
          </Select>
        );
        break;

      case 'multiselect':
        const selectedValues = Array.isArray(value) ? value : [];
        filterInput = (
          <div className="space-y-2">
            <div className="max-h-32 overflow-y-auto border border-[var(--border-secondary)] rounded p-2">
              {filter.options?.map((option) => (
                <label key={option.value} className="flex items-center gap-2 p-1">
                  <input
                    type="checkbox"
                    checked={selectedValues.includes(option.value)}
                    onChange={(e) => {
                      const newValues = e.target.checked
                        ? [...selectedValues, option.value]
                        : selectedValues.filter(v => v !== option.value);
                      updateFilterValue(filter.id, newValues);
                    }}
                    disabled={isDisabled || option.disabled}
                    className="rounded"
                  />
                  <span className="text-sm">
                    {option.icon} {option.label}
                  </span>
                </label>
              ))}
            </div>
            {selectedValues.length > 0 && (
              <div className="flex flex-wrap gap-1">
                {selectedValues.map((val) => {
                  const option = filter.options?.find(opt => opt.value === val);
                  return (
                    <Badge key={val} className="bg-[var(--color-info)]/10 text-[var(--color-info)] text-xs">
                      {option?.label || val}
                      <button
                        onClick={() => {
                          const newValues = selectedValues.filter(v => v !== val);
                          updateFilterValue(filter.id, newValues);
                        }}
                        className="ml-1 text-[var(--color-info)] hover:text-[var(--color-info)]"
                      >
                        ×
                      </button>
                    </Badge>
                  );
                })}
              </div>
            )}
          </div>
        );
        break;

      case 'boolean':
        filterInput = (
          <Select
            value={value === true ? 'true' : value === false ? 'false' : ''}
            onChange={(e) => {
              const val = e.target.value === 'true' ? true : e.target.value === 'false' ? false : null;
              updateFilterValue(filter.id, val);
            }}
            {...commonProps}
          >
            <option value="">Seleccionar...</option>
            <option value="true">Sí</option>
            <option value="false">No</option>
          </Select>
        );
        break;

      case 'date':
        filterInput = (
          <DatePicker
            value={value ? new Date(value) : null}
            onChange={(date) => updateFilterValue(filter.id, date?.toISOString())}
            placeholder={filter.placeholder}
            disabled={isDisabled}
          />
        );
        break;

      case 'range':
        const rangeValue = Array.isArray(value) ? value : [null, null];
        filterInput = (
          <div className="flex gap-2 items-center">
            <Input
              type="number"
              placeholder="Mín"
              value={rangeValue[0] || ''}
              onChange={(e) => {
                const newRange = [parseFloat(e.target.value) || null, rangeValue[1]];
                updateFilterValue(filter.id, newRange);
              }}
              {...commonProps}
              className="flex-1"
            />
            <span className="text-[var(--text-tertiary)]">-</span>
            <Input
              type="number"
              placeholder="Máx"
              value={rangeValue[1] || ''}
              onChange={(e) => {
                const newRange = [rangeValue[0], parseFloat(e.target.value) || null];
                updateFilterValue(filter.id, newRange);
              }}
              {...commonProps}
              className="flex-1"
            />
          </div>
        );
        break;

      default:
        filterInput = (
          <div className="text-[var(--text-tertiary)] text-sm">
            Tipo de filtro no soportado: {filter.type}
          </div>
        );
    }

    return (
      <div key={filter.id} className={compact ? 'space-y-1' : 'space-y-2'}>
        <div className="flex items-center justify-between">
          <label className={`font-medium text-[var(--text-secondary)] ${compact ? 'text-sm' : ''}`}>
            <span className="mr-1">{FILTER_TYPE_ICONS[filter.type]}</span>
            {filter.display_name}
            {filter.required && <span className="text-red-500 ml-1">*</span>}
          </label>
          
          {filter.help_text && (
            <span className="text-xs text-[var(--text-tertiary)]" title={filter.help_text}>
              ℹ️
            </span>
          )}
        </div>
        
        {filterInput}
        
        {error && (
          <p className="text-sm text-[var(--color-error)]">{error}</p>
        )}
      </div>
    );
  };

  const renderPresets = () => {
    if (!showPresets || panel.presets.length === 0) return null;

    return (
      <div className="space-y-2">
        <div className="flex items-center justify-between">
          <h4 className="font-medium text-[var(--text-secondary)]">Filtros guardados</h4>
          <Button
            variant="ghost"
            size="sm"
            onClick={() => setIsPresetModalOpen(true)}
            disabled={disabled || loading}
          >
            💾 Guardar
          </Button>
        </div>
        
        <div className="flex flex-wrap gap-2">
          {panel.presets.map((preset) => (
            <div key={preset.id} className="flex items-center gap-1">
              <Button
                variant="outline"
                size="sm"
                onClick={() => handlePresetSelect(preset.id)}
                disabled={disabled || loading}
                className={panel.active_preset === preset.id ? 'bg-[var(--color-info)]/5 border-blue-300' : ''}
              >
                {preset.icon && <span className="mr-1">{preset.icon}</span>}
                {preset.name}
              </Button>
              
              {onPresetDelete && !preset.is_public && (
                <Button
                  variant="ghost"
                  size="sm"
                  onClick={() => onPresetDelete(preset.id)}
                  className="text-[var(--color-error)] hover:text-[var(--color-error)] p-1"
                >
                  ×
                </Button>
              )}
            </div>
          ))}
        </div>
      </div>
    );
  };

  if (panel.collapsible && isCollapsed) {
    return (
      <Card className={`p-3 ${className}`}>
        <button
          onClick={() => setIsCollapsed(false)}
          className="flex items-center justify-between w-full text-left"
        >
          <h3 className="font-semibold text-[var(--text-primary)]">{panel.title}</h3>
          <span className="text-[var(--text-tertiary)]">▼</span>
        </button>
      </Card>
    );
  }

  const gridClass = panel.layout === 'grid' ? 'grid grid-cols-1 md:grid-cols-2 gap-4' :
                   panel.layout === 'horizontal' ? 'grid grid-cols-1 lg:grid-cols-3 gap-4' :
                   'space-y-4';

  return (
    <>
      <Card className={`p-4 ${className}`}>
        <div className="space-y-4">
          {/* Header */}
          <div className="flex items-center justify-between">
            <h3 className="font-semibold text-[var(--text-primary)]">{panel.title}</h3>
            <div className="flex items-center gap-2">
              {loading && (
                <div className="animate-spin rounded-full h-4 w-4 border-b-2 border-blue-600"></div>
              )}
              
              {panel.collapsible && (
                <Button
                  variant="ghost"
                  size="sm"
                  onClick={() => setIsCollapsed(true)}
                >
                  ▲
                </Button>
              )}
            </div>
          </div>

          {/* Presets */}
          {renderPresets()}

          {/* Filters */}
          <div className={gridClass}>
            {panel.filters.map(filter => renderFilter(filter))}
          </div>

          {/* Actions */}
          <div className="flex items-center justify-between pt-4 border-t border-[var(--border-primary)]">
            <div className="text-sm text-[var(--text-secondary)]">
              {appliedFilters.length} filtro{appliedFilters.length !== 1 ? 's' : ''} aplicado{appliedFilters.length !== 1 ? 's' : ''}
            </div>
            
            <div className="flex gap-2">
              {showReset && appliedFilters.length > 0 && (
                <Button
                  variant="outline"
                  size="sm"
                  onClick={resetFilters}
                  disabled={disabled || loading}
                >
                  Limpiar
                </Button>
              )}
              
              <Button
                variant="primary"
                size="sm"
                onClick={applyFilters}
                disabled={disabled || loading}
              >
                Aplicar filtros
              </Button>
            </div>
          </div>
        </div>
      </Card>

      {/* Save Preset Modal */}
      {isPresetModalOpen && (
        <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50">
          <Card className="w-full max-w-md p-6">
            <h3 className="text-lg font-semibold mb-4">Guardar filtro</h3>
            
            <div className="space-y-4">
              <div>
                <label className="block text-sm font-medium text-[var(--text-secondary)] mb-1">
                  Nombre del filtro *
                </label>
                <Input
                  type="text"
                  value={newPresetName}
                  onChange={(e) => setNewPresetName(e.target.value)}
                  placeholder="Ej: Ventas del último mes"
                  className="w-full"
                />
              </div>
              
              <div>
                <label className="block text-sm font-medium text-[var(--text-secondary)] mb-1">
                  Descripción (opcional)
                </label>
                <Input
                  type="text"
                  value={newPresetDescription}
                  onChange={(e) => setNewPresetDescription(e.target.value)}
                  placeholder="Descripción del filtro"
                  className="w-full"
                />
              </div>

              <div className="flex justify-end gap-2 pt-4 border-t border-[var(--border-primary)]">
                <Button
                  variant="outline"
                  onClick={() => {
                    setIsPresetModalOpen(false);
                    setNewPresetName('');
                    setNewPresetDescription('');
                  }}
                >
                  Cancelar
                </Button>
                <Button
                  variant="primary"
                  onClick={handlePresetSave}
                  disabled={!newPresetName.trim()}
                >
                  Guardar
                </Button>
              </div>
            </div>
          </Card>
        </div>
      )}
    </>
  );
};

export default FilterPanel;