/**
 * MultilineInput Component
 *
 * Expandable textarea cell for long text content.
 * Includes AI suggestion display when available.
 * Memoized to prevent unnecessary re-renders when parent table updates.
 */

import { useState, useCallback, useRef, useEffect, memo } from 'react';
import { Textarea } from '@/components/ui/textarea';
import { cn } from '@/lib/utils';
import { Popover, PopoverTrigger, PopoverContent } from '@/components/ui/popover';
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from '@/components/ui/tooltip';
import { X, Loader2, Sparkles } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { AiDescriptionCompare } from '@/components/ai/AiDescriptionCompare';
import type { Field, SelectOption } from '../../../../types';
import type { ValidationError } from '../../store/types';
import { useValidationStore } from '../../store/validationStore';

/** Time window (ms) during which other cells should not open after a popover closes */
const POPOVER_CLOSE_DELAY = 150;

/** AI suggestion data for a single field */
interface AiFieldSuggestion {
  isValid: boolean;
  suggestion?: string | null;
  issues?: string[];
}

interface MultilineInputProps {
  value: unknown;
  field: Field<string>;
  options?: SelectOption[];
  rowIndex: number;
  productIndex: string;
  isValidating: boolean;
  errors: ValidationError[];
  onChange: (value: unknown) => void;
  onBlur: (value: unknown) => void;
  onFetchOptions?: () => void;
  isLoadingOptions?: boolean;
  /** AI suggestion for this field */
  aiSuggestion?: AiFieldSuggestion | null;
  /** Whether AI is currently validating */
  isAiValidating?: boolean;
  /** Called when user dismisses/clears the AI suggestion (also called after applying) */
  onDismissAiSuggestion?: () => void;
  /** Called to manually trigger AI re-validation */
  onRevalidate?: () => void;
}

const MultilineInputComponent = ({
  field,
  value,
  productIndex,
  isValidating,
  errors,
  onChange: _onChange, // Unused - onBlur handles both update and validation
  onBlur,
  aiSuggestion,
  isAiValidating,
  onDismissAiSuggestion,
  onRevalidate,
}: MultilineInputProps) => {
  const [popoverOpen, setPopoverOpen] = useState(false);
  const [editValue, setEditValue] = useState('');
  const [localDisplayValue, setLocalDisplayValue] = useState<string | null>(null);
  const [popoverWidth, setPopoverWidth] = useState(400);
  const [popoverHeight, setPopoverHeight] = useState<number | undefined>(undefined);
  const resizeContainerRef = useRef<HTMLDivElement>(null);
  const cellRef = useRef<HTMLDivElement>(null);
  const preventReopenRef = useRef(false);
  // Tracks intentional closes (close button, accept/dismiss) vs click-outside closes
  const intentionalCloseRef = useRef(false);
  const mainTextareaRef = useRef<HTMLTextAreaElement>(null);
  // Tracks the value when popover opened, to detect actual changes
  const initialEditValueRef = useRef('');

  // Get the product name for this row from the store
  const productName = useValidationStore(
    (s) => s.rows.find((row) => row.__index === productIndex)?.name as string | undefined
  );

  // Get store state and actions for coordinating popover close behavior across cells
  const cellPopoverClosedAt = useValidationStore((s) => s.cellPopoverClosedAt);
  const setCellPopoverClosed = useValidationStore((s) => s.setCellPopoverClosed);

  const hasError = errors.length > 0;
  const errorMessage = errors[0]?.message;

  // Check if we have a displayable AI suggestion
  const hasAiSuggestion = aiSuggestion && !aiSuggestion.isValid && aiSuggestion.suggestion;
  const aiIssues = aiSuggestion?.issues || [];

  // Handle wheel scroll in textarea - stop propagation to prevent table scroll
  const handleTextareaWheel = useCallback((e: React.WheelEvent<HTMLTextAreaElement>) => {
    const target = e.currentTarget;
    const { scrollTop, scrollHeight, clientHeight } = target;
    const atTop = scrollTop === 0;
    const atBottom = scrollTop + clientHeight >= scrollHeight - 1;

    // Only stop propagation if we can scroll in the direction of the wheel
    if ((e.deltaY < 0 && !atTop) || (e.deltaY > 0 && !atBottom)) {
      e.stopPropagation();
    }
  }, []);

  // Initialize localDisplayValue on mount and when value changes externally
  useEffect(() => {
    const strValue = String(value ?? '');
    if (localDisplayValue === null || strValue !== localDisplayValue) {
      setLocalDisplayValue(strValue);
    }
  }, [value, localDisplayValue]);

  // Auto-resize a textarea to fit its content
  const autoResizeTextarea = useCallback((textarea: HTMLTextAreaElement | null) => {
    if (!textarea) return;
    textarea.style.height = 'auto';
    textarea.style.height = `${textarea.scrollHeight}px`;
  }, []);

  // Auto-resize main textarea when value changes or popover opens
  useEffect(() => {
    if (popoverOpen) {
      // Small delay to ensure textarea is rendered
      requestAnimationFrame(() => {
        autoResizeTextarea(mainTextareaRef.current);
      });
    }
  }, [popoverOpen, editValue, autoResizeTextarea]);

  // Set initial popover height to fit the textarea content, capped by window height.
  // Only applies on desktop (lg breakpoint) and non-AI mode (AI mode uses AiDescriptionCompare's own sizing).
  useEffect(() => {
    if (!popoverOpen || hasAiSuggestion) { setPopoverHeight(undefined); return; }
    const isDesktop = window.matchMedia('(min-width: 1024px)').matches;
    if (!isDesktop) { setPopoverHeight(undefined); return; }
    const rafId = requestAnimationFrame(() => {
      const main = mainTextareaRef.current;
      const container = resizeContainerRef.current;
      if (!container) return;

      const mainScrollH = main ? main.scrollHeight : 0;
      const leftChrome = main ? (main.closest('[data-col="left"]')?.scrollHeight ?? 0) - main.offsetHeight : 0;

      const naturalHeight = leftChrome + mainScrollH;
      const maxHeight = Math.floor(window.innerHeight * 0.7);
      setPopoverHeight(Math.max(Math.min(naturalHeight, maxHeight), 200));
    });
    return () => cancelAnimationFrame(rafId);
  }, [popoverOpen, hasAiSuggestion]);

  // Check if another cell's popover was recently closed (prevents immediate focus on click-outside)
  const wasPopoverRecentlyClosed = useCallback(() => {
    return Date.now() - cellPopoverClosedAt < POPOVER_CLOSE_DELAY;
  }, [cellPopoverClosedAt]);

  // Calculate and set popover width based on cell width
  const updatePopoverWidth = useCallback(() => {
    if (cellRef.current) {
      setPopoverWidth(Math.max(cellRef.current.offsetWidth, 200));
    }
  }, []);

  // Handle trigger click to toggle the popover
  const handleTriggerClick = useCallback(
    (e: React.MouseEvent) => {
      if (preventReopenRef.current) {
        e.preventDefault();
        e.stopPropagation();
        preventReopenRef.current = false;
        return;
      }
      
      // Block opening if another popover was just closed
      if (wasPopoverRecentlyClosed()) {
        e.preventDefault();
        e.stopPropagation();
        return;
      }

      // Only process if not already open
      if (!popoverOpen) {
        updatePopoverWidth();
        setPopoverOpen(true);
        // Initialize edit value from the current display and track it for change detection
        const initValue = localDisplayValue || String(value ?? '');
        setEditValue(initValue);
        initialEditValueRef.current = initValue;
      }
    },
    [popoverOpen, value, localDisplayValue, wasPopoverRecentlyClosed, updatePopoverWidth]
  );

  // Handle immediate close of popover (used by close button and actions - intentional closes)
  const handleClosePopover = useCallback(() => {
    // Only process if the user actually changed the value
    if (editValue !== initialEditValueRef.current) {
      // Update local display immediately
      setLocalDisplayValue(editValue);

      // onBlur handles both cell update and validation (don't call onChange first
      // as it would update the store before onBlur can capture previousValue)
      onBlur(editValue);
    }

    // Mark this as an intentional close (not click-outside)
    intentionalCloseRef.current = true;

    // Immediately close popover
    setPopoverOpen(false);

    // Prevent reopening this same cell
    preventReopenRef.current = true;
    setTimeout(() => {
      preventReopenRef.current = false;
    }, 100);
  }, [editValue, onBlur]);

  // Handle popover open/close (called by Radix for click-outside and escape key)
  const handlePopoverOpenChange = useCallback(
    (open: boolean) => {
      if (!open && popoverOpen) {
        // Check if this was an intentional close (via close button or actions)
        const wasIntentional = intentionalCloseRef.current;
        intentionalCloseRef.current = false; // Reset for next time

        if (wasIntentional) {
          // Intentional close already handled by handleClosePopover
          return;
        }

        // This is a click-outside close - only save if user actually changed the value
        if (editValue !== initialEditValueRef.current) {
          setLocalDisplayValue(editValue);
          // onBlur handles both cell update and validation
          onBlur(editValue);
        }

        setPopoverOpen(false);

        // Signal to other cells that a popover just closed via click-outside
        setCellPopoverClosed();

        preventReopenRef.current = true;
        setTimeout(() => {
          preventReopenRef.current = false;
        }, 100);
      } else if (open && !popoverOpen) {
        // Block opening if another popover was just closed
        if (wasPopoverRecentlyClosed()) {
          return;
        }
        updatePopoverWidth();
        // Initialize edit value and track it for change detection
        const initValue = localDisplayValue || String(value ?? '');
        setEditValue(initValue);
        initialEditValueRef.current = initValue;
        setPopoverOpen(true);
      }
    },
    [popoverOpen, localDisplayValue, wasPopoverRecentlyClosed, editValue, onBlur, setCellPopoverClosed, updatePopoverWidth, value]
  );

  // Handle direct input change
  const handleChange = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {
    setEditValue(e.target.value);
    autoResizeTextarea(e.target);
  }, [autoResizeTextarea]);

  // Handle accepting the AI suggestion (possibly edited) via AiDescriptionCompare
  const handleAcceptSuggestion = useCallback((text: string) => {
    setEditValue(text);
    setLocalDisplayValue(text);
    onBlur(text);
    onDismissAiSuggestion?.();
    intentionalCloseRef.current = true;
    setPopoverOpen(false);
  }, [onBlur, onDismissAiSuggestion]);

  // Handle dismissing the AI suggestion via AiDescriptionCompare
  const handleDismissSuggestion = useCallback(() => {
    onDismissAiSuggestion?.();
    intentionalCloseRef.current = true;
    setPopoverOpen(false);
  }, [onDismissAiSuggestion]);

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

  // Tooltip content - show full description or error message
  const tooltipContent = errorMessage || displayValue;
  const showTooltip = tooltipContent && tooltipContent.length > 30;

  return (
    <div className="w-full relative" ref={cellRef}>
      <Popover open={popoverOpen} onOpenChange={handlePopoverOpenChange} modal>
        <TooltipProvider>
          <Tooltip delayDuration={300}>
            <TooltipTrigger asChild>
              <PopoverTrigger asChild>
                <div
                  onClick={handleTriggerClick}
                  className={cn(
                    'pl-2 pr-4 py-1 rounded-md text-sm w-full cursor-pointer relative',
                    'overflow-hidden leading-tight h-[65px] top-0',
                    'border',
                    hasError ? 'border-destructive bg-destructive/5' : 'border-input',
                    hasAiSuggestion && !hasError && 'border-purple-300 bg-purple-50/50 dark:border-purple-700 dark:bg-purple-950/20',
                    isValidating && 'opacity-50'
                  )}
                >
                  {displayValue}
                  {/* AI suggestion indicator - small badge in corner, clickable to open with AI expanded */}
                  {hasAiSuggestion && !popoverOpen && (
                    <button
                      type="button"
                      onClick={(e) => {
                        e.stopPropagation();
                        // Block opening if another popover was just closed
                        if (wasPopoverRecentlyClosed()) {
                          return;
                        }
                        updatePopoverWidth();
                        setPopoverOpen(true);
                        // Initialize edit value and track it for change detection
                        const initValue = localDisplayValue || String(value ?? '');
                        setEditValue(initValue);
                        initialEditValueRef.current = initValue;
                      }}
                      className="absolute bottom-1 right-1 flex items-center gap-1 px-1.5 py-0.5 rounded bg-purple-100 hover:bg-purple-200 dark:bg-purple-900/50 dark:hover:bg-purple-800/50 text-purple-600 dark:text-purple-400 text-xs transition-colors"
                      title="View AI suggestion"
                    >
                      <Sparkles className="h-3 w-3" />
                      <span>{aiIssues.length}</span>
                    </button>
                  )}
                  {/* AI validating indicator */}
                  {isAiValidating && (
                    <div className="absolute bottom-1 right-1 flex items-center gap-1 px-1.5 py-0.5 rounded bg-purple-100 dark:bg-purple-900/50">
                      <Loader2 className="h-3 w-3 animate-spin text-purple-500" />
                    </div>
                  )}
                </div>
              </PopoverTrigger>
            </TooltipTrigger>
            {showTooltip && !popoverOpen && (
              <TooltipContent
                side="top"
                align="start"
                className="max-w-[400px] whitespace-pre-wrap"
              >
                <p>{tooltipContent}</p>
              </TooltipContent>
            )}
          </Tooltip>
        </TooltipProvider>
        <PopoverContent
          className="p-0 shadow-lg rounded-md max-lg:!w-[95vw]"
          style={{ width: hasAiSuggestion ? popoverWidth * 2 : popoverWidth }}
          align="start"
          side="bottom"
          alignOffset={0}
          sideOffset={-65}
          ref={(node) => {
            // Override Radix popper positioning to center on screen when AI suggestion is showing
            if (node && hasAiSuggestion) {
              const wrapper = node.parentElement;
              if (wrapper?.hasAttribute('data-radix-popper-content-wrapper')) {
                wrapper.style.position = 'fixed';
                wrapper.style.top = '50%';
                wrapper.style.left = '50%';
                wrapper.style.transform = 'translate(-50%, -50%)';
              }
            }
          }}
        >
          <div
            ref={resizeContainerRef}
            className={cn(
              "flex flex-col lg:flex-row items-stretch max-h-[85vh]",
              hasAiSuggestion
                ? "overflow-y-auto lg:overflow-hidden"
                : "lg:resize-y lg:overflow-auto lg:min-h-[120px] overflow-y-auto lg:max-h-none"
            )}
            style={popoverHeight ? { height: popoverHeight } : undefined}
          >
            {/* Close button */}
            <Button
              size="icon"
              variant="ghost"
              onClick={handleClosePopover}
              className="h-6 w-6 text-muted-foreground absolute top-0.5 right-0.5 z-10"
            >
              <X className="h-3 w-3" />
            </Button>

            {hasAiSuggestion ? (
              <AiDescriptionCompare
                currentValue={editValue}
                onCurrentChange={setEditValue}
                suggestion={aiSuggestion.suggestion!}
                issues={aiIssues}
                productName={productName}
                onAccept={handleAcceptSuggestion}
                onDismiss={handleDismissSuggestion}
                onRevalidate={onRevalidate}
                isRevalidating={isAiValidating}
              />
            ) : (
              <div data-col="left" className="flex flex-col min-h-0 w-full">
                <Textarea
                  ref={mainTextareaRef}
                  value={editValue}
                  onChange={handleChange}
                  onWheel={handleTextareaWheel}
                  className="overflow-y-auto overscroll-contain text-sm lg:flex-1 resize-y lg:resize-none bg-white min-h-[120px] lg:min-h-0"
                  placeholder={`Enter ${field.label || 'text'}...`}
                  autoFocus
                />
              </div>
            )}
          </div>
        </PopoverContent>
      </Popover>
      {isValidating && (
        <div className="absolute right-2 top-1/2 -translate-y-1/2">
          <Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />
        </div>
      )}
    </div>
  );
};

// Memoize to prevent re-renders when parent table state changes
export const MultilineInput = memo(MultilineInputComponent);
