import { useState, useEffect, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { Modal } from '../ui';
import { ClockIcon, RotateCcwIcon, GitCompareIcon, PlusIcon, MinusIcon, SparklesIcon, TrashIcon } from 'lucide-react';
import { ConfirmDialog } from '../ui/ConfirmDialog';
import { deletePromptVersion, getPromptVersions } from '../../services/database';
import { scheduleAllSaveSync } from '../../services/webdav-save-sync';
import type { Prompt, PromptVersion } from '@prompthub/shared/types';

interface VersionHistoryModalProps {
  isOpen: boolean;
  onClose: () => void;
  prompt: Prompt;
  onRestore: (version: PromptVersion) => void;
}

// Calculate LCS (Longest Common Subsequence) of two strings for diff
// 计算两个字符串的 LCS (最长公共子序列) 用于 diff
function computeLCS(a: string[], b: string[]): number[][] {
  const m = a.length;
  const n = b.length;
  const dp: number[][] = Array(m + 1).fill(null).map(() => Array(n + 1).fill(0));
  
  for (let i = 1; i <= m; i++) {
    for (let j = 1; j <= n; j++) {
      if (a[i - 1] === b[j - 1]) {
        dp[i][j] = dp[i - 1][j - 1] + 1;
      } else {
        dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
      }
    }
  }
  return dp;
}

interface DiffLine {
  type: 'add' | 'remove' | 'unchanged';
  content: string;
  oldLineNum?: number;
  newLineNum?: number;
}

// Generate git-style diff
// 生成 git 风格的 diff
function generateDiff(oldText: string, newText: string): DiffLine[] {
  const oldLines = (oldText || '').split('\n');
  const newLines = (newText || '').split('\n');
  
  if (oldText === newText) {
    return oldLines.map((line, i) => ({
      type: 'unchanged' as const,
      content: line,
      oldLineNum: i + 1,
      newLineNum: i + 1,
    }));
  }
  
  const dp = computeLCS(oldLines, newLines);
  const diff: DiffLine[] = [];
  
  let i = oldLines.length;
  let j = newLines.length;
  const stack: DiffLine[] = [];
  
  while (i > 0 || j > 0) {
    if (i > 0 && j > 0 && oldLines[i - 1] === newLines[j - 1]) {
      stack.push({ 
        type: 'unchanged', 
        content: oldLines[i - 1], 
        oldLineNum: i, 
        newLineNum: j 
      });
      i--;
      j--;
    } else if (j > 0 && (i === 0 || dp[i][j - 1] >= dp[i - 1][j])) {
      stack.push({ 
        type: 'add', 
        content: newLines[j - 1], 
        newLineNum: j 
      });
      j--;
    } else if (i > 0) {
      stack.push({ 
        type: 'remove', 
        content: oldLines[i - 1], 
        oldLineNum: i 
      });
      i--;
    }
  }
  
  while (stack.length > 0) {
    diff.push(stack.pop()!);
  }
  
  return diff;
}

// Git-style diff view
// Git 风格差异视图
function GitDiffView({
  oldText,
  newText,
  label,
  emptyLabel,
}: {
  oldText: string;
  newText: string;
  label: string;
  emptyLabel: string;
}) {
  const diff = useMemo(() => generateDiff(oldText, newText), [oldText, newText]);
  
  const stats = useMemo(() => {
    const added = diff.filter(d => d.type === 'add').length;
    const removed = diff.filter(d => d.type === 'remove').length;
    return { added, removed };
  }, [diff]);
  
  const isUnchanged = stats.added === 0 && stats.removed === 0;
  
  return (
    <div className="space-y-2">
      <div className="flex items-center justify-between">
        <div className="text-xs font-medium text-muted-foreground uppercase">{label}</div>
        {!isUnchanged && (
          <div className="flex items-center gap-3 text-xs">
            <span className="flex items-center gap-1 text-green-600">
              <PlusIcon className="w-3 h-3" />
              {stats.added}
            </span>
            <span className="flex items-center gap-1 text-red-600">
              <MinusIcon className="w-3 h-3" />
              {stats.removed}
            </span>
          </div>
        )}
      </div>
      
      {isUnchanged ? (
        <div className="text-sm text-muted-foreground italic p-3 bg-muted/30 rounded-lg">
          {emptyLabel}
        </div>
      ) : (
        <div className="rounded-lg border border-border overflow-hidden font-mono text-xs">
          <div className="max-h-64 overflow-y-auto">
            {diff.map((line, index) => (
              <div
                key={index}
                className={`flex ${
                  line.type === 'add' 
                    ? 'bg-green-500/15 text-green-700 dark:text-green-300' 
                    : line.type === 'remove' 
                      ? 'bg-red-500/15 text-red-700 dark:text-red-300' 
                      : 'bg-transparent text-foreground/80'
                }`}
              >
                {/* Line numbers */}
                {/* 行号 */}
                <div className="flex-shrink-0 w-16 flex text-muted-foreground/50 select-none border-r border-border/50">
                  <span className="w-8 text-right px-1 border-r border-border/30">
                    {line.oldLineNum || ''}
                  </span>
                  <span className="w-8 text-right px-1">
                    {line.newLineNum || ''}
                  </span>
                </div>
                {/* Symbol */}
                {/* 符号 */}
                <div className={`flex-shrink-0 w-5 text-center font-bold ${
                  line.type === 'add' ? 'text-green-600' : line.type === 'remove' ? 'text-red-600' : ''
                }`}>
                  {line.type === 'add' ? '+' : line.type === 'remove' ? '-' : ' '}
                </div>
                {/* Content */}
                {/* 内容 */}
                <div className="flex-1 px-2 py-0.5 whitespace-pre-wrap break-all">
                  {line.content || ' '}
                </div>
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

export function VersionHistoryModal({ isOpen, onClose, prompt, onRestore }: VersionHistoryModalProps) {
  const [versions, setVersions] = useState<PromptVersion[]>([]);
  const [selectedVersion, setSelectedVersion] = useState<PromptVersion | null>(null);
  const [compareVersion, setCompareVersion] = useState<PromptVersion | null>(null);
  const [showDiff, setShowDiff] = useState(false);
  const { t } = useTranslation();
  const [isLoading, setIsLoading] = useState(true);
  const [isDeleting, setIsDeleting] = useState(false);
  const [versionToDelete, setVersionToDelete] = useState<PromptVersion | null>(null);

  useEffect(() => {
    if (isOpen && prompt) {
      loadVersions();
    }
  }, [isOpen, prompt]);

  const loadVersions = async () => {
    setIsLoading(true);
    setShowDiff(false);
    setCompareVersion(null);
    try {
      const historyVersions = await getPromptVersions(prompt.id);
      
      // Add current version to list (as latest version)
      // 将当前版本也加入列表（作为最新版本）
      const currentVersion: PromptVersion = {
        id: 'current',
        promptId: prompt.id,
        version: prompt.version,
        systemPrompt: prompt.systemPrompt,
        userPrompt: prompt.userPrompt,
        variables: prompt.variables || [],
        note: t('prompt.currentVersion'),
        aiResponse: prompt.lastAiResponse, // Use current version's AI response
        createdAt: prompt.updatedAt,
      };
      
      // Merge current version and history versions, sorted by version number descending
      const allVersions = [currentVersion, ...historyVersions.filter(v => v.version !== prompt.version)];
      
      setVersions(allVersions);
      if (allVersions.length > 0) {
        setSelectedVersion(allVersions[0]);
      }
    } catch (error) {
      console.error('Failed to load versions:', error);
    } finally {
      setIsLoading(false);
    }
  };

  const handleRestore = () => {
    if (selectedVersion) {
      if (
        confirm(
          t('prompt.restoreConfirm', {
            version: selectedVersion.version,
          }),
        )
      ) {
        onRestore(selectedVersion);
        onClose();
      }
    }
  };

  const handleDeleteVersion = async () => {
    if (!versionToDelete || versionToDelete.id === 'current') {
      setVersionToDelete(null);
      return;
    }

    setIsDeleting(true);
    try {
      await deletePromptVersion(versionToDelete.id);
      scheduleAllSaveSync('prompt:delete-version');
      await loadVersions();
      setVersionToDelete(null);
    } catch (error) {
      console.error('Failed to delete prompt version:', error);
    } finally {
      setIsDeleting(false);
    }
  };

  return (
    <Modal isOpen={isOpen} onClose={onClose} title={t('prompt.history')} size="2xl">
      {isLoading ? (
        <div className="flex items-center justify-center py-12">
          <div className="text-muted-foreground">{t('prompt.historyLoading')}</div>
        </div>
      ) : versions.length === 0 ? (
        <div className="flex flex-col items-center justify-center py-12 text-center">
          <ClockIcon className="w-12 h-12 text-muted-foreground/50 mb-4" />
          <p className="text-muted-foreground">{t('prompt.noHistory')}</p>
          <p className="text-sm text-muted-foreground/70 mt-1">
            {t('prompt.noHistoryHint')}
          </p>
        </div>
      ) : (
        <div className="flex gap-4 min-h-[400px]">
          {/* Version list */}
          {/* 版本列表 */}
          <div className="w-48 border-r border-border pr-4 space-y-1">
            <div className="text-xs text-muted-foreground mb-2 px-1">
              {showDiff ? t('prompt.selectCompareVersion') : t('prompt.selectVersion')}
            </div>
            {versions.map((version, index) => (
              <button
                key={version.id}
                onClick={() => {
                  if (showDiff) {
                    setCompareVersion(version);
                  } else {
                    setSelectedVersion(version);
                  }
                }}
                className={`w-full text-left px-3 py-2 rounded-lg text-sm transition-colors ${
                  showDiff 
                    ? compareVersion?.id === version.id
                      ? 'bg-green-500 text-white'
                      : selectedVersion?.id === version.id
                        ? 'bg-red-500 text-white'
                        : 'hover:bg-muted'
                    : selectedVersion?.id === version.id
                      ? 'bg-primary text-white'
                      : 'hover:bg-muted'
                }`}
              >
                <div className="font-medium">v{version.version}</div>
                <div className={`text-xs ${
                  (showDiff ? (compareVersion?.id === version.id || selectedVersion?.id === version.id) : selectedVersion?.id === version.id)
                    ? 'text-white/70' 
                    : 'text-muted-foreground'
                }`}>
                  {new Date(version.createdAt).toLocaleString()}
                </div>
              </button>
            ))}
          </div>

          {/* Version content / Diff comparison */}
          {/* 版本内容 / 差异对比 */}
          <div className="flex-1 space-y-4">
            {showDiff && selectedVersion && compareVersion ? (
              <>
                <div className="flex items-center gap-2 text-sm text-muted-foreground mb-4 p-2 rounded-lg bg-muted/30">
                  <span className="px-2 py-1 rounded bg-red-500/20 text-red-600 font-mono text-xs">v{selectedVersion.version}</span>
                  <span className="text-muted-foreground">→</span>
                  <span className="px-2 py-1 rounded bg-green-500/20 text-green-600 font-mono text-xs">v{compareVersion.version}</span>
                  <span className="text-xs text-muted-foreground ml-auto">
                    {new Date(selectedVersion.createdAt).toLocaleDateString()} → {new Date(compareVersion.createdAt).toLocaleDateString()}
                  </span>
                </div>
                <GitDiffView 
                  oldText={selectedVersion.systemPrompt || ''} 
                  newText={compareVersion.systemPrompt || ''} 
                  label={t('prompt.systemPromptLabel')}
                  emptyLabel={t('prompt.noChanges')}
                />
                <GitDiffView 
                  oldText={selectedVersion.userPrompt} 
                  newText={compareVersion.userPrompt} 
                  label={t('prompt.userPromptLabel')}
                  emptyLabel={t('prompt.noChanges')}
                />
              </>
            ) : selectedVersion && (
              <>
                <div>
                  <div className="text-xs font-medium text-muted-foreground uppercase mb-2">
                    {t('prompt.systemPromptLabel')}
                  </div>
                  <div className="p-3 rounded-lg bg-muted/50 text-sm font-mono whitespace-pre-wrap max-h-32 overflow-y-auto">
                    {selectedVersion.systemPrompt || t('prompt.noContent')}
                  </div>
                </div>
                <div>
                  <div className="text-xs font-medium text-muted-foreground uppercase mb-2">
                    {t('prompt.userPromptLabel')}
                  </div>
                  <div className="p-3 rounded-lg bg-muted/50 text-sm font-mono whitespace-pre-wrap max-h-48 overflow-y-auto">
                    {selectedVersion.userPrompt}
                  </div>
                </div>
                {selectedVersion.note && (
                  <div>
                    <div className="text-xs font-medium text-muted-foreground uppercase mb-2">
                      {t('prompt.changeNote')}
                    </div>
                    <div className="p-3 rounded-lg bg-muted/50 text-sm">
                      {selectedVersion.note}
                    </div>
                  </div>
                )}
                {/* AI response */}
                {/* AI 响应 */}
                {selectedVersion.aiResponse && (
                  <div>
                    <div className="text-xs font-medium text-muted-foreground uppercase mb-2 flex items-center gap-1.5">
                      <SparklesIcon className="w-3.5 h-3.5 text-primary" />
                      {t('prompt.aiResponse')}
                    </div>
                    <div className="p-3 rounded-lg bg-primary/5 border border-primary/20 text-sm whitespace-pre-wrap max-h-48 overflow-y-auto">
                      {selectedVersion.aiResponse}
                    </div>
                  </div>
                )}
              </>
            )}
          </div>
        </div>
      )}

      {/* Action buttons */}
      {/* 操作按钮 */}
      {versions.length > 0 && selectedVersion && (
        <div className="flex justify-between mt-6 pt-4 border-t border-border">
          <div className="flex gap-3">
            <button
              onClick={() => {
                if (showDiff) {
                  setShowDiff(false);
                  setCompareVersion(null);
                } else {
                  setShowDiff(true);
                }
              }}
              className={`flex items-center gap-2 h-9 px-4 rounded-lg text-sm font-medium transition-colors ${
                showDiff 
                  ? 'bg-primary text-white' 
                  : 'hover:bg-muted'
              }`}
            >
              <GitCompareIcon className="w-4 h-4" />
              {showDiff ? t('prompt.exitCompare') : t('prompt.versionCompare')}
            </button>
            {!showDiff && selectedVersion.id !== 'current' && (
              <button
                onClick={() => setVersionToDelete(selectedVersion)}
                disabled={isDeleting}
                className="flex items-center gap-2 h-9 px-4 rounded-lg border border-red-500/20 text-red-600 hover:bg-red-500/10 transition-colors disabled:opacity-50"
              >
                <TrashIcon className="w-4 h-4" />
                {t('common.delete', 'Delete')}
              </button>
            )}
          </div>
          <div className="flex gap-3">
            <button
              onClick={onClose}
              className="h-9 px-4 rounded-lg text-sm font-medium hover:bg-muted transition-colors"
            >
              {t('common.cancel')}
            </button>
            {!showDiff && (
              <button
                onClick={handleRestore}
                className="flex items-center gap-2 h-9 px-4 rounded-lg bg-primary text-white text-sm font-medium hover:bg-primary/90 transition-colors"
              >
                <RotateCcwIcon className="w-4 h-4" />
                {t('prompt.restoreVersion')}
              </button>
            )}
          </div>
        </div>
      )}
      <ConfirmDialog
        isOpen={Boolean(versionToDelete)}
        onClose={() => {
          if (isDeleting) return;
          setVersionToDelete(null);
        }}
        onConfirm={handleDeleteVersion}
        title={t('prompt.deleteVersionTitle', 'Delete version')}
        message={t('prompt.deleteVersionConfirm', {
          version: versionToDelete?.version ?? '',
        })}
        confirmText={
          isDeleting ? t('common.loading', 'Loading...') : t('common.delete', 'Delete')
        }
        cancelText={t('common.cancel')}
        variant="destructive"
      />
    </Modal>
  );
}
