import { useState, useCallback, useEffect } from 'react';
import { 
  validateFormComprehensive,
  validateFieldRealTime,
  generateValidationSummary
} from '../utils/validation';

/**
 * Custom hook for comprehensive form validation with real-time feedback
 * @param {string} formType - Type of form ('project', 'rodal', 'tree', 'user')
 * @param {object} initialData - Initial form data
 * @param {object} additionalData - Additional data for validation (e.g., existing records)
 * @param {object} options - Validation options
 */
export const useValidation = (formType, initialData = {}, additionalData = {}, options = {}) => {
  const {
    validateOnChange = true,
    validateOnBlur = true,
    showWarnings = true,
    debounceMs = 300
  } = options;

  const [formData, setFormData] = useState(initialData);
  const [validationResult, setValidationResult] = useState(null);
  const [fieldValidations, setFieldValidations] = useState({});
  const [isValidating, setIsValidating] = useState(false);
  const [validationSummary, setValidationSummary] = useState(null);
  const [touchedFields, setTouchedFields] = useState(new Set());

  // Debounce timer for validation
  const [debounceTimer, setDebounceTimer] = useState(null);

  /**
   * Validate a single field
   */
  const validateField = useCallback((fieldName, value, additionalFieldData = {}) => {
    const validation = validateFieldRealTime(
      fieldName, 
      value, 
      { ...additionalData, ...additionalFieldData }
    );
    
    setFieldValidations(prev => ({
      ...prev,
      [fieldName]: validation
    }));
    
    return validation;
  }, [additionalData]);

  /**
   * Validate the entire form
   */
  const validateForm = useCallback(() => {
    setIsValidating(true);
    
    try {
      const result = validateFormComprehensive(formType, formData, additionalData);
      setValidationResult(result);
      
      const summary = generateValidationSummary(result);
      setValidationSummary(summary);
      
      return result;
    } catch (error) {
      console.error('Form validation error:', error);
      const errorResult = {
        isValid: false,
        errors: { general: 'Error en la validación del formulario' },
        warnings: {},
        fieldValidations: {}
      };
      setValidationResult(errorResult);
      return errorResult;
    } finally {
      setIsValidating(false);
    }
  }, [formType, formData, additionalData]);

  /**
   * Update a field value with optional validation
   */
  const updateField = useCallback((fieldName, value, validate = validateOnChange) => {
    setFormData(prev => ({
      ...prev,
      [fieldName]: value
    }));

    // Mark field as touched
    setTouchedFields(prev => new Set([...prev, fieldName]));

    // Clear existing debounce timer
    if (debounceTimer) {
      clearTimeout(debounceTimer);
    }

    // Validate field with debounce if enabled
    if (validate && debounceMs > 0) {
      const timer = setTimeout(() => {
        validateField(fieldName, value);
      }, debounceMs);
      setDebounceTimer(timer);
    } else if (validate) {
      validateField(fieldName, value);
    }
  }, [validateOnChange, debounceMs, debounceTimer, validateField]);

  /**
   * Handle field blur event
   */
  const handleFieldBlur = useCallback((fieldName, value) => {
    setTouchedFields(prev => new Set([...prev, fieldName]));
    
    if (validateOnBlur) {
      validateField(fieldName, value);
    }
  }, [validateOnBlur, validateField]);

  /**
   * Reset form to initial state
   */
  const resetForm = useCallback(() => {
    setFormData(initialData);
    setValidationResult(null);
    setFieldValidations({});
    setValidationSummary(null);
    setTouchedFields(new Set());
    setIsValidating(false);
    
    if (debounceTimer) {
      clearTimeout(debounceTimer);
      setDebounceTimer(null);
    }
  }, [initialData, debounceTimer]);

  /**
   * Reset validation state only
   */
  const resetValidation = useCallback(() => {
    setValidationResult(null);
    setFieldValidations({});
    setValidationSummary(null);
    setIsValidating(false);
  }, []);

  /**
   * Set form data programmatically
   */
  const setFormDataProgrammatically = useCallback((newData, validate = false) => {
    setFormData(newData);
    
    if (validate) {
      // Validate all fields
      Object.keys(newData).forEach(fieldName => {
        validateField(fieldName, newData[fieldName]);
      });
    }
  }, [validateField]);

  /**
   * Get field validation state
   */
  const getFieldValidation = useCallback((fieldName) => {
    return fieldValidations[fieldName] || { isValid: true, errors: [], warnings: [] };
  }, [fieldValidations]);

  /**
   * Check if field has been touched
   */
  const isFieldTouched = useCallback((fieldName) => {
    return touchedFields.has(fieldName);
  }, [touchedFields]);

  /**
   * Get field error message
   */
  const getFieldError = useCallback((fieldName) => {
    const validation = getFieldValidation(fieldName);
    return validation.errors && validation.errors.length > 0 ? validation.errors[0] : null;
  }, [getFieldValidation]);

  /**
   * Get field warning messages
   */
  const getFieldWarnings = useCallback((fieldName) => {
    const validation = getFieldValidation(fieldName);
    return validation.warnings || [];
  }, [getFieldValidation]);

  /**
   * Check if field is valid
   */
  const isFieldValid = useCallback((fieldName) => {
    const validation = getFieldValidation(fieldName);
    return validation.isValid;
  }, [getFieldValidation]);

  /**
   * Get all form errors
   */
  const getAllErrors = useCallback(() => {
    const errors = {};
    
    // Add form-level errors
    if (validationResult && validationResult.errors) {
      Object.assign(errors, validationResult.errors);
    }
    
    // Add field-level errors
    Object.keys(fieldValidations).forEach(fieldName => {
      const validation = fieldValidations[fieldName];
      if (!validation.isValid && validation.errors && validation.errors.length > 0) {
        errors[fieldName] = validation.errors[0];
      }
    });
    
    return errors;
  }, [validationResult, fieldValidations]);

  /**
   * Get all form warnings
   */
  const getAllWarnings = useCallback(() => {
    const warnings = {};
    
    // Add form-level warnings
    if (validationResult && validationResult.warnings) {
      Object.assign(warnings, validationResult.warnings);
    }
    
    // Add field-level warnings
    Object.keys(fieldValidations).forEach(fieldName => {
      const validation = fieldValidations[fieldName];
      if (validation.warnings && validation.warnings.length > 0) {
        warnings[fieldName] = validation.warnings;
      }
    });
    
    return warnings;
  }, [validationResult, fieldValidations]);

  // Cleanup debounce timer on unmount
  useEffect(() => {
    return () => {
      if (debounceTimer) {
        clearTimeout(debounceTimer);
      }
    };
  }, [debounceTimer]);

  // Computed properties
  const isValid = validationResult?.isValid ?? true;
  const hasErrors = Object.keys(getAllErrors()).length > 0;
  const hasWarnings = Object.keys(getAllWarnings()).length > 0;
  const errorCount = Object.keys(getAllErrors()).length;
  const warningCount = Object.values(getAllWarnings()).flat().length;

  return {
    // Form data
    formData,
    setFormData: setFormDataProgrammatically,
    
    // Validation results
    validationResult,
    fieldValidations,
    validationSummary,
    isValidating,
    
    // Validation state
    isValid,
    hasErrors,
    hasWarnings,
    errorCount,
    warningCount,
    
    // Field operations
    updateField,
    handleFieldBlur,
    validateField,
    
    // Form operations
    validateForm,
    resetForm,
    resetValidation,
    
    // Field state queries
    getFieldValidation,
    getFieldError,
    getFieldWarnings,
    isFieldValid,
    isFieldTouched,
    
    // Bulk queries
    getAllErrors,
    getAllWarnings,
    
    // Touch state
    touchedFields,
    setTouchedFields
  };
};

/**
 * Hook for validating sync data integrity
 */
export const useSyncValidation = () => {
  const [validationResult, setValidationResult] = useState(null);
  const [isValidating, setIsValidating] = useState(false);

  const validateSyncData = useCallback(async (records) => {
    setIsValidating(true);
    
    try {
      const { validateSyncDataIntegrity, validateBatchConsistency } = await import('../utils/validation');
      
      // Validate data integrity
      const integrityResult = validateSyncDataIntegrity(records);
      
      // If we have valid records, also validate batch consistency
      if (integrityResult.validRecords.length > 0) {
        // Group records by rodal for batch validation
        const recordsByRodal = integrityResult.validRecords.reduce((acc, record) => {
          if (!acc[record.rodalId]) {
            acc[record.rodalId] = [];
          }
          acc[record.rodalId].push(record);
          return acc;
        }, {});

        // Validate each batch
        const batchValidations = {};
        for (const [rodalId, rodalRecords] of Object.entries(recordsByRodal)) {
          const batch = { rodalId: parseInt(rodalId), records: rodalRecords };
          batchValidations[rodalId] = validateBatchConsistency(batch);
        }

        integrityResult.batchValidations = batchValidations;
      }
      
      setValidationResult(integrityResult);
      return integrityResult;
      
    } catch (error) {
      console.error('Sync validation error:', error);
      const errorResult = {
        isValid: false,
        errors: ['Error en la validación de sincronización'],
        warnings: [],
        validRecords: [],
        invalidRecords: records || [],
        summary: {
          total: records?.length || 0,
          valid: 0,
          invalid: records?.length || 0,
          warningsCount: 0
        }
      };
      setValidationResult(errorResult);
      return errorResult;
    } finally {
      setIsValidating(false);
    }
  }, []);

  const resetValidation = useCallback(() => {
    setValidationResult(null);
    setIsValidating(false);
  }, []);

  return {
    validationResult,
    isValidating,
    validateSyncData,
    resetValidation
  };
};

export default useValidation;