import { useState, useRef, useEffect, memo, useCallback } from 'react';
import TextareaAutosize from 'react-textarea-autosize';
import { Send, Square, Command, History, Paperclip, X, Image, FileText } from 'lucide-react';

// LocalStorage key for input history
const HISTORY_KEY = 'claude-webui-input-history';
const MAX_HISTORY = 100;
const MAX_FILES = 5;
const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB

// Allowed file types
const ALLOWED_EXTENSIONS = [
  // Images
  '.png', '.jpg', '.jpeg', '.gif', '.webp',
  // Text/Code
  '.txt', '.md', '.csv', '.html', '.css', '.js', '.ts', '.jsx', '.tsx',
  '.json', '.xml', '.yaml', '.yml', '.py', '.go', '.rs', '.java', '.c',
  '.cpp', '.h', '.sh', '.bash', '.zsh', '.toml', '.ini', '.conf', '.sql',
  '.rb', '.php', '.swift', '.kt', '.scala', '.r', '.lua', '.pl', '.pm'
];

// Load history from localStorage
function loadHistory() {
  try {
    const stored = localStorage.getItem(HISTORY_KEY);
    return stored ? JSON.parse(stored) : [];
  } catch {
    return [];
  }
}

// Save history to localStorage
function saveHistory(history) {
  try {
    localStorage.setItem(HISTORY_KEY, JSON.stringify(history.slice(0, MAX_HISTORY)));
  } catch {}
}

// Available slash commands for autocomplete
const COMMANDS = [
  { name: 'compact', description: 'Compact context (summarize conversation)' },
  { name: 'help', description: 'Show available commands' },
  { name: 'clear', description: 'Clear chat history' },
  { name: 'export', description: 'Export chat as Markdown' },
  { name: 'scroll', description: 'Scroll to top or bottom' },
  { name: 'new', description: 'Start a new session' },
  { name: 'info', description: 'Show session info' },
  { name: 'history', description: 'Search input history (/history <term>)' },
];

export const ChatInput = memo(function ChatInput({ onSend, onStop, disabled, isProcessing, placeholder, sessionId }) {
  // Use uncontrolled input for performance - no React re-render on every keystroke
  const textareaRef = useRef(null);
  const fileInputRef = useRef(null);

  // These states don't change on every keystroke, so they're fine
  const [showCommands, setShowCommands] = useState(false);
  const [selectedIndex, setSelectedIndex] = useState(0);
  const [filteredCommands, setFilteredCommands] = useState(COMMANDS);
  const [inputHistory] = useState(() => loadHistory());
  const [historyIndex, setHistoryIndex] = useState(-1);
  const [savedInput, setSavedInput] = useState('');
  const [attachedFiles, setAttachedFiles] = useState([]);
  const [isDragOver, setIsDragOver] = useState(false);
  const [uploadError, setUploadError] = useState(null);

  // Add message to history
  const addToHistory = useCallback((msg) => {
    const trimmed = msg.trim();
    if (!trimmed) return;

    const history = loadHistory();
    const filtered = history.filter(h => h !== trimmed);
    const newHistory = [trimmed, ...filtered].slice(0, MAX_HISTORY);
    saveHistory(newHistory);
  }, []);

  // Validate file
  const validateFile = useCallback((file) => {
    const ext = '.' + file.name.split('.').pop().toLowerCase();
    if (!ALLOWED_EXTENSIONS.includes(ext) && !file.type.startsWith('image/')) {
      return `File type not allowed: ${ext}`;
    }
    if (file.size > MAX_FILE_SIZE) {
      return `File too large: ${(file.size / 1024 / 1024).toFixed(1)}MB (max 10MB)`;
    }
    return null;
  }, []);

  // Process and add files
  const processFiles = useCallback((files) => {
    setUploadError(null);
    const fileArray = Array.from(files);
    const remaining = MAX_FILES - attachedFiles.length;

    if (fileArray.length > remaining) {
      setUploadError(`Only ${remaining} more file(s) can be added (max ${MAX_FILES})`);
      return;
    }

    const newFiles = [];
    for (const file of fileArray) {
      const error = validateFile(file);
      if (error) {
        setUploadError(error);
        return;
      }

      const isImage = file.type.startsWith('image/');
      const fileData = {
        file,
        name: file.name,
        size: file.size,
        type: file.type,
        isImage,
        preview: isImage ? URL.createObjectURL(file) : null,
        id: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
      };
      newFiles.push(fileData);
    }

    setAttachedFiles(prev => [...prev, ...newFiles]);
  }, [attachedFiles.length, validateFile]);

  // Remove attached file
  const removeFile = useCallback((id) => {
    setAttachedFiles(prev => {
      const file = prev.find(f => f.id === id);
      if (file?.preview) {
        URL.revokeObjectURL(file.preview);
      }
      return prev.filter(f => f.id !== id);
    });
  }, []);

  // Handle paste event
  const handlePaste = useCallback((e) => {
    const items = e.clipboardData?.items;
    if (!items) return;

    const files = [];
    for (const item of items) {
      if (item.kind === 'file') {
        const file = item.getAsFile();
        if (file) files.push(file);
      }
    }

    if (files.length > 0) {
      e.preventDefault();
      processFiles(files);
    }
  }, [processFiles]);

  // Handle drag and drop
  const handleDragOver = useCallback((e) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragOver(true);
  }, []);

  const handleDragLeave = useCallback((e) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragOver(false);
  }, []);

  const handleDrop = useCallback((e) => {
    e.preventDefault();
    e.stopPropagation();
    setIsDragOver(false);

    const files = e.dataTransfer?.files;
    if (files && files.length > 0) {
      processFiles(files);
    }
  }, [processFiles]);

  // Handle file input change
  const handleFileSelect = useCallback((e) => {
    const files = e.target.files;
    if (files && files.length > 0) {
      processFiles(files);
    }
    e.target.value = '';
  }, [processFiles]);

  // Cleanup previews on unmount
  useEffect(() => {
    return () => {
      attachedFiles.forEach(f => {
        if (f.preview) URL.revokeObjectURL(f.preview);
      });
    };
  }, []);

  // Get current message from textarea (uncontrolled)
  const getMessage = () => textareaRef.current?.value || '';
  const setMessage = (val) => {
    if (textareaRef.current) {
      textareaRef.current.value = val;
    }
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    const message = getMessage();
    if (message.trim() || attachedFiles.length > 0) {
      addToHistory(message);
      onSend(message, attachedFiles);
      setMessage('');
      setAttachedFiles([]);
      setShowCommands(false);
      setHistoryIndex(-1);
      setSavedInput('');
      setUploadError(null);
      // Reset textarea height
      if (textareaRef.current) {
        textareaRef.current.style.height = 'auto';
      }
    }
  };

  const selectCommand = (cmdName) => {
    setMessage(`/${cmdName} `);
    setShowCommands(false);
    textareaRef.current?.focus();
  };


  const handleKeyDown = (e) => {
    // ESC to stop generation
    if (e.key === 'Escape') {
      if (isProcessing && onStop) {
        e.preventDefault();
        onStop();
        return;
      }
      if (showCommands) {
        setShowCommands(false);
        return;
      }
    }

    // Handle command selection
    if (showCommands) {
      if (e.key === 'ArrowDown') {
        e.preventDefault();
        setSelectedIndex(i => Math.min(i + 1, filteredCommands.length - 1));
        return;
      }
      if (e.key === 'ArrowUp') {
        e.preventDefault();
        setSelectedIndex(i => Math.max(i - 1, 0));
        return;
      }
      if (e.key === 'Tab' || (e.key === 'Enter' && filteredCommands.length > 0)) {
        e.preventDefault();
        selectCommand(filteredCommands[selectedIndex].name);
        return;
      }
    }

    // Arrow up/down for history navigation
    if (!showCommands && inputHistory.length > 0) {
      const message = getMessage();
      if (e.key === 'ArrowUp') {
        const textarea = textareaRef.current;
        if (textarea && (textarea.selectionStart === 0 || message === '')) {
          e.preventDefault();
          if (historyIndex === -1) {
            setSavedInput(message);
          }
          const newIndex = Math.min(historyIndex + 1, inputHistory.length - 1);
          setHistoryIndex(newIndex);
          setMessage(inputHistory[newIndex]);
          return;
        }
      }
      if (e.key === 'ArrowDown' && historyIndex >= 0) {
        e.preventDefault();
        const newIndex = historyIndex - 1;
        setHistoryIndex(newIndex);
        if (newIndex === -1) {
          setMessage(savedInput);
        } else {
          setMessage(inputHistory[newIndex]);
        }
        return;
      }
    }

    if (e.key === 'Enter' && !e.shiftKey) {
      e.preventDefault();
      handleSubmit(e);
    }
  };

  // Handle input changes for slash command detection (lightweight, no state updates for value)
  const handleInput = useCallback(() => {
    const value = textareaRef.current?.value || '';

    // Show command menu when typing "/" at the start
    if (value.startsWith('/')) {
      const query = value.slice(1).toLowerCase();
      const filtered = COMMANDS.filter(cmd =>
        cmd.name.toLowerCase().includes(query)
      );
      setFilteredCommands(filtered);
      setShowCommands(filtered.length > 0);
      setSelectedIndex(0);
    } else {
      setShowCommands(false);
    }
  }, []);

  return (
    <form
      onSubmit={handleSubmit}
      onDragOver={handleDragOver}
      onDragLeave={handleDragLeave}
      onDrop={handleDrop}
      className={`p-4 border-t border-dark-800 bg-dark-900 transition-colors ${isDragOver ? 'bg-orange-900/20 border-orange-500/50' : ''}`}
    >
      {/* Drag overlay */}
      {isDragOver && (
        <div className="absolute inset-0 bg-orange-900/30 border-2 border-dashed border-orange-500 rounded-lg flex items-center justify-center z-20 pointer-events-none">
          <div className="text-orange-400 text-lg font-medium">Drop files here</div>
        </div>
      )}

      {/* Upload error */}
      {uploadError && (
        <div className="max-w-4xl mx-auto mb-2 px-3 py-2 bg-red-900/30 border border-red-700 rounded-lg text-red-400 text-sm flex justify-between items-center">
          <span>{uploadError}</span>
          <button type="button" onClick={() => setUploadError(null)} className="text-red-500 hover:text-red-400">
            <X className="w-4 h-4" />
          </button>
        </div>
      )}

      {/* Attached files preview */}
      {attachedFiles.length > 0 && (
        <div className="max-w-4xl mx-auto mb-3 flex gap-2 flex-wrap">
          {attachedFiles.map((file) => (
            <div
              key={file.id}
              className="relative group bg-dark-800 border border-dark-700 rounded-lg overflow-hidden"
            >
              {file.isImage ? (
                <div className="w-16 h-16 relative">
                  <img
                    src={file.preview}
                    alt={file.name}
                    className="w-full h-full object-cover"
                  />
                  <div className="absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center">
                    <button
                      type="button"
                      onClick={() => removeFile(file.id)}
                      className="p-1 bg-red-600 rounded-full text-white hover:bg-red-500"
                    >
                      <X className="w-3 h-3" />
                    </button>
                  </div>
                </div>
              ) : (
                <div className="px-3 py-2 flex items-center gap-2 max-w-48">
                  <FileText className="w-4 h-4 text-dark-400 flex-shrink-0" />
                  <span className="text-dark-300 text-xs truncate">{file.name}</span>
                  <button
                    type="button"
                    onClick={() => removeFile(file.id)}
                    className="p-0.5 text-dark-500 hover:text-red-400 flex-shrink-0"
                  >
                    <X className="w-3 h-3" />
                  </button>
                </div>
              )}
            </div>
          ))}
          {attachedFiles.length < MAX_FILES && (
            <button
              type="button"
              onClick={() => fileInputRef.current?.click()}
              className="w-16 h-16 border border-dashed border-dark-600 rounded-lg flex items-center justify-center text-dark-500 hover:text-dark-400 hover:border-dark-500 transition-colors"
              title="Add more files"
            >
              <Paperclip className="w-5 h-5" />
            </button>
          )}
        </div>
      )}

      <div className="flex gap-3 items-end max-w-4xl mx-auto">
        {/* File input (hidden) */}
        <input
          ref={fileInputRef}
          type="file"
          multiple
          accept={ALLOWED_EXTENSIONS.join(',')}
          onChange={handleFileSelect}
          className="hidden"
        />

        {/* Attach button */}
        <button
          type="button"
          onClick={() => fileInputRef.current?.click()}
          disabled={disabled || attachedFiles.length >= MAX_FILES}
          className={`p-3 rounded-xl transition-all ${
            disabled || attachedFiles.length >= MAX_FILES
              ? 'bg-dark-800 text-dark-600 cursor-not-allowed'
              : 'bg-dark-800 text-dark-400 hover:text-orange-400 hover:bg-dark-700'
          }`}
          title={attachedFiles.length >= MAX_FILES ? `Max ${MAX_FILES} files` : 'Attach files (or paste/drag)'}
        >
          <Paperclip className="w-5 h-5" />
        </button>

        <div className="flex-1 relative">
          {/* Command autocomplete dropdown */}
          {showCommands && (
            <div className="absolute bottom-full left-0 right-0 mb-2 bg-dark-800 border border-dark-700 rounded-lg shadow-xl overflow-hidden z-10">
              {filteredCommands.map((cmd, index) => (
                <button
                  key={cmd.name}
                  type="button"
                  onClick={() => selectCommand(cmd.name)}
                  className={`w-full px-4 py-2.5 flex items-center gap-3 text-left transition-colors
                    ${index === selectedIndex ? 'bg-orange-600/20 text-orange-400' : 'hover:bg-dark-700 text-dark-200'}`}
                >
                  <Command className="w-4 h-4 text-dark-500" />
                  <span className="font-medium">/{cmd.name}</span>
                  <span className="text-dark-500 text-sm">{cmd.description}</span>
                </button>
              ))}
            </div>
          )}

          <TextareaAutosize
            ref={textareaRef}
            defaultValue=""
            onKeyDown={handleKeyDown}
            onInput={handleInput}
            onPaste={handlePaste}
            placeholder={isProcessing ? 'Type to send a follow-up message...' : placeholder}
            disabled={disabled}
            minRows={2}
            maxRows={8}
            cacheMeasurements
            className="w-full bg-dark-800 border border-dark-700 rounded-xl px-4 py-3 pr-12 text-dark-100 placeholder-dark-500 focus:outline-none focus:border-orange-500/50 focus:ring-1 focus:ring-orange-500/20 resize-none transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
          />
          <div className="absolute right-2 bottom-2 text-xs text-dark-600">
            {isProcessing ? 'ESC to stop' : '↑↓ history'}
          </div>
        </div>

        {isProcessing ? (
          <button
            type="button"
            onClick={onStop}
            className="p-3 rounded-xl transition-all bg-red-600 hover:bg-red-500 text-white shadow-lg shadow-red-600/20"
            title="Stop generation (ESC)"
          >
            <Square className="w-5 h-5" />
          </button>
        ) : (
          <button
            type="submit"
            disabled={disabled}
            className={`p-3 rounded-xl transition-all ${
              disabled
                ? 'bg-dark-800 text-dark-600 cursor-not-allowed'
                : 'bg-orange-600 hover:bg-orange-500 text-white shadow-lg shadow-orange-600/20'
            }`}
          >
            <Send className="w-5 h-5" />
          </button>
        )}
      </div>

      <div className="text-center mt-2 text-xs text-dark-600">
        {isProcessing ? 'Generating... Press Enter to send follow-up, ESC to stop' : 'Paste, drag & drop, or click clip to attach files'}
      </div>
    </form>
  );
});
