/**
 * HookEditor Component
 *
 * 钩子编辑器：用于添加和编辑单个钩子规则
 */

import { useState } from 'react';
import {
  X,
  Plus,
  Trash2,
  Play,
  RefreshCw,
  ChevronDown,
  ChevronRight,
} from 'lucide-react';
import { motion, AnimatePresence } from 'framer-motion';
import { cn } from '../utils/cn';
import { modalOverlay, modalContent, smoothTransition } from '../utils/animations';
import { Button } from '../primitives/Button';
import type { ShellCommandConfig } from '../api/client.js';

type HookType = 'file_edited' | 'file_created' | 'file_deleted' | 'session_completed';

interface HookEditorProps {
  type: HookType;
  pattern?: string;
  commands: ShellCommandConfig[];
  isNew: boolean;
  onSave: (type: HookType, pattern: string, commands: ShellCommandConfig[]) => Promise<void>;
  onCancel: () => void;
  onTest: (command: ShellCommandConfig, id: string) => Promise<void>;
  saving: boolean;
  responsive?: boolean;
}

interface CommandEditorState {
  command: string[];
  environment: Record<string, string>;
  timeout?: number;
  cwd?: string;
  showAdvanced: boolean;
}

export function HookEditor({
  type,
  pattern: initialPattern,
  commands: initialCommands,
  isNew,
  onSave,
  onCancel,
  onTest,
  saving,
  responsive = false,
}: HookEditorProps) {
  const isFileHook = type !== 'session_completed';

  // 表单状态
  const [pattern, setPattern] = useState(initialPattern || '');
  const [commandStates, setCommandStates] = useState<CommandEditorState[]>(() => {
    if (initialCommands.length > 0) {
      return initialCommands.map((cmd) => ({
        command: cmd.command,
        environment: cmd.environment || {},
        timeout: cmd.timeout,
        cwd: cmd.cwd,
        showAdvanced: !!(cmd.environment && Object.keys(cmd.environment).length > 0) || !!cmd.timeout || !!cmd.cwd,
      }));
    }
    return [{
      command: [''],
      environment: {},
      timeout: undefined,
      cwd: undefined,
      showAdvanced: false,
    }];
  });

  const [testingIndex, setTestingIndex] = useState<number | null>(null);
  const [errors, setErrors] = useState<{ pattern?: string; commands?: string[] }>({});

  // 验证表单
  const validate = () => {
    const newErrors: { pattern?: string; commands?: string[] } = {};
    const commandErrors: string[] = [];

    if (isFileHook && !pattern.trim()) {
      newErrors.pattern = 'Pattern is required';
    }

    commandStates.forEach((state, idx) => {
      const cmdStr = state.command.filter(Boolean).join(' ').trim();
      if (!cmdStr) {
        commandErrors[idx] = 'Command is required';
      }
    });

    if (commandErrors.some(Boolean)) {
      newErrors.commands = commandErrors;
    }

    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  };

  // 保存
  const handleSave = async () => {
    if (!validate()) return;

    const commands: ShellCommandConfig[] = commandStates.map((state) => {
      const cmd: ShellCommandConfig = {
        command: state.command.filter(Boolean),
      };
      if (Object.keys(state.environment).length > 0) {
        cmd.environment = state.environment;
      }
      if (state.timeout) {
        cmd.timeout = state.timeout;
      }
      if (state.cwd) {
        cmd.cwd = state.cwd;
      }
      return cmd;
    });

    await onSave(type, pattern, commands);
  };

  // 测试命令
  const handleTest = async (index: number) => {
    const state = commandStates[index];
    const cmd: ShellCommandConfig = {
      command: state.command.filter(Boolean),
    };
    if (Object.keys(state.environment).length > 0) {
      cmd.environment = state.environment;
    }
    if (state.timeout) {
      cmd.timeout = state.timeout;
    }
    if (state.cwd) {
      cmd.cwd = state.cwd;
    }

    if (cmd.command.length === 0) return;

    setTestingIndex(index);
    await onTest(cmd, `editor-${index}`);
    setTestingIndex(null);
  };

  // 更新命令
  const updateCommand = (index: number, updates: Partial<CommandEditorState>) => {
    setCommandStates((prev) => {
      const newStates = [...prev];
      newStates[index] = { ...newStates[index], ...updates };
      return newStates;
    });
  };

  // 更新命令参数
  const updateCommandArg = (cmdIndex: number, argIndex: number, value: string) => {
    setCommandStates((prev) => {
      const newStates = [...prev];
      const newCommand = [...newStates[cmdIndex].command];
      newCommand[argIndex] = value;
      newStates[cmdIndex] = { ...newStates[cmdIndex], command: newCommand };
      return newStates;
    });
  };

  // 添加命令参数
  const addCommandArg = (cmdIndex: number) => {
    setCommandStates((prev) => {
      const newStates = [...prev];
      newStates[cmdIndex] = {
        ...newStates[cmdIndex],
        command: [...newStates[cmdIndex].command, ''],
      };
      return newStates;
    });
  };

  // 删除命令参数
  const removeCommandArg = (cmdIndex: number, argIndex: number) => {
    setCommandStates((prev) => {
      const newStates = [...prev];
      const newCommand = newStates[cmdIndex].command.filter((_, i) => i !== argIndex);
      newStates[cmdIndex] = {
        ...newStates[cmdIndex],
        command: newCommand.length > 0 ? newCommand : [''],
      };
      return newStates;
    });
  };

  // 添加环境变量
  const addEnvVar = (cmdIndex: number) => {
    setCommandStates((prev) => {
      const newStates = [...prev];
      const newEnv = { ...newStates[cmdIndex].environment };
      newEnv[`VAR_${Object.keys(newEnv).length + 1}`] = '';
      newStates[cmdIndex] = { ...newStates[cmdIndex], environment: newEnv };
      return newStates;
    });
  };

  // 更新环境变量
  const updateEnvVar = (cmdIndex: number, oldKey: string, newKey: string, value: string) => {
    setCommandStates((prev) => {
      const newStates = [...prev];
      const newEnv = { ...newStates[cmdIndex].environment };
      if (oldKey !== newKey) {
        delete newEnv[oldKey];
      }
      newEnv[newKey] = value;
      newStates[cmdIndex] = { ...newStates[cmdIndex], environment: newEnv };
      return newStates;
    });
  };

  // 删除环境变量
  const removeEnvVar = (cmdIndex: number, key: string) => {
    setCommandStates((prev) => {
      const newStates = [...prev];
      const newEnv = { ...newStates[cmdIndex].environment };
      delete newEnv[key];
      newStates[cmdIndex] = { ...newStates[cmdIndex], environment: newEnv };
      return newStates;
    });
  };

  // 添加新命令
  const addCommand = () => {
    setCommandStates((prev) => [
      ...prev,
      {
        command: [''],
        environment: {},
        timeout: undefined,
        cwd: undefined,
        showAdvanced: false,
      },
    ]);
  };

  // 删除命令
  const removeCommand = (index: number) => {
    if (commandStates.length <= 1) return;
    setCommandStates((prev) => prev.filter((_, i) => i !== index));
  };

  const title = isNew
    ? isFileHook ? 'Add File Hook' : 'Add Session Hook'
    : isFileHook ? 'Edit File Hook' : 'Edit Session Hook';

  return (
    <AnimatePresence>
      <motion.div
        variants={modalOverlay}
        initial="initial"
        animate="animate"
        exit="exit"
        transition={{ duration: 0.2 }}
        className={cn(
          'fixed inset-0 bg-black/70 flex z-[60]',
          responsive ? 'items-end md:items-center justify-center' : 'items-center justify-center'
        )}
        onClick={onCancel}
      >
        <motion.div
          variants={modalContent}
          initial="initial"
          animate="animate"
          exit="exit"
          transition={smoothTransition}
          onClick={(e) => e.stopPropagation()}
          className={cn(
            'bg-surface-subtle max-h-[85vh] overflow-hidden flex flex-col',
            responsive
              ? 'w-full md:w-full md:max-w-lg md:mx-4 rounded-t-2xl md:rounded-lg'
              : 'rounded-lg w-full max-w-lg mx-4'
          )}
        >
          {/* Header */}
          <div
            className={cn(
              'flex items-center justify-between border-b border-line',
              responsive ? 'px-4 py-3' : 'px-6 py-4'
            )}
          >
            {responsive && (
              <div className="absolute top-2 left-1/2 -translate-x-1/2 w-10 h-1 bg-surface-emphasis rounded-full md:hidden" />
            )}
            <h3 className={cn('text-lg font-semibold', responsive && 'mt-2 md:mt-0')}>
              {title}
            </h3>
            <Button variant="ghost" size="icon" onClick={onCancel}>
              <X size={20} />
            </Button>
          </div>

          {/* Content */}
          <div className="flex-1 overflow-y-auto p-4 space-y-4">
            {/* Pattern (for file hooks) */}
            {isFileHook && (
              <div>
                <label className="block text-sm font-medium text-fg-secondary mb-1">
                  Pattern (glob)
                </label>
                <input
                  type="text"
                  value={pattern}
                  onChange={(e) => setPattern(e.target.value)}
                  placeholder="e.g., *.ts, src/**/*.tsx"
                  className={cn(
                    'w-full px-3 py-2 bg-surface-base border rounded-lg text-sm',
                    'focus:outline-none focus:ring-2 focus:ring-primary-500',
                    errors.pattern ? 'border-red-500' : 'border-line'
                  )}
                />
                {errors.pattern && (
                  <p className="text-xs text-red-400 mt-1">{errors.pattern}</p>
                )}
                <p className="text-xs text-fg-subtle mt-1">
                  Use glob patterns to match files (e.g., *.ts, **/*.json)
                </p>
              </div>
            )}

            {/* Commands */}
            <div>
              <div className="flex items-center justify-between mb-2">
                <label className="text-sm font-medium text-fg-secondary">
                  Commands
                </label>
                {isFileHook && (
                  <Button
                    variant="ghost"
                    size="sm"
                    onClick={addCommand}
                    className="text-primary-400"
                  >
                    <Plus size={14} className="mr-1" />
                    Add Command
                  </Button>
                )}
              </div>

              <div className="space-y-4">
                {commandStates.map((state, cmdIndex) => (
                  <div
                    key={cmdIndex}
                    className="bg-surface-base/50 rounded-lg p-3 border border-line"
                  >
                    {/* Command args */}
                    <div className="space-y-2">
                      <div className="flex items-center justify-between">
                        <span className="text-xs text-fg-subtle">
                          Command {commandStates.length > 1 ? cmdIndex + 1 : ''}
                        </span>
                        <div className="flex items-center gap-1">
                          <Button
                            variant="ghost"
                            size="sm"
                            onClick={() => handleTest(cmdIndex)}
                            disabled={testingIndex === cmdIndex}
                            className="h-6 text-green-400 hover:text-green-300"
                          >
                            {testingIndex === cmdIndex ? (
                              <RefreshCw size={12} className="animate-spin mr-1" />
                            ) : (
                              <Play size={12} className="mr-1" />
                            )}
                            Test
                          </Button>
                          {commandStates.length > 1 && (
                            <Button
                              variant="ghost"
                              size="sm"
                              onClick={() => removeCommand(cmdIndex)}
                              className="h-6 w-6 p-0 text-red-400 hover:text-red-300"
                            >
                              <Trash2 size={12} />
                            </Button>
                          )}
                        </div>
                      </div>

                      <div className="flex flex-wrap gap-2">
                        {state.command.map((arg, argIndex) => (
                          <div key={argIndex} className="flex items-center gap-1">
                            <input
                              type="text"
                              value={arg}
                              onChange={(e) => updateCommandArg(cmdIndex, argIndex, e.target.value)}
                              placeholder={argIndex === 0 ? 'command' : 'arg'}
                              className={cn(
                                'px-2 py-1 bg-surface-subtle border border-line-muted rounded text-sm font-mono',
                                'focus:outline-none focus:ring-1 focus:ring-primary-500',
                                argIndex === 0 ? 'min-w-[100px]' : 'min-w-[80px]'
                              )}
                            />
                            {state.command.length > 1 && (
                              <button
                                onClick={() => removeCommandArg(cmdIndex, argIndex)}
                                className="text-fg-subtle hover:text-red-400"
                              >
                                <X size={14} />
                              </button>
                            )}
                          </div>
                        ))}
                        <Button
                          variant="ghost"
                          size="sm"
                          onClick={() => addCommandArg(cmdIndex)}
                          className="h-7 px-2"
                        >
                          <Plus size={14} />
                        </Button>
                      </div>

                      {errors.commands?.[cmdIndex] && (
                        <p className="text-xs text-red-400">{errors.commands[cmdIndex]}</p>
                      )}
                    </div>

                    {/* Advanced options toggle */}
                    <button
                      onClick={() => updateCommand(cmdIndex, { showAdvanced: !state.showAdvanced })}
                      className="flex items-center gap-1 text-xs text-fg-subtle hover:text-fg-secondary mt-3"
                    >
                      {state.showAdvanced ? <ChevronDown size={14} /> : <ChevronRight size={14} />}
                      Advanced options
                    </button>

                    {/* Advanced options */}
                    {state.showAdvanced && (
                      <div className="mt-3 space-y-3 pl-4 border-l border-line">
                        {/* Timeout */}
                        <div>
                          <label className="block text-xs text-fg-muted mb-1">
                            Timeout (ms)
                          </label>
                          <input
                            type="number"
                            value={state.timeout || ''}
                            onChange={(e) => updateCommand(cmdIndex, {
                              timeout: e.target.value ? parseInt(e.target.value) : undefined
                            })}
                            placeholder="30000"
                            className="w-32 px-2 py-1 bg-surface-subtle border border-line-muted rounded text-sm focus:outline-none focus:ring-1 focus:ring-primary-500"
                          />
                        </div>

                        {/* Working Directory */}
                        <div>
                          <label className="block text-xs text-fg-muted mb-1">
                            Working Directory
                          </label>
                          <input
                            type="text"
                            value={state.cwd || ''}
                            onChange={(e) => updateCommand(cmdIndex, { cwd: e.target.value || undefined })}
                            placeholder="(project root)"
                            className="w-full px-2 py-1 bg-surface-subtle border border-line-muted rounded text-sm focus:outline-none focus:ring-1 focus:ring-primary-500"
                          />
                        </div>

                        {/* Environment Variables */}
                        <div>
                          <div className="flex items-center justify-between mb-1">
                            <label className="text-xs text-fg-muted">
                              Environment Variables
                            </label>
                            <Button
                              variant="ghost"
                              size="sm"
                              onClick={() => addEnvVar(cmdIndex)}
                              className="h-5 px-1 text-xs"
                            >
                              <Plus size={10} className="mr-0.5" />
                              Add
                            </Button>
                          </div>
                          <div className="space-y-1">
                            {Object.entries(state.environment).map(([key, value]) => (
                              <div key={key} className="flex items-center gap-1">
                                <input
                                  type="text"
                                  value={key}
                                  onChange={(e) => updateEnvVar(cmdIndex, key, e.target.value, value)}
                                  placeholder="KEY"
                                  className="w-28 px-2 py-1 bg-surface-subtle border border-line-muted rounded text-xs font-mono focus:outline-none focus:ring-1 focus:ring-primary-500"
                                />
                                <span className="text-fg-subtle">=</span>
                                <input
                                  type="text"
                                  value={value}
                                  onChange={(e) => updateEnvVar(cmdIndex, key, key, e.target.value)}
                                  placeholder="value"
                                  className="flex-1 px-2 py-1 bg-surface-subtle border border-line-muted rounded text-xs font-mono focus:outline-none focus:ring-1 focus:ring-primary-500"
                                />
                                <button
                                  onClick={() => removeEnvVar(cmdIndex, key)}
                                  className="text-fg-subtle hover:text-red-400"
                                >
                                  <X size={12} />
                                </button>
                              </div>
                            ))}
                          </div>
                        </div>
                      </div>
                    )}
                  </div>
                ))}
              </div>
            </div>
          </div>

          {/* Footer */}
          <div
            className={cn(
              'flex items-center justify-end gap-2 border-t border-line',
              responsive ? 'px-4 py-3 safe-area-pb' : 'px-6 py-4'
            )}
          >
            <Button variant="ghost" onClick={onCancel} disabled={saving}>
              Cancel
            </Button>
            <Button onClick={handleSave} disabled={saving}>
              {saving ? (
                <>
                  <RefreshCw size={14} className="animate-spin mr-1" />
                  Saving...
                </>
              ) : (
                'Save'
              )}
            </Button>
          </div>
        </motion.div>
      </motion.div>
    </AnimatePresence>
  );
}
