/**
 * ComparePreview - Document Comparison Preview Component
 *
 * Features:
 * - Compare two documents using Monaco Editor
 * - Support PDF and Word (.docx) files
 * - Automatic text extraction and line-by-line comparison
 * - Navigation between differences
 *
 * Props:
 * - doc1Path: Original document path
 * - doc2Path: Comparison document path
 */

import React, { useState, useRef, useEffect } from "react";
import { DiffEditor, loader } from "@monaco-editor/react";
import type { editor } from "monaco-editor";
import { pdfjs } from 'react-pdf';
import mammoth from 'mammoth';
import { toastService } from '~/components/ui/Toast';
import { DOCUMENT_URL } from '~/config/api-config';

// Setup PDF.js worker
pdfjs.GlobalWorkerOptions.workerSrc = '/pdf.worker.js';

// 配置 Monaco Editor 使用本地资源（避免 CDN 加载超时）
// Monaco Editor 资源已通过 npm run copy-monaco 复制到 public/monaco-editor
if (typeof window !== 'undefined') {
  console.log('[Monaco] 使用本地资源加载');

  loader.config({
    paths: {
      vs: '/monaco-editor/vs'
    }
  });

  // 添加加载超时监控和错误处理
  const initTimeout = setTimeout(() => {
    console.error('[Monaco] 加载超时（30秒）');
    toastService.error('代码编辑器加载超时，请刷新页面重试');
  }, 30000);

  loader.init().then(() => {
    clearTimeout(initTimeout);
    console.log('[Monaco] ✅ 加载成功');
  }).catch((error: Error) => {
    clearTimeout(initTimeout);
    console.error('[Monaco] ❌ 加载失败:', error);
    toastService.error(`代码编辑器加载失败: ${error.message}`);
  });
}

// Document type enum
type DocumentType = 'pdf' | 'docx' | 'unknown';

// PDF type enum
type PdfType = 'text' | 'scanned' | 'unknown';

// PDF info interface
interface PdfInfo {
  type: PdfType;
  numPages: number;
  textLength: number;
  confidence: number;
}

// Document info interface
interface DocumentInfo {
  fileType: DocumentType;
  pdfType?: PdfType;
  numPages?: number;
  textLength: number;
  confidence: number;
}

// Component Props interface
interface ComparePreviewProps {
  doc1Path: string;
  doc2Path: string;
}

export function ComparePreview({ doc1Path, doc2Path }: ComparePreviewProps): JSX.Element {
  // 如果没有模板合同路径，直接返回提示
  if (!doc2Path || doc2Path.trim() === '') {
    return (
      <div style={{
        height: '100%',
        width: '100%',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        padding: '40px',
        backgroundColor: '#f9f9f9'
      }}>
        <div style={{
          maxWidth: '500px',
          textAlign: 'center',
          padding: '32px',
          backgroundColor: '#fff',
          borderRadius: '8px',
          boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',
          border: '1px solid #e0e0e0'
        }}>
          <div style={{
            width: '64px',
            height: '64px',
            margin: '0 auto 24px',
            backgroundColor: '#fff3cd',
            borderRadius: '50%',
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            border: '3px solid #ffc107'
          }}>
            <i className="ri-file-warning-line" style={{ fontSize: '32px', color: '#ff9800' }}></i>
          </div>
          <h3 style={{
            fontSize: '20px',
            fontWeight: '600',
            color: '#333',
            marginBottom: '12px'
          }}>
            无法进行对比
          </h3>
          <p style={{
            fontSize: '14px',
            color: '#666',
            lineHeight: '1.6',
            marginBottom: '16px'
          }}>
            该文档类型暂未上传模板合同，无法进行对比分析。
          </p>
          <div style={{
            padding: '12px 16px',
            backgroundColor: '#fff3cd',
            border: '1px solid #ffc107',
            borderRadius: '4px',
            fontSize: '13px',
            color: '#856404',
            lineHeight: '1.5'
          }}>
            <i className="ri-error-warning-line" style={{ marginRight: '6px' }}></i>
            <strong>提示：</strong>请先在文档类型管理中为该类型上传模板合同，然后重新加载此页面。
          </div>
        </div>
      </div>
    );
  }

  const [originalText, setOriginalText] = useState<string>('');
  const [modifiedText, setModifiedText] = useState<string>('');
  const diffEditorRef = useRef<editor.IStandaloneDiffEditor | null>(null);
  const [diffCount, setDiffCount] = useState<number>(0);
  const [currentDiff, setCurrentDiff] = useState<number>(0);

  const [doc1Info, setDoc1Info] = useState<DocumentInfo | null>(null);
  const [doc2Info, setDoc2Info] = useState<DocumentInfo | null>(null);
  const [isLoadingDoc1, setIsLoadingDoc1] = useState(false);
  const [isLoadingDoc2, setIsLoadingDoc2] = useState(false);

  // Log initial props
//   console.log('[ComparePreview] Component initialized with paths:', { doc1Path, doc2Path });

  // Detect file type based on file path
  const detectFileType = (filePath: string): DocumentType => {
    const lowerPath = filePath.toLowerCase();
    if (lowerPath.endsWith('.pdf')) return 'pdf';
    if (lowerPath.endsWith('.docx') || lowerPath.endsWith('.doc')) return 'docx';
    return 'unknown';
  };

  // PDF type detection function
  const detectPdfType = async (pdfUrl: string): Promise<PdfInfo> => {
    const loadingTask = pdfjs.getDocument(pdfUrl);
    const pdf = await loadingTask.promise;

    let totalTextLength = 0;
    const pagesToCheck = Math.min(pdf.numPages, 3);

    for (let i = 1; i <= pagesToCheck; i++) {
      const page = await pdf.getPage(i);
      const textContent = await page.getTextContent();
      const pageText = textContent.items
        .map((item: any) => item.str)
        .join('');
      totalTextLength += pageText.length;
    }

    const avgTextPerPage = totalTextLength / pagesToCheck;
    const confidence = Math.min(avgTextPerPage / 500, 1);

    let type: PdfType;
    if (avgTextPerPage > 100) {
      type = 'text';
    } else if (avgTextPerPage > 10) {
      type = 'scanned';
    } else {
      type = 'unknown';
    }

    return {
      type,
      numPages: pdf.numPages,
      textLength: totalTextLength,
      confidence
    };
  };

  // PDF text extraction function
  const extractTextFromPdf = async (pdfUrl: string): Promise<string> => {
    const loadingTask = pdfjs.getDocument(pdfUrl);
    const pdf = await loadingTask.promise;

    let fullText = '';

    for (let i = 1; i <= pdf.numPages; i++) {
      const page = await pdf.getPage(i);
      const textContent = await page.getTextContent();
      const pageText = textContent.items
        .map((item: any) => item.str)
        .join(' ');
      fullText += `\n========== Page ${i} ==========\n${pageText}\n`;
    }

    return fullText;
  };

  // Word document text extraction function
  const extractTextFromWord = async (docUrl: string): Promise<string> => {
    const response = await fetch(docUrl);
    if (!response.ok) {
      throw new Error(`Cannot load document: ${response.statusText}`);
    }

    const arrayBuffer = await response.arrayBuffer();
    const textResult = await mammoth.extractRawText({ arrayBuffer });

    return textResult.value;
  };

  // Load document and extract text (supports PDF and Word)
  const loadDocumentAndExtractText = async (
    docPath: string,
    setDocInfo: (info: DocumentInfo | null) => void,
    setLoading: (loading: boolean) => void,
    setTextContent: (text: string) => void
  ) => {
    try {
      setLoading(true);

      const docUrl = docPath.startsWith('http') ? docPath : `${DOCUMENT_URL}${docPath}`;
    //   console.log('[ComparePreview] Loading document:', docUrl);

      const fileType = detectFileType(docPath);

      if (fileType === 'pdf') {
        const pdfInfo = await detectPdfType(docUrl);
        const text = await extractTextFromPdf(docUrl);

        const docInfo: DocumentInfo = {
          fileType: 'pdf',
          pdfType: pdfInfo.type,
          numPages: pdfInfo.numPages,
          textLength: pdfInfo.textLength,
          confidence: pdfInfo.confidence
        };

        setDocInfo(docInfo);
        setTextContent(text);

        // console.log('[ComparePreview] PDF text extracted:', {
        //   path: docPath,
        //   textLength: text.length,
        //   firstChars: text.substring(0, 100)
        // });

        if (pdfInfo.type === 'text') {
          toastService.success(`PDF加载成功！共 ${pdfInfo.numPages} 页，提取了 ${pdfInfo.textLength} 个字符`);
        } else if (pdfInfo.type === 'scanned') {
          toastService.warning('检测到扫描版PDF，文本提取质量可能较低');
        } else {
          toastService.error('无法识别PDF类型，可能是图片PDF');
        }
      } else if (fileType === 'docx') {
        const text = await extractTextFromWord(docUrl);

        const docInfo: DocumentInfo = {
          fileType: 'docx',
          textLength: text.length,
          confidence: 1.0
        };

        setDocInfo(docInfo);
        setTextContent(text);

        // console.log('[ComparePreview] Word text extracted:', {
        //   path: docPath,
        //   textLength: text.length,
        //   firstChars: text.substring(0, 100)
        // });

        toastService.success(`Word文档加载成功！提取了 ${text.length} 个字符`);
      } else {
        toastService.error('不支持的文件类型');
        setTextContent('');
      }
    } catch (error) {
      console.error('Document loading failed:', error);
      toastService.error(`文档加载失败: ${error instanceof Error ? error.message : '未知错误'}`);
      setDocInfo(null);
      setTextContent('');
    } finally {
      setLoading(false);
    }
  };

  // Monaco Editor mount callback
  const handleEditorDidMount = (editor: editor.IStandaloneDiffEditor) => {
    diffEditorRef.current = editor;

    // console.log('[ComparePreview] Editor mounted, checking differences...', {
    //   originalTextLength: originalText.length,
    //   modifiedTextLength: modifiedText.length
    // });

    // Polling function to get diff results
    // Monaco Editor's diff calculation is asynchronous and may return null initially
    let retryCount = 0;
    const maxRetries = 20; // Maximum 20 attempts
    const retryInterval = 150; // Check every 150ms

    const pollForDiffChanges = () => {
      retryCount++;
      const lineChanges = editor.getLineChanges();

    //   console.log(`[ComparePreview] Polling attempt ${retryCount}:`, {
    //     lineChanges: lineChanges ? `${lineChanges.length} changes` : 'null',
    //     hasLineChanges: lineChanges !== null
    //   });

      // If we got the diff results
      if (lineChanges !== null) {
        setDiffCount(lineChanges.length);
        // console.log(`[ComparePreview] ✅ Successfully got ${lineChanges.length} differences on attempt ${retryCount}`);

        // Verify the result makes sense
        if (lineChanges.length === 0 && originalText.length > 0 && modifiedText.length > 0) {
          const textsAreIdentical = originalText === modifiedText;
        //   console.log('[ComparePreview] Texts are identical?', textsAreIdentical);

          if (textsAreIdentical) {
            // console.log('[ComparePreview] ℹ️ Documents are identical - 0 differences is correct');
          } else {
            console.warn('[ComparePreview] ⚠️ Documents differ but Monaco shows 0 differences');
            // console.log('[ComparePreview] Original text sample:', originalText.substring(0, 100));
            // console.log('[ComparePreview] Modified text sample:', modifiedText.substring(0, 100));
          }
        }
        return; // Stop polling
      }

      // If still null and haven't exceeded max retries, try again
      if (retryCount < maxRetries) {
        setTimeout(pollForDiffChanges, retryInterval);
      } else {
        console.error(`[ComparePreview] ❌ Failed to get diff results after ${maxRetries} attempts`);
        setDiffCount(0);
      }
    };

    // Start polling after a short delay
    setTimeout(pollForDiffChanges, 100);
  };

  // Add highlight flash animation when navigating to a difference
  const addFlashHighlight = (editor: editor.ICodeEditor, lineNumber: number) => {
    const decorations = editor.deltaDecorations([], [
      {
        range: new (window as any).monaco.Range(lineNumber, 1, lineNumber, 1),
        options: {
          isWholeLine: true,
          className: 'diff-flash-highlight',
        }
      }
    ]);

    // Remove the highlight after animation completes
    setTimeout(() => {
      editor.deltaDecorations(decorations, []);
    }, 1000);
  };

  // Go to next difference
  const goToNextDiff = () => {
    if (!diffEditorRef.current) return;

    const lineChanges = diffEditorRef.current.getLineChanges();
    if (!lineChanges || lineChanges.length === 0) return;

    const nextIndex = (currentDiff + 1) % lineChanges.length;
    const nextChange = lineChanges[nextIndex];

    const modifiedEditor = diffEditorRef.current.getModifiedEditor();
    modifiedEditor.revealLineInCenter(nextChange.modifiedStartLineNumber);
    modifiedEditor.setPosition({
      lineNumber: nextChange.modifiedStartLineNumber,
      column: 1
    });

    // Add flash highlight
    addFlashHighlight(modifiedEditor, nextChange.modifiedStartLineNumber);

    setCurrentDiff(nextIndex);
  };

  // Go to previous difference
  const goToPreviousDiff = () => {
    if (!diffEditorRef.current) return;

    const lineChanges = diffEditorRef.current.getLineChanges();
    if (!lineChanges || lineChanges.length === 0) return;

    const prevIndex = currentDiff === 0 ? lineChanges.length - 1 : currentDiff - 1;
    const prevChange = lineChanges[prevIndex];

    const modifiedEditor = diffEditorRef.current.getModifiedEditor();
    modifiedEditor.revealLineInCenter(prevChange.modifiedStartLineNumber);
    modifiedEditor.setPosition({
      lineNumber: prevChange.modifiedStartLineNumber,
      column: 1
    });

    // Add flash highlight
    addFlashHighlight(modifiedEditor, prevChange.modifiedStartLineNumber);

    setCurrentDiff(prevIndex);
  };

  // Load documents on mount
  useEffect(() => {
    // console.log('[ComparePreview] Doc1 path changed:', doc1Path);
    if (doc1Path) {
      loadDocumentAndExtractText(doc1Path, setDoc1Info, setIsLoadingDoc1, setOriginalText);
    } else {
      setOriginalText('');
    }
  }, [doc1Path]);

  useEffect(() => {
    // console.log('[ComparePreview] Doc2 path changed:', doc2Path);
    if (doc2Path) {
      loadDocumentAndExtractText(doc2Path, setDoc2Info, setIsLoadingDoc2, setModifiedText);
    } else {
      setModifiedText('');
    }
  }, [doc2Path]);

  // Recalculate differences when text changes
  useEffect(() => {
    // console.log('[ComparePreview] Text changed, recalculating differences...', {
    //   originalTextLength: originalText.length,
    //   modifiedTextLength: modifiedText.length,
    //   hasEditor: !!diffEditorRef.current
    // });

    const timer = setTimeout(() => {
      if (diffEditorRef.current) {
        const lineChanges = diffEditorRef.current.getLineChanges();
        if (lineChanges) {
          setDiffCount(lineChanges.length);
        //   console.log(`[ComparePreview] Recalculated differences: ${lineChanges.length} found`);

          // 如果文本都不为空但差异为0，打印警告
          if (lineChanges.length === 0 && originalText.length > 0 && modifiedText.length > 0) {
            console.warn('[ComparePreview] Warning: Both texts loaded but 0 differences found!', {
              doc1PathsMatch: doc1Path === doc2Path,
              originalSample: originalText.substring(0, 50),
              modifiedSample: modifiedText.substring(0, 50)
            });
          }
        }
      }
    }, 100);

    return () => clearTimeout(timer);
  }, [originalText, modifiedText, doc1Path, doc2Path]);

  return (
    <div className="compare-preview-container" style={{
      height: '100%',
      width: '100%',
      display: 'flex',
      flexDirection: 'column',
      overflow: 'hidden'
    }}>
      {/* Character-level diff highlighting styles */}
      <style>{`
        .compare-preview-container {
          height: 100%;
          width: 100%;
        }

        .monaco-diff-editor .char-insert {
          background-color: rgba(100, 150, 50, 0.6) !important;
        }

        .monaco-diff-editor .char-delete {
          background-color: rgba(200, 50, 50, 0.5) !important;
        }

        .monaco-diff-editor .line-insert .char-insert {
          background-color: rgba(100, 150, 50, 0.7) !important;
        }

        .monaco-diff-editor .line-delete .char-delete {
          background-color: rgba(200, 50, 50, 0.6) !important;
        }

        /* Flash highlight animation for navigation */
        .diff-flash-highlight {
          background-color: rgba(255, 200, 0, 0.3) !important;
          animation: flash-pulse 1s ease-in-out;
        }

        @keyframes flash-pulse {
          0%, 100% { background-color: rgba(255, 200, 0, 0); }
          50% { background-color: rgba(255, 200, 0, 0.5); }
        }

        /* Navigation button focus styles */
        .nav-diff-button {
          padding: 6px 12px;
          background-color: #fff;
          border: 1px solid #d0d0d0;
          border-radius: 4px;
          cursor: pointer;
          font-size: 14px;
          display: flex;
          align-items: center;
          gap: 6px;
          transition: all 0.2s ease;
        }

        .nav-diff-button:hover:not(:disabled) {
          background-color: #f0f0f0;
          border-color: #00684a;
        }

        .nav-diff-button:focus {
          outline: none;
          border-color: #00684a;
          box-shadow: 0 0 0 2px rgba(0, 104, 74, 0.2);
        }

        .nav-diff-button:active:not(:disabled) {
          background-color: #e0e0e0;
        }

        .nav-diff-button:disabled {
          cursor: not-allowed;
          opacity: 0.5;
        }
      `}</style>

      {/* Toolbar and Info banner - combined in one row */}
      <div style={{
        padding: '12px 16px',
        borderBottom: '1px solid #e0e0e0',
        backgroundColor: '#f5f5f5',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'space-between',
        gap: '16px'
      }}>
        {/* Left side: Toolbar controls */}
        <div style={{ display: 'flex', alignItems: 'center', gap: '12px', flexShrink: 0 }}>
          {/* Diff statistics */}
          <div style={{
            padding: '6px 12px',
            backgroundColor: '#fff',
            border: '1px solid #d0d0d0',
            borderRadius: '4px',
            fontSize: '14px',
            color: '#333'
          }}>
            <i className="ri-git-compare-line" style={{ marginRight: '6px', color: '#00684a' }}></i>
            发现 <strong style={{ color: '#00684a' }}>{diffCount}</strong> 处差异
            {diffCount > 0 && ` (当前: ${currentDiff + 1}/${diffCount})`}
          </div>

          {/* Navigation buttons */}
          <button
            className="nav-diff-button"
            onClick={goToPreviousDiff}
            disabled={diffCount === 0}
          >
            <i className="ri-arrow-up-line"></i>
            上一处差异
          </button>

          <button
            className="nav-diff-button"
            onClick={goToNextDiff}
            disabled={diffCount === 0}
          >
            <i className="ri-arrow-down-line"></i>
            下一处差异
          </button>
        </div>

        {/* Right side: Info banner */}
        <div style={{
          display: 'flex',
          alignItems: 'center',
          gap: '8px',
          padding: '6px 12px',
          backgroundColor: '#e7f3ff',
          border: '1px solid #b3d9ff',
          borderRadius: '4px',
          fontSize: '13px',
          color: '#004085',
          flexShrink: 1,
          minWidth: 0
        }}>
          <i className="ri-information-line" style={{ fontSize: '16px', flexShrink: 0 }}></i>
          <div style={{ lineHeight: '1.5', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
            <strong>差异高亮说明：</strong>
            <span style={{ marginLeft: '8px' }}>
              <span style={{ color: '#dc3545', fontWeight: 'bold' }}>左侧红色</span>：原始版本 |
              <span style={{ color: '#28a745', fontWeight: 'bold', marginLeft: '8px' }}>右侧绿色</span>：比对版本 |
              <span style={{ color: '#666', fontWeight: 'bold', marginLeft: '8px' }}>深色高亮</span>：字符差异
            </span>
          </div>
        </div>
      </div>

      {/* Diff Editor main area */}
      <div style={{ flex: 1, overflow: 'hidden', position: 'relative' }}>
        {/* 只有当两个文本都加载完成后才渲染 Monaco Editor */}
        {originalText && modifiedText && !isLoadingDoc1 && !isLoadingDoc2 ? (
          <DiffEditor
            key={`${doc1Path}-${doc2Path}-${originalText.length}-${modifiedText.length}`}
            height="100%"
            language="plaintext"
            original={originalText}
            modified={modifiedText}
            onMount={handleEditorDidMount}
            theme="vs"
            options={{
              readOnly: true,
              renderSideBySide: true,
              ignoreTrimWhitespace: false,
              renderWhitespace: 'selection',
              fontSize: 14,
              lineNumbers: 'on',
              minimap: {
                enabled: true
              },
              scrollBeyondLastLine: false,
              wordWrap: 'on',
              automaticLayout: true,
              renderIndicators: true,
              diffWordWrap: 'on',
              enableSplitViewResizing: true,
              diffAlgorithm: 'advanced',
            }}
          />
        ) : (
          <div style={{
            height: '100%',
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            color: '#666',
            fontSize: '14px'
          }}>
            {isLoadingDoc1 || isLoadingDoc2 ? (
              <span>正在加载文档...</span>
            ) : (
              <span>等待文档加载...</span>
            )}
          </div>
        )}

        {/* Loading overlay */}
        {(isLoadingDoc1 || isLoadingDoc2) && (
          <div style={{
            position: 'absolute',
            top: 0,
            left: 0,
            right: 0,
            bottom: 0,
            backgroundColor: 'rgba(255, 255, 255, 0.9)',
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            zIndex: 1000
          }}>
            <div style={{ textAlign: 'center' }}>
              <div style={{
                width: '48px',
                height: '48px',
                border: '4px solid #f3f3f3',
                borderTop: '4px solid #00684a',
                borderRadius: '50%',
                animation: 'spin 1s linear infinite',
                margin: '0 auto 16px'
              }}></div>
              <div style={{ fontSize: '16px', color: '#333' }}>
                正在加载文档并提取文本...
              </div>
              {isLoadingDoc1 && <div style={{ fontSize: '14px', color: '#666', marginTop: '8px' }}>📄 加载原始文档</div>}
              {isLoadingDoc2 && <div style={{ fontSize: '14px', color: '#666', marginTop: '8px' }}>📄 加载对比文档</div>}
            </div>
          </div>
        )}
      </div>

      {/* Spinner animation */}
      <style>{`
        @keyframes spin {
          0% { transform: rotate(0deg); }
          100% { transform: rotate(360deg); }
        }
      `}</style>
    </div>
  );
}
