import React, { useState, useCallback, useRef, useEffect } from 'react'
import { Field } from '../../../../types'
import { Textarea } from '@/components/ui/textarea'
import { cn } from '@/lib/utils'
import { Popover, PopoverTrigger, PopoverContent } from '@/components/ui/popover'
import { X } from 'lucide-react'
import { Button } from '@/components/ui/button'

interface MultilineInputProps<T extends string> {
  field: Field<T>
  value: any
  onChange: (value: any) => void
  hasErrors?: boolean
  disabled?: boolean
  className?: string
}

const MultilineInput = <T extends string>({
  field,
  value,
  onChange,
  hasErrors = false,
  disabled = false,
  className = ''
}: MultilineInputProps<T>) => {
  const [popoverOpen, setPopoverOpen] = useState(false);
  const [editValue, setEditValue] = useState('');
  const [localDisplayValue, setLocalDisplayValue] = useState<string | null>(null);
  const cellRef = useRef<HTMLDivElement>(null);
  const preventReopenRef = useRef(false);
  const pendingChangeRef = useRef<string | null>(null);
  
  // Add state for hover
  const [isHovered, setIsHovered] = useState(false);
  
  // Helper function to check if a class is present in the className string
  const hasClass = (cls: string): boolean => {
    const classNames = (className || '').split(' ');
    return classNames.includes(cls);
  };
  
  // Initialize localDisplayValue on mount and when value changes externally
  useEffect(() => {
    if (localDisplayValue === null || 
        (typeof value === 'string' && typeof localDisplayValue === 'string' && 
         value.trim() !== localDisplayValue.trim())) {
      setLocalDisplayValue(value);
    }
  }, [value, localDisplayValue]);
  
  // Process any pending changes in the background
  useEffect(() => {
    if (pendingChangeRef.current !== null && !popoverOpen) {
      const newValue = pendingChangeRef.current;
      pendingChangeRef.current = null;
      // Apply changes after the popover is closed
      if (newValue !== value) {
        onChange(newValue);
      }
    }
  }, [popoverOpen, onChange, value]);

  // Handle trigger click to toggle the popover
  const handleTriggerClick = useCallback((e: React.MouseEvent) => {
    if (preventReopenRef.current) {
      e.preventDefault();
      e.stopPropagation();
      preventReopenRef.current = false;
      return;
    }
    
    // Only process if not already open
    if (!popoverOpen) {
      setPopoverOpen(true);
      // Initialize edit value from the current display
      setEditValue(localDisplayValue || value || '');
    }
  }, [popoverOpen, value, localDisplayValue]);

  // Handle immediate close of popover
  const handleClosePopover = useCallback(() => {
    // Only process if we have changes
    if (editValue !== value || editValue !== localDisplayValue) {
      // Store pending changes for async processing
      pendingChangeRef.current = editValue;
      
      // Update local display immediately 
      setLocalDisplayValue(editValue);
      
      // Queue up the change to be processed in the background
      setTimeout(() => {
        onChange(editValue);
      }, 0);
    }
    
    // Immediately close popover
    setPopoverOpen(false);
    
    // Prevent reopening
    preventReopenRef.current = true;
    setTimeout(() => {
      preventReopenRef.current = false;
    }, 100);
  }, [editValue, value, localDisplayValue, onChange]);
  
  // Handle clicking outside the popover
  const handleInteractOutside = useCallback(() => {
    handleClosePopover();
  }, [handleClosePopover]);
  
  // Handle popover open/close
  const handlePopoverOpenChange = useCallback((open: boolean) => {
    if (!open && popoverOpen) {
      // Just call the close handler
      handleClosePopover();
    } else if (open && !popoverOpen) {
      // When opening, set edit value from current display
      setEditValue(localDisplayValue || value || '');
      setPopoverOpen(true);
    }
  }, [value, popoverOpen, handleClosePopover, localDisplayValue]);
  
  // Handle direct input change
  const handleChange = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {
    setEditValue(e.target.value);
  }, []);

  // Calculate display value
  const displayValue = localDisplayValue !== null ? localDisplayValue : (value ?? '');

  // Add outline even when not in focus
  const outlineClass = "border focus-visible:ring-0 focus-visible:ring-offset-0";

  // If disabled, just render the value without any interactivity
  if (disabled) {
    return (
      <div 
        className={cn(
          "px-3 py-2 min-h-[80px] max-h-[80px] rounded-md text-sm w-full",
          outlineClass,
          hasErrors ? "border-destructive" : "border-input"
        )}
        style={{
          backgroundColor: hasClass('!bg-blue-100') ? '#dbeafe' : 
                          hasClass('!bg-blue-200') ? '#bfdbfe' : 
                          hasClass('hover:!bg-blue-100') && isHovered ? '#dbeafe' :
                          undefined,
          borderColor: hasClass('!border-blue-500') ? '#3b82f6' : 
                      hasClass('!border-blue-200') ? '#bfdbfe' : 
                      hasClass('!border-blue-200') && isHovered ? '#bfdbfe' :
                      undefined,
          borderRadius: hasClass('!rounded-md') ? '0.375rem' : undefined,
          borderWidth: hasClass('!border-blue-500') || hasClass('!border-blue-200') ? '0px' : undefined,
          cursor: hasClass('hover:!bg-blue-100') ? 'pointer' : undefined
        }}
        onMouseEnter={() => setIsHovered(true)}
        onMouseLeave={() => setIsHovered(false)}
      >
        {displayValue}
      </div>
    );
  }

  return (
    <div className="w-full" ref={cellRef}>
      <Popover open={popoverOpen} onOpenChange={handlePopoverOpenChange}>
        <PopoverTrigger asChild>
          <div 
            onClick={handleTriggerClick}
            className={cn(
              "px-3 py-2 min-h-[80px] max-h-[80px] rounded-md text-sm w-full cursor-pointer",
              "overflow-hidden whitespace-pre-wrap",
              outlineClass,
              hasErrors ? "border-destructive" : "border-input",
              className
            )}
            style={{
              backgroundColor: hasClass('!bg-blue-100') ? '#dbeafe' : 
                              hasClass('!bg-blue-200') ? '#bfdbfe' : 
                              hasClass('hover:!bg-blue-100') && isHovered ? '#dbeafe' :
                              undefined,
              borderColor: hasClass('!border-blue-500') ? '#3b82f6' : 
                          hasClass('!border-blue-200') ? '#bfdbfe' : 
                          hasClass('!border-blue-200') && isHovered ? '#bfdbfe' :
                          undefined,
              borderRadius: hasClass('!rounded-md') ? '0.375rem' : undefined,
              borderWidth: hasClass('!border-blue-500') || hasClass('!border-blue-200') ? '0px' : undefined,
              cursor: hasClass('hover:!bg-blue-100') ? 'pointer' : 'pointer'
            }}
            onMouseEnter={() => setIsHovered(true)}
            onMouseLeave={() => setIsHovered(false)}
          >
            {displayValue}
          </div>
        </PopoverTrigger>
        <PopoverContent 
          className="p-0 shadow-lg rounded-md" 
          style={{ width: cellRef.current?.offsetWidth || 'auto' }}
          align="start"
          side="bottom"
          alignOffset={0}
          sideOffset={-80}
          avoidCollisions={false}
          onInteractOutside={handleInteractOutside}
          forceMount
        >
          <div className="flex flex-col">
            <Button 
              size="icon" 
              variant="ghost" 
              onClick={handleClosePopover} 
              className="h-6 w-6 text-muted-foreground absolute top-0.5 right-0.5"
            >
              <X className="h-3 w-3" />
            </Button>
          
            <Textarea
              value={editValue}
              onChange={handleChange}
              className="min-h-[200px] border-none focus-visible:ring-0 rounded-none p-2"
              placeholder={`Enter ${field.label || 'text'}...`}
              autoFocus
            />
          </div>
        </PopoverContent>
      </Popover>
    </div>
  );
};

export default React.memo(MultilineInput, (prev, next) => {
  if (prev.hasErrors !== next.hasErrors) return false;
  if (prev.disabled !== next.disabled) return false;
  if (prev.field !== next.field) return false;
  if (prev.value !== next.value) return false;
  if (prev.className !== next.className) return false;
  return true;
}); 