import React, { useState, useEffect, useCallback, useRef } from 'react';
import { 
  FaTimes, 
  FaPlus, 
  FaSpinner, 
  FaCheckCircle, 
  FaTimesCircle,
  FaExclamationTriangle,
  FaSearch
} from 'react-icons/fa';
import { toast } from 'react-toastify';
import { 
  type QuickCreateDoctypeConfig, 
  type QuickCreateFieldConfig, 
  getQuickCreateConfig 
} from './QuickCreateConfig';
import apiService from '../services/apiService';

// Simple Link Input component for use inside modal (avoids circular dependency)
interface SimpleLinkInputProps {
  doctype: string;
  value: string;
  onChange: (value: string) => void;
  disabled?: boolean;
  placeholder?: string;
  filters?: Record<string, any>;
}

const SimpleLinkInput: React.FC<SimpleLinkInputProps> = ({
  doctype,
  value,
  onChange,
  disabled = false,
  placeholder = 'Search...',
  filters = {},
}) => {
  const [searchText, setSearchText] = useState('');
  const [results, setResults] = useState<{ value: string; description?: string }[]>([]);
  const [isOpen, setIsOpen] = useState(false);
  const [isLoading, setIsLoading] = useState(false);
  const containerRef = useRef<HTMLDivElement>(null);
  const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  // Search function
  const searchLink = useCallback(async (text: string = '') => {
    if (!doctype) return;
    setIsLoading(true);
    try {
      const params = new URLSearchParams({ 
        doctype, 
        txt: text,
        page_length: '20',
      });
      if (filters && Object.keys(filters).length > 0) {
        params.append('filters', JSON.stringify(filters));
      }
      const response = await apiService.apiCall<{ value: string; description?: string }[]>(
        `/api/method/frappe.desk.search.search_link?${params.toString()}`
      );
      setResults(response || []);
    } catch (error) {
      console.error(`Error fetching ${doctype} links:`, error);
      setResults([]);
    } finally {
      setIsLoading(false);
    }
  }, [doctype, filters]);

  // Debounced search
  useEffect(() => {
    if (!isOpen) return;
    if (debounceRef.current) clearTimeout(debounceRef.current);
    debounceRef.current = setTimeout(() => searchLink(searchText), 300);
    return () => { if (debounceRef.current) clearTimeout(debounceRef.current); };
  }, [searchText, isOpen, searchLink]);

  // Load on open
  useEffect(() => {
    if (isOpen) searchLink(searchText);
  }, [isOpen]);

  // Close on outside click
  useEffect(() => {
    const handleClickOutside = (e: MouseEvent) => {
      if (containerRef.current && !containerRef.current.contains(e.target as Node)) {
        setIsOpen(false);
        setSearchText('');
      }
    };
    document.addEventListener('mousedown', handleClickOutside);
    return () => document.removeEventListener('mousedown', handleClickOutside);
  }, []);

  const handleSelect = (val: string) => {
    onChange(val);
    setSearchText('');
    setIsOpen(false);
  };

  const handleClear = () => {
    onChange('');
    setSearchText('');
  };

  return (
    <div ref={containerRef} className="relative">
      <div className="relative">
        <FaSearch className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400" size={12} />
        <input
          type="text"
          value={isOpen ? searchText : value}
          placeholder={placeholder}
          disabled={disabled}
          className={`w-full pl-9 pr-8 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded-md 
            focus:outline-none focus:ring-2 focus:ring-blue-500 
            disabled:bg-gray-100 dark:disabled:bg-gray-700 
            bg-white dark:bg-gray-700 text-gray-900 dark:text-white`}
          onFocus={() => !disabled && setIsOpen(true)}
          onChange={(e) => {
            setSearchText(e.target.value);
            setIsOpen(true);
          }}
        />
        {value && !disabled && !isOpen && (
          <button
            type="button"
            onClick={handleClear}
            className="absolute right-2 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600"
          >
            <FaTimes size={12} />
          </button>
        )}
      </div>
      
      {isOpen && !disabled && (
        <div className="absolute z-50 w-full mt-1 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded-md shadow-lg max-h-40 overflow-auto">
          {isLoading ? (
            <div className="p-3 text-center text-gray-500 dark:text-gray-400 text-sm">
              <FaSpinner className="animate-spin inline mr-2" size={12} />
              Loading...
            </div>
          ) : results.length > 0 ? (
            <ul>
              {results.map((item, idx) => (
                <li
                  key={idx}
                  onClick={() => handleSelect(item.value)}
                  className={`px-3 py-2 cursor-pointer text-sm hover:bg-blue-500 hover:text-white
                    ${value === item.value ? 'bg-blue-50 dark:bg-blue-900/30' : ''}`}
                >
                  {item.value}
                  {item.description && (
                    <span className="text-xs text-gray-500 ml-2">{item.description}</span>
                  )}
                </li>
              ))}
            </ul>
          ) : (
            <div className="p-3 text-center text-gray-500 dark:text-gray-400 text-sm">
              No results found
            </div>
          )}
        </div>
      )}
    </div>
  );
};

interface QuickCreateModalProps {
  doctype: string;
  isOpen: boolean;
  onClose: () => void;
  onSuccess: (newRecord: any) => void;
  initialValues?: Record<string, any>;
  parentFilters?: Record<string, any>; // Filters to pass down to link fields
  customConfig?: QuickCreateDoctypeConfig; // Override default config
}

const QuickCreateModal: React.FC<QuickCreateModalProps> = ({
  doctype,
  isOpen,
  onClose,
  onSuccess,
  initialValues = {},
  parentFilters = {},
  customConfig,
}) => {
  const [formData, setFormData] = useState<Record<string, any>>({});
  const [errors, setErrors] = useState<Record<string, string>>({});
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [config, setConfig] = useState<QuickCreateDoctypeConfig | null>(null);

  // Get configuration for the doctype
  useEffect(() => {
    const doctypeConfig = customConfig || getQuickCreateConfig(doctype);
    setConfig(doctypeConfig);

    if (doctypeConfig) {
      // Initialize form data with default values
      const defaultData: Record<string, any> = {};
      doctypeConfig.fields.forEach((field) => {
        if (field.defaultValue !== undefined) {
          defaultData[field.fieldname] = field.defaultValue;
        } else if (field.fieldtype === 'Check') {
          defaultData[field.fieldname] = 0;
        } else {
          defaultData[field.fieldname] = '';
        }
      });

      // Merge with initial values
      setFormData({ ...defaultData, ...initialValues });
    }
  }, [doctype, customConfig, initialValues]);

  // Reset form when modal opens
  useEffect(() => {
    if (isOpen && config) {
      const defaultData: Record<string, any> = {};
      config.fields.forEach((field) => {
        if (field.defaultValue !== undefined) {
          defaultData[field.fieldname] = field.defaultValue;
        } else if (field.fieldtype === 'Check') {
          defaultData[field.fieldname] = 0;
        } else {
          defaultData[field.fieldname] = '';
        }
      });
      setFormData({ ...defaultData, ...initialValues });
      setErrors({});
    }
  }, [isOpen, config, initialValues]);

  // Handle field change
  const handleFieldChange = useCallback((fieldname: string, value: any) => {
    setFormData((prev) => ({ ...prev, [fieldname]: value }));
    // Clear error for this field
    setErrors((prev) => {
      const newErrors = { ...prev };
      delete newErrors[fieldname];
      return newErrors;
    });
  }, []);

  // Validate form
  const validateForm = useCallback((): boolean => {
    if (!config) return false;

    const newErrors: Record<string, string> = {};

    config.fields.forEach((field) => {
      if (field.required && !field.hidden) {
        const value = formData[field.fieldname];
        if (value === undefined || value === null || value === '') {
          newErrors[field.fieldname] = `${field.label} is required`;
        }
      }
    });

    // Run custom validation if provided
    if (config.validateBeforeCreate) {
      const customError = config.validateBeforeCreate(formData);
      if (customError) {
        toast.error(customError, {
          position: 'top-right',
          autoClose: 4000,
          icon: <FaExclamationTriangle />,
        });
        return false;
      }
    }

    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  }, [config, formData]);

  // Handle form submission
  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();

    if (!validateForm() || !config) {
      return;
    }

    setIsSubmitting(true);

    try {
      // Prepare data for API - only include non-empty fields
      const dataToSubmit: Record<string, any> = {};
      Object.entries(formData).forEach(([key, value]) => {
        if (value !== '' && value !== null && value !== undefined) {
          dataToSubmit[key] = value;
        }
      });

      // Make API call to create the record
      const response = await apiService.apiCall<any>(
        `/api/resource/${config.doctype}`,
        {
          method: 'POST',
          body: JSON.stringify(dataToSubmit),
        }
      );

      if (response?.data) {
        const newRecord = response.data;
        
        toast.success(`${config.title.replace('Create New ', '')} created successfully!`, {
          position: 'top-right',
          autoClose: 3000,
          icon: <FaCheckCircle />,
        });

        // Call afterCreate callback if provided
        if (config.afterCreate) {
          config.afterCreate(newRecord);
        }

        // Call onSuccess callback with the new record
        onSuccess(newRecord);
        onClose();
      } else {
        throw new Error('Failed to create record');
      }
    } catch (err) {
      console.error('Error creating record:', err);
      const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred';
      
      // Check for duplicate entry error
      if (errorMessage.includes('Duplicate') || errorMessage.includes('already exists')) {
        toast.error(`A record with this name already exists. Please use a different name.`, {
          position: 'top-right',
          autoClose: 5000,
          icon: <FaTimesCircle />,
        });
      } else {
        toast.error(`Failed to create: ${errorMessage}`, {
          position: 'top-right',
          autoClose: 5000,
          icon: <FaTimesCircle />,
        });
      }
    } finally {
      setIsSubmitting(false);
    }
  };

  // Render a single field based on its type
  const renderField = (field: QuickCreateFieldConfig) => {
    if (field.hidden) return null;

    const value = formData[field.fieldname];
    const error = errors[field.fieldname];
    const isDisabled = field.readOnly || isSubmitting;

    // Check if field should be shown based on depends_on
    if (field.dependsOn) {
      const dependsOnValue = formData[field.dependsOn];
      if (!dependsOnValue) return null;
    }

    const baseInputClass = `w-full px-3 py-2 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 
      ${error ? 'border-red-500' : 'border-gray-300 dark:border-gray-600'}
      ${isDisabled ? 'bg-gray-100 dark:bg-gray-700 cursor-not-allowed' : 'bg-white dark:bg-gray-700'}
      text-gray-900 dark:text-white`;

    switch (field.fieldtype) {
      case 'Data':
        return (
          <input
            type="text"
            value={value || ''}
            onChange={(e) => handleFieldChange(field.fieldname, e.target.value)}
            placeholder={field.placeholder}
            disabled={isDisabled}
            className={baseInputClass}
          />
        );

      case 'Text':
        return (
          <textarea
            value={value || ''}
            onChange={(e) => handleFieldChange(field.fieldname, e.target.value)}
            placeholder={field.placeholder}
            disabled={isDisabled}
            rows={3}
            className={`${baseInputClass} resize-none`}
          />
        );

      case 'Select':
        return (
          <select
            value={value || ''}
            onChange={(e) => handleFieldChange(field.fieldname, e.target.value)}
            disabled={isDisabled}
            className={baseInputClass}
          >
            <option value="">Select {field.label}</option>
            {(field.options || []).map((option) => {
              const optionValue = typeof option === 'string' ? option : option.value;
              const optionLabel = typeof option === 'string' ? option : option.label;
              return (
                <option key={optionValue} value={optionValue}>
                  {optionLabel}
                </option>
              );
            })}
          </select>
        );

      case 'Link':
        return (
          <SimpleLinkInput
            doctype={field.linkDoctype || ''}
            value={value || ''}
            onChange={(val) => handleFieldChange(field.fieldname, val)}
            disabled={isDisabled}
            placeholder={field.placeholder}
            // filters={{ ...field.linkFilters, ...parentFilters }}
            filters={field.linkFilters || {}}
          />
        );

      case 'Check':
        return (
          <label className="flex items-center gap-2 cursor-pointer">
            <input
              type="checkbox"
              checked={value === 1 || value === true}
              onChange={(e) => handleFieldChange(field.fieldname, 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"
            />
            <span className="text-sm text-gray-700 dark:text-gray-300">
              {field.description || field.label}
            </span>
          </label>
        );

      case 'Int':
        return (
          <input
            type="number"
            value={value || ''}
            onChange={(e) => handleFieldChange(field.fieldname, parseInt(e.target.value) || '')}
            placeholder={field.placeholder}
            disabled={isDisabled}
            step="1"
            className={baseInputClass}
          />
        );

      case 'Float':
        return (
          <input
            type="number"
            value={value || ''}
            onChange={(e) => handleFieldChange(field.fieldname, parseFloat(e.target.value) || '')}
            placeholder={field.placeholder}
            disabled={isDisabled}
            step="0.01"
            className={baseInputClass}
          />
        );

      case 'Date':
        return (
          <input
            type="date"
            value={value || ''}
            onChange={(e) => handleFieldChange(field.fieldname, e.target.value)}
            disabled={isDisabled}
            className={baseInputClass}
          />
        );

      case 'Datetime':
        return (
          <input
            type="datetime-local"
            value={value || ''}
            onChange={(e) => handleFieldChange(field.fieldname, e.target.value)}
            disabled={isDisabled}
            className={baseInputClass}
          />
        );

      default:
        return (
          <input
            type="text"
            value={value || ''}
            onChange={(e) => handleFieldChange(field.fieldname, e.target.value)}
            placeholder={field.placeholder}
            disabled={isDisabled}
            className={baseInputClass}
          />
        );
    }
  };

  if (!isOpen || !config) return null;

  return (
    <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-[9999]">
      <div className="bg-white dark:bg-gray-800 rounded-lg shadow-xl w-full max-w-lg mx-4 max-h-[90vh] flex flex-col">
        {/* Header */}
        <div className="flex items-center justify-between p-4 border-b border-gray-200 dark:border-gray-700">
          <h3 className="text-lg font-semibold text-gray-800 dark:text-white flex items-center gap-2">
            <FaPlus className="text-blue-500" size={16} />
            {config.title}
          </h3>
          <button
            type="button"
            onClick={onClose}
            disabled={isSubmitting}
            className="p-1 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 rounded transition-colors disabled:opacity-50"
          >
            <FaTimes size={18} />
          </button>
        </div>

        {/* Form */}
        <form onSubmit={handleSubmit} className="flex-1 overflow-y-auto p-4">
          <div className="space-y-4">
            {config.fields.map((field) => {
              if (field.hidden) return null;
              
              // Check depends_on
              if (field.dependsOn) {
                const dependsOnValue = formData[field.dependsOn];
                if (!dependsOnValue) return null;
              }

              return (
                <div key={field.fieldname}>
                  {field.fieldtype !== 'Check' && (
                    <label className="block text-xs font-medium text-gray-700 dark:text-gray-300 mb-1">
                      {field.label}
                      {field.required && <span className="text-red-500 ml-1">*</span>}
                    </label>
                  )}
                  
                  {renderField(field)}
                  
                  {field.description && field.fieldtype !== 'Check' && (
                    <p className="mt-1 text-xs text-gray-500 dark:text-gray-400">
                      {field.description}
                    </p>
                  )}
                  
                  {errors[field.fieldname] && (
                    <p className="mt-1 text-xs text-red-500 flex items-center gap-1">
                      <FaExclamationTriangle size={10} />
                      {errors[field.fieldname]}
                    </p>
                  )}
                </div>
              );
            })}
          </div>
        </form>

        {/* Footer */}
        <div className="flex justify-end gap-3 p-4 border-t border-gray-200 dark:border-gray-700">
          <button
            type="button"
            onClick={onClose}
            disabled={isSubmitting}
            className="px-4 py-2 text-sm font-medium text-gray-700 bg-gray-200 hover:bg-gray-300 rounded-lg transition-colors disabled:opacity-50"
          >
            Cancel
          </button>
          <button
            type="submit"
            onClick={handleSubmit}
            disabled={isSubmitting}
            className="px-4 py-2 text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 rounded-lg transition-colors disabled:opacity-50 flex items-center gap-2"
          >
            {isSubmitting ? (
              <>
                <FaSpinner className="animate-spin" size={14} />
                Creating...
              </>
            ) : (
              <>
                <FaPlus size={14} />
                Create
              </>
            )}
          </button>
        </div>
      </div>
    </div>
  );
};

export default QuickCreateModal;