import React, { useState, useEffect, useRef } from 'react';
import { isFormatSupportedForPreview } from '../constants/fileSupport';
import { PDFStatus } from '../types';
import { pdfPreviewService } from '../services/pdfPreviewService';
import { useToast } from '../contexts/ToastContext';
import { useConfirm } from '../contexts/ConfirmContext';
import { X, FileText, Loader, AlertCircle, Maximize2, Eye, Download, ExternalLink, RefreshCw, Scissors, ChevronLeft, ChevronRight } from 'lucide-react';
import { PDFSelectionTool } from './PDFSelectionTool';
import { CreateNoteFromPDFDialog } from './CreateNoteFromPDFDialog';
import { noteService } from '../services/noteService';
import { useLanguage } from '../contexts/LanguageContext';
import { knowledgeBaseService } from '../services/knowledgeBaseService';
import * as pdfjs from 'pdfjs-dist';

// Set worker path for PDF.js
pdfjs.GlobalWorkerOptions.workerSrc = `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.min.mjs`;

interface PDFPreviewProps {
  fileId: string;
  fileName: string;
  authToken: string;
  groupId?: string;
  onClose: () => void;
}

export const PDFPreview: React.FC<PDFPreviewProps> = ({ fileId, fileName, authToken, groupId, onClose }) => {
  const [status, setStatus] = useState<PDFStatus>({ status: 'pending' });
  const [loading, setLoading] = useState(true);
  const [isFullscreen, setIsFullscreen] = useState(false);
  const [pdfUrl, setPdfUrl] = useState<string>('');
  const [iframeError, setIframeError] = useState(false);
  const [isSelectionMode, setIsSelectionMode] = useState(false);
  const [currentPage, setCurrentPage] = useState(1);
  const [pdfBlob, setPdfBlob] = useState<Blob | null>(null);
  const [selectionData, setSelectionData] = useState<{ screenshot: Blob; text: string } | null>(null);
  const [numPages, setNumPages] = useState<number>(0);
  const [pdfDoc, setPdfDoc] = useState<pdfjs.PDFDocumentProxy | null>(null);
  const [zoomLevel, setZoomLevel] = useState<number>(1.0); // Add zoom level state
  const currentRenderTask = useRef<pdfjs.RenderTask | null>(null); // Save current rendering task
  const scrollContainerRef = useRef<HTMLDivElement>(null);
  const flipDirection = useRef<'next' | 'prev' | null>(null);
  const lastFlipTime = useRef<number>(0);

  const { showToast } = useToast();
  const { confirm } = useConfirm();
  const { t, language } = useLanguage();
  const containerRef = React.useRef<HTMLDivElement>(null);
  const canvasRef = useRef<HTMLCanvasElement>(null);

  useEffect(() => {
    if (status.status === 'ready') {
      pdfPreviewService.getPDFUrl(fileId)
        .then(result => {
          setPdfUrl(result.url); // Set pdfUrl for download

          // Fetch PDF data and create blob URL
          fetch(result.url)
            .then(async response => {
              if (!response.ok) {
                const errorData = await response.json().catch(() => ({}));
                throw new Error(errorData.message || 'Failed to fetch PDF data');
              }
              return response.blob();
            })
            .then(blob => {
              setPdfBlob(blob);

              // Start fetching and rendering PDF document
              loadAndRenderPDF(blob);
            })
            .catch((err) => {
              console.error('PDF fetch error:', err);
              setIframeError(true);
              setStatus({ status: 'failed', error: err.message });
            });
        })
        .catch((err) => {
          console.error('getPDFUrl error:', err);
          setIframeError(true);
          setStatus({ status: 'failed', error: err.message });
        });
    }
  }, [status.status, fileId]);

  useEffect(() => {
    if (pdfDoc && currentPage) {
      // Re-render on page change or zoom level change
      renderCurrentPage(pdfDoc, currentPage);
    }
  }, [currentPage, pdfDoc, zoomLevel]);

  const isSupported = isFormatSupportedForPreview(fileName);

  useEffect(() => {
    if (isSupported) {
      checkPDFStatus();
      const interval = setInterval(checkPDFStatus, 3000);
      return () => clearInterval(interval);
    } else {
      setLoading(false);
      setStatus({ status: 'failed', error: t('previewNotSupported') });
    }
  }, [fileId, isSupported]);

  const checkPDFStatus = async () => {
    try {
      const pdfStatus = await pdfPreviewService.getPDFStatus(fileId);
      setStatus(pdfStatus);

      // Actively trigger conversion if status is pending
      if (pdfStatus.status === 'pending') {
        setStatus({ status: 'converting' });
        try {
          // Access PDF URL to trigger conversion
          await pdfPreviewService.preloadPDF(fileId);
        } catch (error) {
          console.log('Preload triggered, conversion should start');
        }
      }

      if (pdfStatus.status === 'ready' || pdfStatus.status === 'failed') {
        setLoading(false);
      }
    } catch (error: any) {
      setLoading(false);
      const errorMessage = error.message || t('checkPDFStatusFailed');
      setStatus({ status: 'failed', error: errorMessage });
      showToast(errorMessage, 'error');
    }
  };

  const loadAndRenderPDF = async (blob: Blob) => {
    try {
      const pdfData = await blob.arrayBuffer();
      const pdf = await pdfjs.getDocument({ data: pdfData }).promise;

      setPdfDoc(pdf);
      setNumPages(pdf.numPages);

      if (currentPage > pdf.numPages) {
        setCurrentPage(pdf.numPages);
      }

      renderCurrentPage(pdf, currentPage);
    } catch (error) {
      console.error('Failed to load PDF:', error);
      setIframeError(true);
    }
  };

  const handleZoomIn = () => {
    setZoomLevel(prev => Math.min(3.0, prev + 0.1));
  };

  const handleZoomOut = () => {
    setZoomLevel(prev => Math.max(0.5, prev - 0.1));
  };

  const handleResetZoom = () => {
    setZoomLevel(1.0);
  };

  const renderCurrentPage = async (pdf: pdfjs.PDFDocumentProxy, pageNum: number) => {
    if (!canvasRef.current) return;

    try {
      // Cancel rendering task if one is in progress
      if (currentRenderTask.current) {
        currentRenderTask.current.cancel();
      }

      const page = await pdf.getPage(pageNum);
      const canvas = canvasRef.current;
      const context = canvas.getContext('2d');

      if (!context) return;

      // Get container dimensions
      if (!containerRef.current) return;
      const container = containerRef.current;
      const containerWidth = container.clientWidth;
      const containerHeight = container.clientHeight;

      // Handle high DPI displays
      const devicePixelRatio = window.devicePixelRatio || 1;

      // Calculate scale to fit page in container width while maintaining aspect ratio
      const viewport = page.getViewport({ scale: 1 });
      const baseScale = (containerWidth - 48) / viewport.width; // Add padding for width

      // Apply zoom level to base scale
      const scale = baseScale * zoomLevel;

      const finalScale = scale * devicePixelRatio;
      const scaledViewport = page.getViewport({ scale: finalScale });
      const cssViewport = page.getViewport({ scale: scale });

      // Set canvas dimensions with device pixel ratio
      canvas.width = scaledViewport.width;
      canvas.height = scaledViewport.height;

      // Set CSS dimensions explicitly for high-DPI
      canvas.style.width = `${cssViewport.width}px`;
      canvas.style.height = `${cssViewport.height}px`;

      // Reset any previous transforms
      context.setTransform(1, 0, 0, 1, 0, 0);

      // Clear canvas
      context.clearRect(0, 0, canvas.width, canvas.height);

      // Fill with white background
      context.fillStyle = 'white';
      context.fillRect(0, 0, canvas.width, canvas.height);

      // Set proper transform for high DPI
      context.scale(devicePixelRatio, devicePixelRatio);

      // Create and save the new render task
      const renderContext = {
        canvasContext: context,
        viewport: page.getViewport({ scale: scale }),
      };

      // Save the render task to allow for cancellation
      currentRenderTask.current = page.render(renderContext);

      // Wait for rendering to complete
      await currentRenderTask.current.promise;

      // Clear the current render task
      currentRenderTask.current = null;

      // Adjust scroll position after page turn
      if (flipDirection.current && scrollContainerRef.current) {
        const container = scrollContainerRef.current;
        if (flipDirection.current === 'next') {
          container.scrollTop = 0;
        } else if (flipDirection.current === 'prev') {
          container.scrollTop = container.scrollHeight;
        }
        flipDirection.current = null;
      }
    } catch (error) {
      if (error instanceof Error && error.name !== 'RenderingCancelledException') {
        console.error('Failed to render PDF page:', error);
      }
      // Clear the current render task even if there's an error
      currentRenderTask.current = null;
    }
  };

  const handleFullscreen = () => {
    setIsFullscreen(!isFullscreen);
  };

  const handleDownload = () => {
    if (pdfUrl) {
      // Directly download if pdfUrl already exists
      const link = document.createElement('a');
      link.href = pdfUrl;
      link.download = fileName.replace(/\.[^/.]+$/, '.pdf');
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
    } else {
      // Try fetching and downloading if pdfUrl does not exist
      pdfPreviewService.getPDFUrl(fileId)
        .then(result => {
          const link = document.createElement('a');
          link.href = result.url;
          link.download = fileName.replace(/\.[^/.]+$/, '.pdf');
          document.body.appendChild(link);
          link.click();
          document.body.removeChild(link);
        })
        .catch(error => {
          console.error('Failed to download PDF:', error);
          showToast('error', t('downloadPDFFailed'));
        });
    }
  };

  const handleOpenInNewTab = () => {
    if (pdfUrl) {
      window.open(pdfUrl, '_blank');
    } else {
      // Try fetching and opening if pdfUrl does not exist
      pdfPreviewService.getPDFUrl(fileId)
        .then(result => {
          window.open(result.url, '_blank');
        })
        .catch(error => {
          console.error('Failed to open PDF in new tab:', error);
          showToast('error', t('openPDFInNewTabFailed'));
        });
    }
  };

  const handleRegenerate = async () => {
    if (await confirm(t('confirmRegeneratePDF'))) {
      setStatus({ status: 'converting' });
      setLoading(true);
      try {
        await pdfPreviewService.preloadPDF(fileId, true);
        // Reset state and trigger reload
        setPdfUrl('');
        setIframeError(false);
        setPdfDoc(null);
        setPdfBlob(null);
        setNumPages(0);
      } catch (error) {
        showToast('error', t('requestRegenerationFailed'));
        setStatus({ status: 'failed', error: t('requestRegenerationFailed') });
      }
    }
  };

  const handleIframeError = () => {
    setIframeError(true);
  };

  const handleWheel = (e: React.WheelEvent) => {
    if (!scrollContainerRef.current || isSelectionMode) return;

    const container = scrollContainerRef.current;
    const { scrollTop, scrollHeight, clientHeight } = container;
    const now = Date.now();
    const throttleMs = 600; // Prevent rapid page turning

    // Scroll down for next page
    if (e.deltaY > 0 && scrollTop + clientHeight >= scrollHeight - 1) {
      if (currentPage < numPages && now - lastFlipTime.current > throttleMs) {
        flipDirection.current = 'next';
        lastFlipTime.current = now;
        setCurrentPage(prev => prev + 1);
      }
    }
    // Scroll up for previous page
    else if (e.deltaY < 0 && scrollTop <= 1) {
      if (currentPage > 1 && now - lastFlipTime.current > throttleMs) {
        flipDirection.current = 'prev';
        lastFlipTime.current = now;
        setCurrentPage(prev => prev - 1);
      }
    }
  };

  const handleSelectionComplete = (screenshot: Blob, text: string) => {
    // Set preliminary data and open dialog
    setSelectionData({ screenshot, text });
    setIsSelectionMode(false);
  };

  const handleSaveNote = async (title: string, content: string, selectedGroupId?: string) => {
    if (!authToken || !selectionData) return;

    try {
      await noteService.createFromPDFSelection(
        authToken,
        fileId,
        selectionData.screenshot,
        selectedGroupId || groupId,
        currentPage
      );
      showToast('success', t('noteCreatedSuccess'));
      setSelectionData(null);
    } catch (error) {
      console.error('Failed to create note:', error);
      showToast('error', t('noteCreatedFailed'));
    }
  };

  const renderContent = () => {
    switch (status.status) {
      case 'pending':
        return (
          <div className="flex flex-col items-center justify-center h-full text-gray-500">
            <Loader size={48} className="animate-spin mb-4" />
            <div className="text-lg font-medium mb-2">{t('preparingPDFConversion')}</div>
            <div className="text-sm">{t('pleaseWait')}</div>
          </div>
        );

      case 'converting':
        return (
          <div className="flex flex-col items-center justify-center h-full text-gray-500">
            <Loader size={48} className="animate-spin mb-4" />
            <div className="text-lg font-medium mb-2">{t('convertingPDF')}</div>
            <div className="text-sm">{t('pleaseWait')}</div>
          </div>
        );

      case 'failed':
        return (
          <div className="flex flex-col items-center justify-center h-full text-red-500">
            <AlertCircle size={48} className="mb-4" />
            <div className="text-lg font-medium mb-2">{t('pdfConversionFailed')}</div>
            <div className="text-sm text-gray-500 text-center max-w-md">
              {status.error || t('pdfConversionError')}
            </div>
            <button
              onClick={checkPDFStatus}
              className="mt-4 px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors"
            >
              {t('retry')}
            </button>
          </div>
        );

      case 'ready':
        if (iframeError) {
          return (
            <div className="flex flex-col items-center justify-center h-full text-gray-500">
              <AlertCircle size={48} className="mb-4" />
              <div className="text-lg font-medium mb-2">{t('pdfLoadFailed')}</div>
              <div className="text-sm text-gray-500 mb-4">{t('pdfLoadError')}</div>
              <div className="flex gap-2">
                <button
                  onClick={handleDownload}
                  className="flex items-center gap-2 px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition-colors"
                >
                  <Download size={16} />
                  {t('downloadPDF')}
                </button>
                <button
                  onClick={handleOpenInNewTab}
                  className="flex items-center gap-2 px-4 py-2 bg-gray-500 text-white rounded hover:bg-gray-600 transition-colors"
                >
                  <ExternalLink size={16} />
                  {t('openInNewWindow')}
                </button>
              </div>
            </div>
          );
        }

        if (!pdfDoc) {
          return (
            <div className="flex flex-col items-center justify-center h-full text-gray-500">
              <Loader size={48} className="animate-spin mb-4" />
              <div className="text-lg font-medium mb-2">{t('loadingPDF')}</div>
            </div>
          );
        }

        return (
          <div className="relative w-full h-full flex flex-col" ref={containerRef}>
            <div
              ref={scrollContainerRef}
              onWheel={handleWheel}
              className="flex-grow overflow-auto pdf-canvas-container bg-gray-100"
            >
              <div className="flex flex-col items-center py-12 pb-32 min-h-full">
                <canvas
                  ref={canvasRef}
                  className="bg-white shadow-xl max-w-full"
                />
              </div>
            </div>

            {isSelectionMode && (
              <PDFSelectionTool
                containerRef={containerRef}
                canvasRef={canvasRef}
                pdfBlob={pdfBlob}
                pageNumber={currentPage}
                authToken={authToken}
                zoomLevel={zoomLevel}
                onSelectionComplete={handleSelectionComplete}
                onCancel={() => setIsSelectionMode(false)}
              />
            )}

            <div className="absolute bottom-4 left-1/2 transform -translate-x-1/2 flex items-center gap-2 bg-white/90 border border-slate-200 px-3 py-1.5 rounded-full shadow-lg z-40">
              <div className="flex items-center border-r border-slate-200 pr-2 mr-2">
                <button
                  onClick={handleZoomOut}
                  className="p-1 hover:bg-slate-100 rounded text-slate-600 min-w-[28px] flex items-center justify-center"
                  title={t('zoomOut')}
                >
                  <span className="text-lg">−</span>
                </button>
                <span className="mx-1 text-sm text-slate-600 min-w-[40px] text-center">{Math.round(zoomLevel * 100)}%</span>
                <button
                  onClick={handleZoomIn}
                  className="p-1 hover:bg-slate-100 rounded text-slate-600 min-w-[28px] flex items-center justify-center"
                  title={t('zoomIn')}
                >
                  <span className="text-lg">+</span>
                </button>
                <button
                  onClick={handleResetZoom}
                  className="ml-1 p-1 px-2 hover:bg-slate-100 rounded text-slate-600 text-xs"
                  title={t('resetZoom')}
                >
                  100%
                </button>
              </div>
              <button
                onClick={() => {
                  const newPage = Math.max(1, currentPage - 1);
                  setCurrentPage(newPage);
                }}
                className="p-1 hover:bg-slate-100 rounded text-slate-600"
              >
                <ChevronLeft size={16} />
              </button>
              <div className="flex items-center gap-1">
                <input
                  type="number"
                  value={currentPage}
                  onChange={(e) => {
                    const val = Math.max(1, Math.min(numPages, parseInt(e.target.value) || 1));
                    setCurrentPage(val);
                  }}
                  className="w-12 text-center text-sm border-none focus:ring-0 bg-transparent font-medium"
                />
                <span className="text-sm text-slate-500">/ {numPages}</span>
              </div>
              <button
                onClick={() => {
                  const newPage = Math.min(numPages, currentPage + 1);
                  setCurrentPage(newPage);
                }}
                className="p-1 hover:bg-slate-100 rounded text-slate-600"
              >
                <ChevronRight size={16} />
              </button>
            </div>

            {selectionData && (
              <CreateNoteFromPDFDialog
                screenshot={selectionData.screenshot}
                extractedText={selectionData.text}
                authToken={authToken}
                initialGroupId={groupId}
                initialPageNumber={currentPage}
                onSave={handleSaveNote}
                onCancel={() => setSelectionData(null)}
              />
            )}
          </div>
        );

      default:
        return null;
    }
  };

  return (
    <div className={`fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-[999] ${isFullscreen ? 'p-0' : 'p-4'
      }`}>
      <div className={`bg-white rounded-lg overflow-hidden flex flex-col ${isFullscreen ? 'w-full h-full' : 'w-full max-w-4xl h-5/6'
        }`}>
        {/* Header */}
        <div className="flex items-center justify-between p-4 border-b bg-gray-50">
          <div className="flex items-center space-x-3">
            <FileText size={20} className="text-gray-600" />
            <div>
              <div className="font-medium text-gray-900">{fileName}</div>
              <div className="text-sm text-gray-500">{t('pdfPreview')}</div>
            </div>
          </div>

          <div className="flex items-center space-x-2">
            {status.status === 'ready' && !iframeError && (
              <>
                <div className="flex items-center gap-2 mr-2 border-r pr-2">
                  <span className="text-sm text-gray-500">{t('selectPageNumber')}</span>
                  <input
                    type="number"
                    min={1}
                    max={numPages}
                    value={currentPage}
                    onChange={(e) => {
                      const val = Math.max(1, Math.min(numPages, parseInt(e.target.value) || 1));
                      setCurrentPage(val);
                    }}
                    className="w-16 px-2 py-1 border rounded text-sm"
                    title={t('enterPageNumber')}
                  />
                </div>
                <button
                  onClick={() => setIsSelectionMode(!isSelectionMode)}
                  className={`p-2 transition-colors ${isSelectionMode ? 'bg-blue-100 text-blue-600 rounded' : 'text-gray-400 hover:text-blue-600'}`}
                  title={isSelectionMode ? t('exitSelectionMode') : t('clickToSelectAndNote')}
                >
                  <Scissors size={18} />
                </button>
                <button
                  onClick={handleRegenerate}
                  className="p-2 text-gray-400 hover:text-blue-600 transition-colors"
                  title={t('regeneratePDF')}
                >
                  <RefreshCw size={18} />
                </button>
                <button
                  onClick={handleDownload}
                  className="p-2 text-gray-400 hover:text-gray-600 transition-colors"
                  title={t('downloadPDF')}
                >
                  <Download size={18} />
                </button>
                <button
                  onClick={handleOpenInNewTab}
                  className="p-2 text-gray-400 hover:text-gray-600 transition-colors"
                  title={t('openInNewWindow')}
                >
                  <ExternalLink size={18} />
                </button>
                <button
                  onClick={handleFullscreen}
                  className="p-2 text-gray-400 hover:text-gray-600 transition-colors"
                  title={isFullscreen ? t('exitFullscreen') : t('fullscreenDisplay')}
                >
                  <Maximize2 size={18} />
                </button>
              </>
            )}
            <button
              onClick={onClose}
              className="p-2 text-gray-400 hover:text-gray-600 transition-colors"
            >
              <X size={18} />
            </button>
          </div>
        </div>

        {/* Content Area */}
        <div className="flex-1 h-full">
          {renderContent()}
        </div>
      </div>
    </div>
  );
};

interface PDFPreviewButtonProps {
  fileId: string;
  fileName: string;
  onPreview: () => void;
}

export const PDFPreviewButton: React.FC<PDFPreviewButtonProps> = ({
  fileId,
  fileName,
  onPreview
}) => {
  const [status, setStatus] = useState<PDFStatus>({ status: 'pending' });
  const [loading, setLoading] = useState(true);
  const { t } = useLanguage();
  const isSupported = isFormatSupportedForPreview(fileName);

  useEffect(() => {
    if (isSupported) {
      checkStatus();
    } else {
      setLoading(false);
    }
  }, [fileId, isSupported]);

  const checkStatus = async () => {
    try {
      const pdfStatus = await pdfPreviewService.getPDFStatus(fileId);
      setStatus(pdfStatus);
    } catch (error) {
      // Ignore error and use default state
    } finally {
      setLoading(false);
    }
  };

  const getIcon = () => {
    if (!isSupported) {
      return <Eye className="w-3 h-3 text-slate-200" />;
    }
    if (loading || status.status === 'converting') {
      return <Loader className="w-3 h-3 animate-spin" />;
    }
    if (status.status === 'failed') {
      return <AlertCircle className="w-3 h-3" />;
    }
    return <Eye className="w-3 h-3" />;
  };

  const getTitle = () => {
    if (!isSupported) return t('previewNotSupported');
    switch (status.status) {
      case 'ready': return t('pdfPreviewReady');
      case 'converting': return t('convertingInProgress');
      case 'failed': return t('conversionFailed');
      default: return t('generatePDFPreviewButton');
    }
  };

  return (
    <button
      onClick={onPreview}
      disabled={loading || status.status === 'converting' || !isSupported}
      className={`p-1 rounded transition-colors ${!isSupported
        ? 'text-slate-200 cursor-not-allowed'
        : status.status === 'failed'
          ? 'text-red-400 hover:text-red-500 hover:bg-red-50'
          : 'text-slate-400 hover:text-blue-500 hover:bg-blue-50'
        } disabled:opacity-50 disabled:cursor-not-allowed`}
      title={getTitle()}
    >
      {getIcon()}
    </button>
  );
};