import React, { useEffect, useRef, useState } from 'react';
import { motion, AnimatePresence } from 'motion/react';
import { ArrowLeft, Download, FileText, CheckCircle2, ExternalLink, Loader2, ZoomIn, ZoomOut } from 'lucide-react';
import { PaperSize } from '../types';
import { StyleOption } from '../types';
import { getPreviewCss } from '../services/templateRenderer';
import { generateDocxDocument } from '../utils/docxConverter';
import ExportOptionsModal from './ExportOptionsModal';
import { open } from '@tauri-apps/plugin-shell';
import { save } from '@tauri-apps/plugin-dialog';
import { writeFile } from '@tauri-apps/plugin-fs';
import { useKeyboardNavigation } from '../hooks/useKeyboardNavigation';

interface PreviewProps {
  htmlContent: string;
  onBack: () => void;
  paperSize: PaperSize;
  selectedStyleId?: string | null;
  inputFileName?: string;
  uiZoom: number;
  onZoomChange: (zoom: number) => void;
  templates: StyleOption[];
}

// Zoom Control Component
const ZoomControl: React.FC<{ zoom: number; onZoomChange: (zoom: number) => void }> = ({ zoom, onZoomChange }) => {
  const decreaseZoom = () => onZoomChange(Math.max(50, zoom - 10));
  const increaseZoom = () => onZoomChange(Math.min(200, zoom + 10));

  return (
    <div className="flex items-center gap-2 bg-zinc-900/80 rounded-lg border border-zinc-800 px-2 py-1">
      <motion.button
        onClick={decreaseZoom}
        whileHover={{ scale: 1.1 }}
        whileTap={{ scale: 0.9 }}
        className="p-2 min-w-[44px] min-h-[44px] flex items-center justify-center text-zinc-400 hover:text-white transition-colors"
        aria-label="Zoom out"
      >
        <ZoomOut size={16} aria-hidden="true" />
      </motion.button>
      <span className="text-xs font-medium text-zinc-300 min-w-[3rem] text-center">{zoom}%</span>
      <motion.button
        onClick={increaseZoom}
        whileHover={{ scale: 1.1 }}
        whileTap={{ scale: 0.9 }}
        className="p-2 min-w-[44px] min-h-[44px] flex items-center justify-center text-zinc-400 hover:text-white transition-colors"
        aria-label="Zoom in"
      >
        <ZoomIn size={16} aria-hidden="true" />
      </motion.button>
    </div>
  );
};

// Font download component
const FontList: React.FC<{ fonts: string[] }> = ({ fonts }) => {
  const [downloadingFont, setDownloadingFont] = useState<string | null>(null);
  const [downloadStatus, setDownloadStatus] = useState<Record<string, string>>({});

  const downloadFont = async (fontName: string) => {
    setDownloadingFont(fontName);
    setDownloadStatus(prev => ({ ...prev, [fontName]: 'Downloading...' }));
    try {
      const encodedName = encodeURIComponent(fontName);
      const downloadUrl = `https://fonts.google.com/download?family=${encodedName}`;
      await open(downloadUrl);
      setDownloadStatus(prev => ({ ...prev, [fontName]: 'Opened in browser' }));
      setTimeout(() => {
        setDownloadStatus(prev => { const newStatus = { ...prev }; delete newStatus[fontName]; return newStatus; });
      }, 3000);
    } catch (err) {
      setDownloadStatus(prev => ({ ...prev, [fontName]: 'Failed' }));
    } finally {
      setDownloadingFont(null);
    }
  };

  const openGoogleFonts = async (fontName: string) => {
    try {
      const url = `https://fonts.google.com/specimen/${fontName.replace(/\s+/g, '+')}`;
      await open(url);
    } catch (err) {
      window.open(`https://fonts.google.com/specimen/${fontName.replace(/\s+/g, '+')}`, '_blank');
    }
  };

  return (
    <div className="flex items-center gap-2 text-sm text-zinc-400">
      <span className="hidden md:inline">Fonts:</span>
      <div className="flex gap-2 flex-wrap">
        {fonts.map((font, index) => (
          <motion.div key={font} className="relative group" initial={{ opacity: 0, scale: 0.8 }} animate={{ opacity: 1, scale: 1 }} transition={{ delay: index * 0.05 }}>
            <div className="flex items-center gap-1">
              <motion.button
                onClick={() => downloadFont(font)}
                disabled={downloadingFont === font}
                whileHover={{ scale: 1.05 }}
                whileTap={{ scale: 0.95 }}
                aria-label={`Download ${font} font`}
                className="px-2 py-1 bg-zinc-900 border border-zinc-800 hover:border-zinc-600 rounded-l text-zinc-300 hover:text-white transition-all flex items-center gap-1.5 text-xs font-medium"
              >
                {downloadingFont === font ? <Loader2 size={10} className="animate-spin" aria-hidden="true" /> : <Download size={10} aria-hidden="true" />}
                {font}
              </motion.button>
              <motion.button
                onClick={() => openGoogleFonts(font)}
                whileHover={{ scale: 1.05 }}
                whileTap={{ scale: 0.95 }}
                aria-label="View on Google Fonts"
                className="px-1.5 py-1 bg-zinc-900 border border-l-0 border-zinc-800 hover:border-zinc-600 rounded-r text-zinc-400 hover:text-white transition-all"
              >
                <ExternalLink size={10} aria-hidden="true" />
              </motion.button>
            </div>
            {downloadStatus[font] && (
              <motion.div className="absolute top-full left-0 mt-1 px-2 py-1 bg-zinc-800 border border-zinc-700 rounded text-xs whitespace-nowrap z-50" initial={{ opacity: 0, y: -5 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -5 }}>
                {downloadStatus[font]}
              </motion.div>
            )}
          </motion.div>
        ))}
      </div>
    </div>
  );
};

export const Preview: React.FC<PreviewProps> = ({
  htmlContent,
  onBack,
  paperSize,
  selectedStyleId,
  inputFileName = 'document',
  uiZoom,
  onZoomChange,
  templates
}) => {
  const iframeRef = useRef<HTMLIFrameElement>(null);
  const backButtonRef = useRef<HTMLButtonElement>(null);
  const saveButtonRef = useRef<HTMLButtonElement>(null);
  const [isExporting, setIsExporting] = useState(false);
  const [successMsg, setSuccessMsg] = useState(false);
  const [showExportModal, setShowExportModal] = useState(false);
  const [focusedElement, setFocusedElement] = useState<'back' | 'fonts' | 'save'>('save');
  const [exportError, setExportError] = useState<string | null>(null);

  // Get current style from templates
  const style = templates.find(s => s.id === selectedStyleId) || templates[0] || null;

  // Extract used fonts for display
  const usedFonts = style ? Array.from(new Set([
    style.typography?.fonts?.heading || style.wordConfig?.heading1?.font || 'Arial',
    style.typography?.fonts?.body || style.wordConfig?.body?.font || 'Arial'
  ])).filter(Boolean) : [];

  useKeyboardNavigation({
    onEscape: () => onBack(),
    onArrowLeft: () => { if (focusedElement === 'save') { setFocusedElement('back'); backButtonRef.current?.focus(); } },
    onArrowRight: () => { if (focusedElement === 'back') { setFocusedElement('save'); saveButtonRef.current?.focus(); } },
    onEnter: () => { if (focusedElement === 'back') onBack(); else if (focusedElement === 'save' && !isExporting) handleSave(); },
    onCtrlEnter: () => { if (!isExporting) handleSave(); },
  }, [focusedElement, isExporting, onBack]);

  useEffect(() => {
    setTimeout(() => saveButtonRef.current?.focus(), 100);
  }, []);

  const handleSave = async () => {
    setShowExportModal(true);
  };

  const handleExportConfirm = async (useTableHeaders: boolean) => {
    setShowExportModal(false);
    const sid = selectedStyleId || 'swiss-grid';
    await generateDocx(sid, useTableHeaders);
  };

  const generateDocx = async (styleId: string, useTableHeaders: boolean = false) => {
    setIsExporting(true);
    try {
      const template = templates.find(s => s.id === styleId) || templates[0];

      // Get base config from wordConfig 
      const cfg = template.wordConfig || {
        heading1: { font: 'Arial', size: 24, color: '000000', align: 'left' },
        heading2: { font: 'Arial', size: 18, color: '333333', align: 'left' },
        body: { font: 'Arial', size: 11, color: '000000', align: 'left' },
        accentColor: '000000'
      };

      // Extract page background from template
      const pageBackground = template.typography?.colors?.background;

      // Get fonts from template
      const codeFont = template.typography?.fonts?.code || template.typography?.fonts?.body || 'Consolas';

      // Detect dark theme
      const isDarkTheme = pageBackground ? parseInt(pageBackground, 16) < 0x444444 : false;

      // DEBUG: Specific markdown constructs for DOCX
      console.log('=== PREVIEW CALLING DOCX (h3, strong, table, ul/ol, li) ===');
      console.log('wordConfig h3:', JSON.stringify({ font: cfg.heading2?.font, size: cfg.body?.size, color: template.elements?.h3?.color }));
      console.log('elements h3:', JSON.stringify(template.elements?.h3));
      console.log('elements strong:', JSON.stringify(template.elements?.strong));
      console.log('elements table:', JSON.stringify(template.elements?.table));
      console.log('elements th:', JSON.stringify(template.elements?.th));
      console.log('elements td:', JSON.stringify(template.elements?.td));
      console.log('elements ul:', JSON.stringify(template.elements?.ul));
      console.log('elements ol:', JSON.stringify(template.elements?.ol));
      console.log('elements li:', JSON.stringify(template.elements?.li));
      console.log('useTableHeaders:', useTableHeaders);
      console.log('=== END PREVIEW CALL ===');

      const blob = await generateDocxDocument(htmlContent, {
        paperSize,
        heading1: cfg.heading1,
        heading2: cfg.heading2,
        body: cfg.body,
        accentColor: cfg.accentColor,
        pageBackground,
        codeFont,
        isDarkTheme,
        elements: template.elements,
        fonts: template.typography?.fonts,
        palette: template.typography?.colors,
        id: template.id,
        page: template.page,
        useTableHeaders
      });

      const arrayBuffer = await blob.arrayBuffer();
      const uint8Array = new Uint8Array(arrayBuffer);

      const defaultName = `${inputFileName}.docx`;
      const savePath = await save({
        defaultPath: defaultName,
        filters: [{ name: 'Word Document', extensions: ['docx'] }]
      });

      if (savePath) {
        await writeFile(savePath, uint8Array);
        setSuccessMsg(true);
        setTimeout(() => setSuccessMsg(false), 3000);
      }
    } catch (e) {
      console.error("Docx Gen Error", e);
      setExportError("Failed to generate DOCX: " + e);
    } finally {
      setIsExporting(false);
    }
  };

  // Track blob URL for cleanup
  const blobUrlRef = useRef<string | null>(null);

  // Render preview whenever dependencies change
  useEffect(() => {
    if (!iframeRef.current || !style) return;

    // DEBUG: Specific markdown constructs for Preview
    console.log('=== PREVIEW DEBUG (h3, strong, table, ul/ol, li) ===');
    console.log('h3:', JSON.stringify(style.elements?.h3));
    console.log('strong:', JSON.stringify(style.elements?.strong));
    console.log('table:', JSON.stringify(style.elements?.table));
    console.log('th:', JSON.stringify(style.elements?.th));
    console.log('td:', JSON.stringify(style.elements?.td));
    console.log('ul:', JSON.stringify(style.elements?.ul));
    console.log('ol:', JSON.stringify(style.elements?.ol));
    console.log('li:', JSON.stringify(style.elements?.li));
    console.log('=== END PREVIEW DEBUG ===');

    // Cleanup old blob URL
    if (blobUrlRef.current) {
      URL.revokeObjectURL(blobUrlRef.current);
      blobUrlRef.current = null;
    }

    // Get CSS from template - this generates from elements structure
    const templateCss = getPreviewCss(style);
    console.log('Generated preview CSS (first 500 chars):', templateCss.substring(0, 500));

    // Get page background from template
    const pageBg = style.typography?.colors?.background || 'ffffff';

    // Build the complete CSS - template CSS now includes .page styles
    const allCss = [
      /* Reset styles first */
      '::-webkit-scrollbar { width: 6px !important; height: 6px !important; }',
      '::-webkit-scrollbar-track { background: transparent !important; }',
      '::-webkit-scrollbar-thumb { background: #71717a !important; border-radius: 3px !important; }',
      '* { scrollbar-width: thin; scrollbar-color: #71717a transparent; box-sizing: border-box; }',
      'html, body { margin: 0; padding: 0; min-height: 100%; }',

      /* Dark outer background */
      'body { background-color: #18181b; padding: 40px 20px; }',

      /* Template CSS - includes .page styles with fonts, colors, etc. */
      templateCss,

      /* Page dimensions (not included in template CSS) */
      `.page {`,
      `  width: ${paperSize === 'A4' ? '210mm' : '8.5in'};`,
      `  min-height: ${paperSize === 'A4' ? '297mm' : '11in'};`,
      `  padding: 25mm;`,
      `  box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.4);`,
      `  box-sizing: border-box;`,
      `  margin: 0 auto;`,
      `}`,

      /* Utilities */
      '.page img { max-width: 100%; }'
    ].join('\n');

    // Inject CSS directly as inline style tag
    const html = `
      <!DOCTYPE html>
      <html>
      <head>
        <link rel="preconnect" href="https://fonts.googleapis.com">
        <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
        <link href="${style.googleFontsImport || 'https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap'}" rel="stylesheet">
        <style>
          ${allCss}
        </style>
      </head>
      <body>
        <div class="page">
          ${htmlContent}
          <script>
            console.log('--- STAGE 2: PREVIEW COMPUTED STYLES ---');
            setTimeout(() => {
              ['h1', 'h2', 'h3', 'p', 'table', 'th', 'td', 'ul', 'ol', 'li', 'blockquote', 'code', 'pre'].forEach(tag => {
                const el = document.querySelector('.page ' + tag);
                if (el) {
                  const style = window.getComputedStyle(el);
                  
                  // Get borders specifically
                  const borderTop = style.borderTopWidth + ' ' + style.borderTopStyle + ' ' + style.borderTopColor;
                  const borderBottom = style.borderBottomWidth + ' ' + style.borderBottomStyle + ' ' + style.borderBottomColor;
                  const borderLeft = style.borderLeftWidth + ' ' + style.borderLeftStyle + ' ' + style.borderLeftColor;
                  const borderRight = style.borderRightWidth + ' ' + style.borderRightStyle + ' ' + style.borderRightColor;
                  
                  console.log(\`PREVIEW \${tag.toUpperCase()}: \`, {
                    fontFamily: style.fontFamily,
                    fontSize: style.fontSize,
                    color: style.color,
                    backgroundColor: style.backgroundColor,
                    fontWeight: style.fontWeight,
                    border: \`T:\${borderTop} R:\${borderRight} B:\${borderBottom} L:\${borderLeft}\`,
                    padding: style.padding,
                    margin: style.margin
                  });
                } else {
                  console.log(\`PREVIEW \${tag.toUpperCase()}: Not found\`);
                }
              });
            }, 500);
          </script>
        </div>
      </body>
      </html>
    `;

    // Create blob URL for CSP compliance
    const blob = new Blob([html], { type: 'text/html' });
    const blobUrl = URL.createObjectURL(blob);
    blobUrlRef.current = blobUrl;
    iframeRef.current.src = blobUrl;

    // Cleanup on unmount
    return () => {
      if (blobUrlRef.current) {
        URL.revokeObjectURL(blobUrlRef.current);
        blobUrlRef.current = null;
      }
    };
  }, [htmlContent, paperSize, selectedStyleId, templates, style]);

  if (!style) {
    return <div className="h-screen flex items-center justify-center text-white" role="status">Loading...</div>;
  }

  return (
    <motion.div className="h-screen flex flex-col bg-zinc-950" initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ duration: 0.3 }}>
      <motion.div className="sticky top-0 z-50 bg-zinc-950/90 backdrop-blur-md border-b border-zinc-800 p-4" initial={{ y: -20, opacity: 0 }} animate={{ y: 0, opacity: 1 }} transition={{ duration: 0.4, ease: [0.22, 1, 0.36, 1] }}>
        <div className="max-w-7xl mx-auto flex flex-col sm:flex-row justify-between items-center gap-4">
          <motion.button ref={backButtonRef} onClick={onBack} onFocus={() => setFocusedElement('back')} whileHover={{ x: -3 }} whileTap={{ scale: 0.95 }} className="flex items-center gap-2 text-zinc-400 hover:text-white transition-colors outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 focus:ring-offset-zinc-950 rounded-lg px-2 py-1">
            <ArrowLeft size={20} aria-hidden="true" />
            <span>Back to Editor</span>
          </motion.button>

          <div className="flex flex-col sm:flex-row items-center gap-6">
            <FontList fonts={usedFonts} />
            <div className="h-4 w-px bg-zinc-800 hidden sm:block" />
            <ZoomControl zoom={uiZoom} onZoomChange={onZoomChange} />
            <div className="h-4 w-px bg-zinc-800 hidden sm:block" />
            <div className="flex items-center gap-4">
              <span className="text-zinc-400 text-sm hidden sm:inline">Format: {paperSize}</span>
              <motion.button
                ref={saveButtonRef}
                onClick={handleSave}
                onFocus={() => setFocusedElement('save')}
                disabled={isExporting}
                aria-live="polite"
                whileHover={{ scale: 1.05, boxShadow: '0 0 20px rgba(59, 130, 246, 0.4)' }}
                whileTap={{ scale: 0.95 }}
                className={`flex items-center gap-2 px-5 py-2.5 rounded-lg font-semibold transition-colors shadow-lg ${successMsg ? 'bg-emerald-600 text-white' : 'bg-blue-600 text-white hover:bg-blue-500'} ${isExporting ? 'opacity-50 cursor-wait' : ''}`}
              >
                <AnimatePresence mode="wait">
                  {successMsg ? (
                    <motion.div key="success" initial={{ scale: 0 }} animate={{ scale: 1 }} exit={{ scale: 0 }} className="flex items-center gap-2">
                      <CheckCircle2 size={18} aria-hidden="true" />
                      <span>Saved!</span>
                    </motion.div>
                  ) : (
                    <motion.div key="default" initial={{ scale: 0 }} animate={{ scale: 1 }} exit={{ scale: 0 }} className="flex items-center gap-2">
                      {isExporting ? <Loader2 size={18} className="animate-spin" aria-hidden="true" /> : <FileText size={18} aria-hidden="true" />}
                      <span>{isExporting ? 'Generating...' : 'Save Word Doc'}</span>
                    </motion.div>
                  )}
                </AnimatePresence>
              </motion.button>
            </div>
          </div>
        </div>
      </motion.div>

      <div className="flex-grow relative bg-zinc-950 overflow-hidden preview-container">
        <iframe ref={iframeRef} className="w-full h-full border-0 block" title="Report Preview" />
      </div>

      <ExportOptionsModal
        isOpen={showExportModal}
        onClose={() => setShowExportModal(false)}
        onExport={handleExportConfirm}
      />
      {exportError && (
        <div role="alert" className="fixed bottom-4 right-4 z-50 p-4 bg-red-900/90 border border-red-800 rounded-xl text-red-200 max-w-md">
          {exportError}
          <button onClick={() => setExportError(null)} className="ml-3 text-red-400 hover:text-white" aria-label="Dismiss error">&#10005;</button>
        </div>
      )}
    </motion.div>
  );
};
