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

import { useState, useRef, useEffect, useCallback, useMemo } from 'react';
import { Send, Square } from 'lucide-react';
import clsx from 'clsx';
import { CommandMenu, type CommandMenuItem } from './CommandMenu.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 { 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 textareaRef = useRef<HTMLTextAreaElement>(null);

  // 命令系统
  const {
    filteredCommands,
    isLoading: commandsLoading,
    filterCommands,
  } = useCommands({ 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 handleInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
    const value = e.target.value;
    const cursorPos = e.target.selectionStart;
    setInput(value);

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

    // 检查文件提及触发（只在非命令输入模式下）
    if (enableFileMention && !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 handleSubmit = () => {
    const trimmed = input.trim();
    if (!trimmed || isLoading || disabled) return;

    // 关闭菜单
    setShowCommandMenu(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;
      }
    }

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

  return (
    <div
      className={clsx(
        'border-t border-line 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}
        />
      )}

      {/* 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">
        {/* 已选文件标签 */}
        {mentionedFiles.length > 0 && (
          <div className="flex flex-wrap gap-1.5 mb-2">
            {mentionedFiles.map((file, index) => (
              <FileMentionTag
                key={`${file}-${index}`}
                path={file}
                size="sm"
                removable
                onRemove={() => handleRemoveFile(file)}
              />
            ))}
          </div>
        )}

        {/* 输入区域 */}
        <div className="flex gap-2 items-end">
          {/* Agent 模式选择器 */}
          {onAgentModeChange && (
            <div className="flex-shrink-0 pb-1.5">
              <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
                  ? 'Type a message, /command, or @file...'
                  : 'Type a message, /command, or @file... (Shift+Enter for new line)'
              }
              disabled={disabled}
              rows={1}
              className={clsx(
                'w-full resize-none rounded-lg border border-line bg-surface-subtle',
                responsive ? 'px-3 py-2.5 md:px-4 md:py-3' : 'px-4 py-3',
                responsive ? 'text-base md:text-sm' : 'text-sm', // 移动端使用 16px 防止缩放
                'text-fg placeholder-fg-subtle',
                'focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent',
                'disabled:opacity-50 disabled:cursor-not-allowed'
              )}
            />
          </div>
          <button
            onClick={isLoading ? onCancel : handleSubmit}
            disabled={!isLoading && (!input.trim() || disabled)}
            className={clsx(
              'rounded-lg flex items-center justify-center transition-colors self-end',
              responsive
                ? 'px-3 py-2.5 md:px-4 md:py-3 min-w-[44px] min-h-[44px]' // 最小触摸目标 44x44
                : 'px-4 py-3',
              isLoading
                ? 'bg-red-600 hover:bg-red-700 active:bg-red-800 text-white'
                : 'bg-primary-600 hover:bg-primary-700 active:bg-primary-800 text-white',
              'disabled:opacity-50 disabled:cursor-not-allowed'
            )}
          >
            {isLoading ? <Square size={20} /> : <Send size={20} />}
          </button>
        </div>
      </div>
      {/* 响应式模式下桌面端显示提示文字 */}
      {responsive && (
        <p className="hidden md:block text-xs text-fg-subtle text-center mt-2">
          Press Enter to send, Shift+Enter for new line, / for commands, @ for files
        </p>
      )}
    </div>
  );
}
