/**
 * Chat Input Component
 *
 * 支持响应式：responsive=true 时适配移动端键盘和触摸操作
 * 支持斜杠命令：输入 / 时显示命令菜单
 * 支持系统命令：输入 : 时显示系统命令菜单
 * 支持文件提及：输入 @ 时显示文件搜索菜单
 */

import { useState, useRef, useEffect, useCallback, useMemo } from 'react';
import { Square, Sparkles } from 'lucide-react';
import { motion } from 'framer-motion';
import clsx from 'clsx';
import { CommandMenu, type CommandMenuItem } from './CommandMenu.js';
import { SystemCommandMenu, type SystemCommandMenuItem } from './SystemCommandMenu.js';
import { FileMenu, type FileMenuItem } from './FileMenu.js';
import { FileMentionTag } from './FileMentionTag.js';
import { AgentModeSelector, type AgentModeType } from './AgentModeSelector.js';
import { useCommands } from '../hooks/useCommands.js';
import { useSystemCommands } from '../hooks/useSystemCommands.js';
import { useFileMention } from '../hooks/useFileMention.js';

interface ChatInputProps {
  onSend: (content: string) => void;
  onCancel: () => void;
  isLoading: boolean;
  disabled?: boolean;
  /** 是否启用响应式布局（移动端适配） */
  responsive?: boolean;
  /** 是否启用斜杠命令 */
  enableCommands?: boolean;
  /** 是否启用文件提及 (@) */
  enableFileMention?: boolean;
  /** Agent 模式 (build/plan) */
  agentMode?: AgentModeType;
  /** Agent 模式变更回调 */
  onAgentModeChange?: (mode: AgentModeType) => void;
  /** 是否自动授权文件写入/编辑 */
  autoApprove?: boolean;
  /** 自动授权变更回调 */
  onAutoApproveChange?: (enabled: boolean) => void;
}

export function ChatInput({
  onSend,
  onCancel,
  isLoading,
  disabled,
  responsive = false,
  enableCommands = true,
  enableFileMention = true,
  agentMode = 'build',
  onAgentModeChange,
  autoApprove = false,
  onAutoApproveChange,
}: ChatInputProps) {
  const [input, setInput] = useState('');
  const [showCommandMenu, setShowCommandMenu] = useState(false);
  const [selectedCommandIndex, setSelectedCommandIndex] = useState(0);
  const [showSystemCommandMenu, setShowSystemCommandMenu] = useState(false);
  const [selectedSystemCommandIndex, setSelectedSystemCommandIndex] = useState(0);
  const textareaRef = useRef<HTMLTextAreaElement>(null);

  // 命令系统
  const {
    filteredCommands,
    isLoading: commandsLoading,
    filterCommands,
  } = useCommands({ autoLoad: enableCommands });

  // 系统命令系统
  const {
    filteredCommands: filteredSystemCommands,
    isLoading: systemCommandsLoading,
    filterCommands: filterSystemCommands,
  } = useSystemCommands({ autoLoad: enableCommands });

  // 文件提及系统
  const {
    isOpen: showFileMenu,
    files: filteredFiles,
    isLoading: filesLoading,
    selectedIndex: fileSelectedIndex,
    setSelectedIndex: setFileSelectedIndex,
    checkTrigger: checkFileTrigger,
    getReplacementText,
    close: closeFileMenu,
    mentionStart,
  } = useFileMention({ enabled: enableFileMention });

  // 解析输入中已存在的文件提及 (匹配 @path/to/file 格式)
  const mentionedFiles = useMemo(() => {
    const regex = /@([\w./-]+)/g;
    const files: string[] = [];
    let match;
    while ((match = regex.exec(input)) !== null) {
      files.push(match[1]);
    }
    return files;
  }, [input]);

  // 移除指定的文件提及
  const handleRemoveFile = useCallback(
    (filePath: string) => {
      // 移除 @filepath 和后面的空格
      const regex = new RegExp(`@${filePath.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\s?`, 'g');
      setInput((prev) => prev.replace(regex, '').trim());
      textareaRef.current?.focus();
    },
    []
  );

  // 自动调整高度
  useEffect(() => {
    const textarea = textareaRef.current;
    if (textarea) {
      textarea.style.height = 'auto';
      // 响应式模式下移动端最大高度稍小
      const maxHeight = responsive && window.innerWidth < 768 ? 120 : 200;
      textarea.style.height = `${Math.min(textarea.scrollHeight, maxHeight)}px`;
    }
  }, [input, responsive]);

  // 检测斜杠命令输入
  const checkCommandTrigger = useCallback(
    (value: string) => {
      if (!enableCommands) return;

      // 检测是否在输入斜杠命令
      // 条件：以 / 开头，且 / 后面没有空格（还在输入命令名）
      const slashMatch = value.match(/^\/(\S*)$/);

      if (slashMatch) {
        const query = slashMatch[1]; // / 后面的内容
        setShowCommandMenu(true);
        setSelectedCommandIndex(0);
        filterCommands(query);
      } else {
        setShowCommandMenu(false);
      }
    },
    [enableCommands, filterCommands]
  );

  // 检测系统命令输入
  const checkSystemCommandTrigger = useCallback(
    (value: string) => {
      if (!enableCommands) return;

      // 检测是否在输入系统命令
      // 条件：以 : 开头，且 : 后面没有空格（还在输入命令名）
      const colonMatch = value.match(/^:(\S*)$/);

      if (colonMatch) {
        const query = colonMatch[1]; // : 后面的内容
        setShowSystemCommandMenu(true);
        setSelectedSystemCommandIndex(0);
        filterSystemCommands(query);
      } else {
        setShowSystemCommandMenu(false);
      }
    },
    [enableCommands, filterSystemCommands]
  );

  // 处理输入变化
  const handleInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
    const value = e.target.value;
    const cursorPos = e.target.selectionStart;
    setInput(value);

    // 检查斜杠命令触发
    checkCommandTrigger(value);

    // 检查系统命令触发
    checkSystemCommandTrigger(value);

    // 检查文件提及触发（只在非命令输入模式下）
    if (enableFileMention && !value.startsWith('/') && !value.startsWith(':')) {
      checkFileTrigger(value, cursorPos);
    } else {
      closeFileMenu();
    }
  };

  // 选择命令
  const handleCommandSelect = useCallback((command: CommandMenuItem) => {
    // 替换输入内容为 /command + 空格，准备输入参数
    setInput(`/${command.name} `);
    setShowCommandMenu(false);

    // 聚焦输入框
    textareaRef.current?.focus();
  }, []);

  // 选择文件
  const handleFileSelect = useCallback(
    (file: FileMenuItem) => {
      if (mentionStart === null) return;

      // 获取当前光标位置
      const cursorPos = textareaRef.current?.selectionStart || input.length;

      // 替换 @ 到光标之间的内容
      const before = input.slice(0, mentionStart);
      const after = input.slice(cursorPos);
      const replacement = getReplacementText(file);

      const newInput = before + replacement + after;
      setInput(newInput);
      closeFileMenu();

      // 聚焦输入框并设置光标位置
      setTimeout(() => {
        textareaRef.current?.focus();
        const newPos = before.length + replacement.length;
        textareaRef.current?.setSelectionRange(newPos, newPos);
      }, 0);
    },
    [input, mentionStart, getReplacementText, closeFileMenu]
  );

  // 关闭命令菜单
  const handleCommandMenuClose = useCallback(() => {
    setShowCommandMenu(false);
  }, []);

  // 选择系统命令
  const handleSystemCommandSelect = useCallback((command: SystemCommandMenuItem) => {
    // 直接发送系统命令
    setInput(`:${command.name}`);
    setShowSystemCommandMenu(false);

    // 聚焦输入框
    textareaRef.current?.focus();
  }, []);

  // 关闭系统命令菜单
  const handleSystemCommandMenuClose = useCallback(() => {
    setShowSystemCommandMenu(false);
  }, []);

  const handleSubmit = () => {
    const trimmed = input.trim();
    if (!trimmed || isLoading || disabled) return;

    // 关闭所有菜单
    setShowCommandMenu(false);
    setShowSystemCommandMenu(false);
    closeFileMenu();

    onSend(trimmed);
    setInput('');

    // 重置高度
    if (textareaRef.current) {
      textareaRef.current.style.height = 'auto';
    }
  };

  const handleKeyDown = (e: React.KeyboardEvent) => {
    // 文件菜单优先处理（因为可以在任意位置触发）
    if (showFileMenu && filteredFiles.length > 0) {
      if (['ArrowUp', 'ArrowDown', 'Tab', 'Escape'].includes(e.key)) {
        // 这些键由 FileMenu 处理
        return;
      }
      if (e.key === 'Enter' && !e.shiftKey) {
        e.preventDefault();
        if (filteredFiles[fileSelectedIndex]) {
          handleFileSelect(filteredFiles[fileSelectedIndex]);
        }
        return;
      }
    }

    // 斜杠命令菜单处理
    if (showCommandMenu && filteredCommands.length > 0) {
      if (['ArrowUp', 'ArrowDown', 'Tab', 'Escape'].includes(e.key)) {
        // 这些键由 CommandMenu 处理，阻止默认行为
        return;
      }
      if (e.key === 'Enter' && !e.shiftKey) {
        // Enter 选择命令
        e.preventDefault();
        if (filteredCommands[selectedCommandIndex]) {
          handleCommandSelect(filteredCommands[selectedCommandIndex]);
        }
        return;
      }
    }

    // 系统命令菜单处理
    if (showSystemCommandMenu && filteredSystemCommands.length > 0) {
      if (['ArrowUp', 'ArrowDown', 'Tab', 'Escape'].includes(e.key)) {
        // 这些键由 SystemCommandMenu 处理，阻止默认行为
        return;
      }
      if (e.key === 'Enter' && !e.shiftKey) {
        // Enter 选择系统命令
        e.preventDefault();
        if (filteredSystemCommands[selectedSystemCommandIndex]) {
          handleSystemCommandSelect(filteredSystemCommands[selectedSystemCommandIndex]);
        }
        return;
      }
    }

    // Enter 发送，Shift+Enter 换行
    if (e.key === 'Enter' && !e.shiftKey) {
      e.preventDefault();
      handleSubmit();
    }
  };

  return (
    <div
      className={clsx(
        'bg-surface-base relative',
        responsive ? 'p-3 md:p-4 safe-area-pb' : 'p-4'
      )}
    >
      {/* Command Menu (斜杠命令) */}
      {enableCommands && (
        <CommandMenu
          commands={filteredCommands}
          isOpen={showCommandMenu}
          selectedIndex={selectedCommandIndex}
          onSelect={handleCommandSelect}
          onClose={handleCommandMenuClose}
          onSelectedIndexChange={setSelectedCommandIndex}
          isLoading={commandsLoading}
        />
      )}

      {/* System Command Menu (系统命令) */}
      {enableCommands && (
        <SystemCommandMenu
          commands={filteredSystemCommands}
          isOpen={showSystemCommandMenu}
          selectedIndex={selectedSystemCommandIndex}
          onSelect={handleSystemCommandSelect}
          onClose={handleSystemCommandMenuClose}
          onSelectedIndexChange={setSelectedSystemCommandIndex}
          isLoading={systemCommandsLoading}
        />
      )}

      {/* File Menu */}
      {enableFileMention && (
        <FileMenu
          files={filteredFiles}
          isOpen={showFileMenu}
          selectedIndex={fileSelectedIndex}
          onSelect={handleFileSelect}
          onClose={closeFileMenu}
          onSelectedIndexChange={setFileSelectedIndex}
          isLoading={filesLoading}
        />
      )}

      <div className="max-w-4xl mx-auto">
        {/* 主输入容器 - 现代化卡片设计 */}
        <div
          className={clsx(
            'relative rounded-2xl border transition-all duration-200',
            'bg-surface-subtle',
            disabled
              ? 'border-line opacity-60'
              : 'border-line hover:border-fg-subtle/30 focus-within:border-primary-500 focus-within:shadow-lg focus-within:shadow-primary-500/10'
          )}
        >
          {/* 已选文件标签 */}
          {mentionedFiles.length > 0 && (
            <div className="flex flex-wrap gap-1.5 px-4 pt-3">
              {mentionedFiles.map((file, index) => (
                <FileMentionTag
                  key={`${file}-${index}`}
                  path={file}
                  size="sm"
                  removable
                  onRemove={() => handleRemoveFile(file)}
                />
              ))}
            </div>
          )}

          {/* 输入区域 */}
          <div className="flex items-end gap-2 p-2">
            {/* Agent 模式选择器 */}
            {onAgentModeChange && (
              <div className="flex-shrink-0 mb-1">
                <AgentModeSelector
                  mode={agentMode}
                  onModeChange={onAgentModeChange}
                  autoApprove={autoApprove}
                  onAutoApproveChange={onAutoApproveChange ?? (() => {})}
                  disabled={disabled || isLoading}
                />
              </div>
            )}

            <div className="flex-1 relative">
              <textarea
                ref={textareaRef}
                value={input}
                onChange={handleInputChange}
                onKeyDown={handleKeyDown}
                placeholder={
                  responsive
                    ? 'Ask anything...'
                    : 'Ask anything... (Shift+Enter for new line)'
                }
                disabled={disabled}
                rows={1}
                className={clsx(
                  'w-full resize-none bg-transparent border-0',
                  responsive ? 'px-2 py-2 md:px-3 md:py-2' : 'px-3 py-2',
                  responsive ? 'text-base md:text-sm' : 'text-sm',
                  'text-fg placeholder-fg-subtle/60',
                  'focus:outline-none focus:ring-0',
                  'disabled:cursor-not-allowed'
                )}
              />
            </div>

            {/* 发送按钮 */}
            <motion.button
              whileHover={{ scale: 1.05 }}
              whileTap={{ scale: 0.95 }}
              onClick={isLoading ? onCancel : handleSubmit}
              disabled={!isLoading && (!input.trim() || disabled)}
              className={clsx(
                'flex-shrink-0 rounded-xl flex items-center justify-center transition-all duration-200',
                responsive
                  ? 'w-10 h-10 md:w-9 md:h-9'
                  : 'w-9 h-9',
                isLoading
                  ? 'bg-red-500 hover:bg-red-600 text-white shadow-lg shadow-red-500/25'
                  : input.trim() && !disabled
                    ? 'bg-gradient-to-r from-primary-500 to-primary-600 hover:from-primary-600 hover:to-primary-700 text-white shadow-lg shadow-primary-500/25'
                    : 'bg-surface-muted text-fg-subtle',
                'disabled:opacity-40 disabled:cursor-not-allowed disabled:shadow-none'
              )}
            >
              {isLoading ? (
                <Square size={18} className="fill-current" />
              ) : (
                <Sparkles size={18} className={clsx(input.trim() && !disabled && 'animate-pulse')} />
              )}
            </motion.button>
          </div>
        </div>

        {/* 底部提示 */}
        {responsive && (
          <div className="hidden md:flex items-center justify-center gap-4 mt-3 text-xs text-fg-subtle/60">
            <span className="flex items-center gap-1">
              <kbd className="px-1.5 py-0.5 rounded bg-surface-subtle text-fg-muted font-mono text-[10px]">Enter</kbd>
              <span>send</span>
            </span>
            <span className="flex items-center gap-1">
              <kbd className="px-1.5 py-0.5 rounded bg-surface-subtle text-fg-muted font-mono text-[10px]">/</kbd>
              <span>commands</span>
            </span>
            <span className="flex items-center gap-1">
              <kbd className="px-1.5 py-0.5 rounded bg-surface-subtle text-fg-muted font-mono text-[10px]">:</kbd>
              <span>system</span>
            </span>
            <span className="flex items-center gap-1">
              <kbd className="px-1.5 py-0.5 rounded bg-surface-subtle text-fg-muted font-mono text-[10px]">@</kbd>
              <span>files</span>
            </span>
          </div>
        )}
      </div>
    </div>
  );
}
