/**
 * CodeEditor Component
 *
 * 基于 CodeMirror 的代码编辑器，支持多标签页和保存功能
 */

import { useState, useCallback, useEffect, useMemo } from 'react';
import CodeMirror from '@uiw/react-codemirror';
import { javascript } from '@codemirror/lang-javascript';
import { python } from '@codemirror/lang-python';
import { json } from '@codemirror/lang-json';
import { html } from '@codemirror/lang-html';
import { css } from '@codemirror/lang-css';
import { markdown } from '@codemirror/lang-markdown';
import { oneDark } from '@codemirror/theme-one-dark';
import { X, Save, Circle, FileCode, MousePointerClick, Code2 } from 'lucide-react';
import { motion, AnimatePresence } from 'framer-motion';
import { toast } from 'sonner';
import { cn } from '../utils/cn.js';
import { writeFile } from '../api/client.js';
import { useTheme } from '../hooks/useTheme.js';

export interface EditorTab {
  id: string;
  path: string;
  name: string;
  content: string;
  originalContent: string;
  language: string;
}

interface CodeEditorProps {
  tabs: EditorTab[];
  activeTabId: string | null;
  onTabChange: (tabId: string) => void;
  onTabClose: (tabId: string) => void;
  onContentChange: (tabId: string, content: string) => void;
  onSave?: (tabId: string, path: string, content: string) => void;
  className?: string;
}

// 根据文件扩展名获取语言
function getLanguageExtension(language: string) {
  switch (language) {
    case 'javascript':
    case 'typescript':
    case 'jsx':
    case 'tsx':
      return javascript({ jsx: true, typescript: language.includes('typescript') || language === 'tsx' });
    case 'python':
      return python();
    case 'json':
      return json();
    case 'html':
      return html();
    case 'css':
    case 'scss':
    case 'less':
      return css();
    case 'markdown':
    case 'md':
      return markdown();
    default:
      return [];
  }
}

// 根据文件名获取语言类型
export function getLanguageFromFilename(filename: string): string {
  const ext = filename.split('.').pop()?.toLowerCase() || '';
  const languageMap: Record<string, string> = {
    ts: 'typescript',
    tsx: 'tsx',
    js: 'javascript',
    jsx: 'jsx',
    py: 'python',
    json: 'json',
    html: 'html',
    htm: 'html',
    css: 'css',
    scss: 'scss',
    less: 'less',
    md: 'markdown',
    markdown: 'markdown',
  };
  return languageMap[ext] || 'text';
}

export function CodeEditor({
  tabs,
  activeTabId,
  onTabChange,
  onTabClose,
  onContentChange,
  onSave,
  className,
}: CodeEditorProps) {
  const { resolvedTheme } = useTheme();
  const [saving, setSaving] = useState<string | null>(null);

  const activeTab = useMemo(
    () => tabs.find((tab) => tab.id === activeTabId),
    [tabs, activeTabId]
  );

  // 检查标签是否有未保存的更改
  const hasUnsavedChanges = useCallback(
    (tab: EditorTab) => tab.content !== tab.originalContent,
    []
  );

  // 保存文件
  const handleSave = useCallback(
    async (tab: EditorTab) => {
      if (!hasUnsavedChanges(tab)) return;

      setSaving(tab.id);
      try {
        const result = await writeFile(tab.path, tab.content);
        if (result.success) {
          onSave?.(tab.id, tab.path, tab.content);
          toast.success(`Saved ${tab.name}`);
        } else {
          toast.error('Failed to save file');
        }
      } catch (error) {
        console.error('Failed to save file:', error);
        toast.error('Failed to save file');
      } finally {
        setSaving(null);
      }
    },
    [hasUnsavedChanges, onSave]
  );

  // 键盘快捷键
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if ((e.metaKey || e.ctrlKey) && e.key === 's') {
        e.preventDefault();
        if (activeTab && hasUnsavedChanges(activeTab)) {
          handleSave(activeTab);
        }
      }
    };

    window.addEventListener('keydown', handleKeyDown);
    return () => window.removeEventListener('keydown', handleKeyDown);
  }, [activeTab, hasUnsavedChanges, handleSave]);

  // 编辑器扩展
  const extensions = useMemo(() => {
    if (!activeTab) return [];
    return [getLanguageExtension(activeTab.language)].flat();
  }, [activeTab]);

  // 获取文件图标颜色
  const getFileIconColor = (language: string) => {
    switch (language) {
      case 'typescript':
      case 'tsx':
        return 'text-blue-500';
      case 'javascript':
      case 'jsx':
        return 'text-yellow-500';
      case 'python':
        return 'text-green-500';
      case 'json':
        return 'text-orange-500';
      case 'html':
        return 'text-red-500';
      case 'css':
      case 'scss':
      case 'less':
        return 'text-purple-500';
      case 'markdown':
        return 'text-cyan-500';
      default:
        return 'text-fg-muted';
    }
  };

  if (tabs.length === 0) {
    return (
      <div className={cn('flex flex-col items-center justify-center h-full bg-surface-base', className)}>
        <motion.div
          initial={{ opacity: 0, y: 10 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ duration: 0.3 }}
          className="text-center max-w-xs"
        >
          <div className="w-20 h-20 mx-auto mb-5 rounded-2xl bg-gradient-to-br from-surface-subtle to-surface-muted flex items-center justify-center shadow-inner">
            <Code2 size={36} className="text-fg-subtle" />
          </div>
          <h3 className="text-fg font-semibold text-lg mb-2">No files open</h3>
          <p className="text-fg-muted text-sm mb-5 leading-relaxed">
            Select a file from the explorer to view and edit its contents
          </p>
          <div className="flex items-center justify-center gap-2 text-xs text-fg-subtle bg-surface-subtle px-4 py-2 rounded-full">
            <MousePointerClick size={14} />
            <span>Click a file to open</span>
          </div>
        </motion.div>
      </div>
    );
  }

  return (
    <div className={cn('flex flex-col h-full bg-surface-base', className)}>
      {/* Tab Bar */}
      <div className="flex items-center border-b border-line bg-surface-subtle/80 backdrop-blur-sm overflow-x-auto scrollbar-hide">
        <AnimatePresence mode="popLayout">
          {tabs.map((tab) => {
            const isActive = tab.id === activeTabId;
            const isModified = hasUnsavedChanges(tab);
            const isSaving = saving === tab.id;
            const iconColor = getFileIconColor(tab.language);

            return (
              <motion.div
                key={tab.id}
                layout
                initial={{ opacity: 0, x: -10 }}
                animate={{ opacity: 1, x: 0 }}
                exit={{ opacity: 0, x: -10, scale: 0.95 }}
                transition={{ duration: 0.15, ease: 'easeOut' }}
                className={cn(
                  'relative flex items-center gap-2 px-3.5 py-2.5 cursor-pointer group min-w-0',
                  'hover:bg-surface-muted/50 transition-all duration-150',
                  isActive
                    ? 'bg-surface-base shadow-sm'
                    : 'border-r border-line/50'
                )}
                onClick={() => onTabChange(tab.id)}
              >
                {/* 活动标签顶部指示条 */}
                {isActive && (
                  <motion.div
                    layoutId="activeTabIndicator"
                    className="absolute top-0 left-0 right-0 h-0.5 bg-gradient-to-r from-primary-500 to-primary-400"
                    transition={{ type: 'spring', stiffness: 500, damping: 35 }}
                  />
                )}

                {/* 文件图标 */}
                <FileCode size={14} className={cn('flex-shrink-0', isActive ? iconColor : 'text-fg-subtle')} />

                {/* 文件名 */}
                <span
                  className={cn(
                    'text-sm truncate max-w-[140px] transition-colors',
                    isActive ? 'text-fg font-medium' : 'text-fg-muted'
                  )}
                  title={tab.path}
                >
                  {tab.name}
                </span>

                {/* 修改指示器 / 保存中 / 关闭按钮 */}
                <div className="flex items-center gap-1 flex-shrink-0">
                  {isSaving ? (
                    <div className="w-3 h-3 border-2 border-primary-500 border-t-transparent rounded-full animate-spin" />
                  ) : isModified ? (
                    <Circle size={8} className="fill-orange-400 text-orange-400" />
                  ) : null}

                  {/* 关闭按钮 */}
                  <button
                    onClick={(e) => {
                      e.stopPropagation();
                      onTabClose(tab.id);
                    }}
                    className={cn(
                      'p-1 rounded-md hover:bg-surface-emphasis/80 transition-all duration-150 flex-shrink-0',
                      'opacity-0 group-hover:opacity-100',
                      isActive && 'opacity-60 hover:opacity-100'
                    )}
                  >
                    <X size={12} className="text-fg-muted" />
                  </button>
                </div>
              </motion.div>
            );
          })}
        </AnimatePresence>

        {/* 保存按钮 */}
        {activeTab && hasUnsavedChanges(activeTab) && (
          <motion.button
            initial={{ opacity: 0, scale: 0.9 }}
            animate={{ opacity: 1, scale: 1 }}
            whileHover={{ scale: 1.05 }}
            whileTap={{ scale: 0.95 }}
            onClick={() => handleSave(activeTab)}
            disabled={saving === activeTab.id}
            className="ml-auto mr-3 px-3 py-1.5 rounded-md bg-primary-500/10 hover:bg-primary-500/20 transition-colors flex items-center gap-1.5"
            title="Save (Cmd+S)"
          >
            <Save size={14} className="text-primary-500" />
            <span className="text-xs text-primary-500 font-medium">Save</span>
          </motion.button>
        )}
      </div>

      {/* Editor */}
      <div className="flex-1 overflow-hidden">
        {activeTab && (
          <CodeMirror
            value={activeTab.content}
            height="100%"
            theme={resolvedTheme === 'dark' ? oneDark : undefined}
            extensions={extensions}
            onChange={(value) => onContentChange(activeTab.id, value)}
            basicSetup={{
              lineNumbers: true,
              highlightActiveLineGutter: true,
              highlightSpecialChars: true,
              history: true,
              foldGutter: true,
              drawSelection: true,
              dropCursor: true,
              allowMultipleSelections: true,
              indentOnInput: true,
              syntaxHighlighting: true,
              bracketMatching: true,
              closeBrackets: true,
              autocompletion: true,
              rectangularSelection: true,
              crosshairCursor: true,
              highlightActiveLine: true,
              highlightSelectionMatches: true,
              closeBracketsKeymap: true,
              defaultKeymap: true,
              searchKeymap: true,
              historyKeymap: true,
              foldKeymap: true,
              completionKeymap: true,
              lintKeymap: true,
            }}
            className="h-full"
          />
        )}
      </div>

      {/* Status Bar */}
      {activeTab && (
        <div className="flex items-center justify-between px-4 py-1.5 border-t border-line bg-surface-subtle/60 text-xs">
          <div className="flex items-center gap-4">
            {/* 语言 */}
            <span className="text-fg-muted capitalize">{activeTab.language}</span>
            {/* 行数 */}
            <span className="text-fg-subtle">
              {activeTab.content.split('\n').length} lines
            </span>
          </div>
          <div className="flex items-center gap-4">
            {/* 编码 */}
            <span className="text-fg-subtle">UTF-8</span>
            {/* 路径 */}
            <span className="text-fg-subtle truncate max-w-[300px]" title={activeTab.path}>
              {activeTab.path}
            </span>
          </div>
        </div>
      )}
    </div>
  );
}
