import React, { useEffect, useRef, useState } from 'react';
import { ArrowLeft, Download, FileText, CheckCircle2, ExternalLink } from 'lucide-react';
import { PaperSize, DocxStyleConfig, DocxBorder } from '../types';
import { TYPOGRAPHY_STYLES } from '../constants';
// @ts-ignore
import * as docx from 'docx';

interface PreviewProps {
  htmlContent: string;
  onBack: () => void;
  paperSize: PaperSize;
  selectedStyleId?: string | null;
}

export const Preview: React.FC<PreviewProps> = ({ htmlContent, onBack, paperSize, selectedStyleId }) => {
  const iframeRef = useRef<HTMLIFrameElement>(null);
  const [isExporting, setIsExporting] = useState(false);
  const [successMsg, setSuccessMsg] = useState(false);

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

  // Extract unique fonts for display
  const usedFonts = Array.from(new Set([
    style.wordConfig.heading1.font,
    style.wordConfig.heading2.font,
    style.wordConfig.body.font
  ])).filter(Boolean);

  // Helper to convert Points to Half-Points (docx standard)
  const pt = (points: number) => points * 2; 
  
  // Helper to convert Inches/MM to Twips
  const inchesToTwips = (inches: number) => Math.round(inches * 1440);
  const mmToTwips = (mm: number) => Math.round(mm * (1440 / 25.4));

  // Helper to map Border config to Docx Border
  const mapBorder = (b?: DocxBorder) => {
    if (!b) return undefined;
    let style = docx.BorderStyle.SINGLE;
    if (b.style === 'double') style = docx.BorderStyle.DOUBLE;
    if (b.style === 'dotted') style = docx.BorderStyle.DOTTED;
    if (b.style === 'dashed') style = docx.BorderStyle.DASHED;
    
    return {
      color: b.color,
      space: b.space,
      style: style,
      size: b.size
    };
  };

  const generateDocx = async (styleId: string) => {
    setIsExporting(true);
    try {
      const style = TYPOGRAPHY_STYLES.find(s => s.id === styleId) || TYPOGRAPHY_STYLES[0];
      const cfg = style.wordConfig;

      // PARSE HTML
      const parser = new DOMParser();
      const doc = parser.parseFromString(htmlContent, 'text/html');
      const nodes = Array.from(doc.body.childNodes);

      const docxChildren = [];

      for (const node of nodes) {
        if (node.nodeType !== Node.ELEMENT_NODE) continue;
        const el = node as HTMLElement;
        const tagName = el.tagName.toLowerCase();
        
        // --- Run Parser (Inline Styles) ---
        const parseRuns = (element: HTMLElement, baseConfig: DocxStyleConfig) => {
             const runs = [];
             for (const child of Array.from(element.childNodes)) {
                 if (child.nodeType === Node.TEXT_NODE) {
                     runs.push(new docx.TextRun({ 
                         text: child.textContent || '', 
                         font: baseConfig.font,
                         size: pt(baseConfig.size),
                         color: baseConfig.color,
                         underline: baseConfig.underline ? { type: docx.UnderlineType.SINGLE, color: baseConfig.color } : undefined,
                     }));
                 } else if (child.nodeType === Node.ELEMENT_NODE) {
                     const childEl = child as HTMLElement;
                     const isBold = childEl.tagName === 'STRONG' || childEl.tagName === 'B';
                     const isItalic = childEl.tagName === 'EM' || childEl.tagName === 'I';
                     runs.push(new docx.TextRun({ 
                         text: childEl.textContent || '', 
                         bold: isBold, 
                         italics: isItalic,
                         font: baseConfig.font,
                         size: pt(baseConfig.size),
                         color: baseConfig.color,
                         underline: baseConfig.underline ? { type: docx.UnderlineType.SINGLE, color: baseConfig.color } : undefined,
                     }));
                 }
             }
             return runs;
        };


        // --- Block Parser ---
        
        // 1. HEADINGS
        if (tagName.match(/^h[1-6]$/)) {
          const level = parseInt(tagName.replace('h', ''));
          
          // Select config based on level (simplified to H1 or H2, fallback H2 for others)
          const hCfg = level === 1 ? cfg.heading1 : cfg.heading2;
          const headingLevel = level === 1 ? docx.HeadingLevel.HEADING_1 : docx.HeadingLevel.HEADING_2;

          // Border Mapping
          const borderConfig: any = {};
          if (hCfg.border) {
             if (hCfg.border.top) borderConfig.top = mapBorder(hCfg.border.top);
             if (hCfg.border.bottom) borderConfig.bottom = mapBorder(hCfg.border.bottom);
             if (hCfg.border.left) borderConfig.left = mapBorder(hCfg.border.left);
             if (hCfg.border.right) borderConfig.right = mapBorder(hCfg.border.right);
          }

          // Alignment Mapping
          let align = docx.AlignmentType.LEFT;
          if (hCfg.align === 'center') align = docx.AlignmentType.CENTER;
          if (hCfg.align === 'right') align = docx.AlignmentType.RIGHT;
          if (hCfg.align === 'both') align = docx.AlignmentType.BOTH;

          docxChildren.push(new docx.Paragraph({
            children: [
              new docx.TextRun({
                text: el.textContent || '',
                font: hCfg.font,
                bold: hCfg.bold,
                italics: hCfg.italic,
                underline: hCfg.underline ? { type: docx.UnderlineType.SINGLE, color: hCfg.color } : undefined,
                size: pt(hCfg.size),
                color: hCfg.color,
                allCaps: hCfg.allCaps,
                smallCaps: hCfg.smallCaps,
                characterSpacing: hCfg.tracking
              })
            ],
            heading: headingLevel,
            alignment: align,
            spacing: { 
              before: hCfg.spacing?.before, 
              after: hCfg.spacing?.after,
              line: hCfg.spacing?.line
            },
            border: borderConfig,
            shading: hCfg.shading ? {
                fill: hCfg.shading.fill,
                color: hCfg.shading.color,
                type: docx.ShadingType.CLEAR // usually clear to show fill
            } : undefined,
            keepNext: true,
            keepLines: true
          }));
        } 
        
        // 2. PARAGRAPHS
        else if (tagName === 'p') {
          let align = docx.AlignmentType.LEFT;
          if (cfg.body.align === 'center') align = docx.AlignmentType.CENTER;
          if (cfg.body.align === 'right') align = docx.AlignmentType.RIGHT;
          if (cfg.body.align === 'both') align = docx.AlignmentType.BOTH;

          docxChildren.push(new docx.Paragraph({
            children: parseRuns(el, cfg.body),
            spacing: { 
              before: cfg.body.spacing?.before, 
              after: cfg.body.spacing?.after,
              line: cfg.body.spacing?.line,
              lineRule: docx.LineRuleType.AUTO
            },
            alignment: align
          }));
        }
        
        // 3. BLOCKQUOTES
        else if (tagName === 'blockquote') {
            docxChildren.push(new docx.Paragraph({
                children: parseRuns(el, { ...cfg.body, size: cfg.body.size + 1, color: cfg.accentColor, italic: true } as DocxStyleConfig),
                indent: { left: 720 }, // 0.5 inch
                border: { left: { color: cfg.accentColor, space: 10, style: docx.BorderStyle.SINGLE, size: 24 } },
                shading: { fill: "F8F8F8", type: docx.ShadingType.CLEAR, color: "auto" }, // Default light grey background for quotes
                spacing: { before: 200, after: 200, line: 300 }
            }));
        }
        
        // 4. LISTS
        else if (tagName === 'ul' || tagName === 'ol') {
            const listItems = Array.from(el.children);
            for (const li of listItems) {
                docxChildren.push(new docx.Paragraph({
                    children: parseRuns(li as HTMLElement, cfg.body),
                    bullet: { level: 0 },
                    spacing: { before: 80, after: 80 }
                }));
            }
        }
      }

      // Create Document
      const docxFile = new docx.Document({
        sections: [{
          properties: {
             page: {
                 size: {
                     width: paperSize === 'A4' ? mmToTwips(210) : inchesToTwips(8.5),
                     height: paperSize === 'A4' ? mmToTwips(297) : inchesToTwips(11),
                 },
                 margin: {
                     top: inchesToTwips(1),
                     right: inchesToTwips(1.2), 
                     bottom: inchesToTwips(1),
                     left: inchesToTwips(1.2),
                 }
             }
          },
          children: docxChildren
        }]
      });

      const blob = await docx.Packer.toBlob(docxFile);
      
      const url = window.URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = `typogenie-${style.name.replace(/\s+/g, '-').toLowerCase()}.docx`;
      a.click();
      window.URL.revokeObjectURL(url);
      
      setSuccessMsg(true);
      setTimeout(() => setSuccessMsg(false), 3000);

    } catch (e) {
      console.error("Docx Gen Error", e);
      alert("Failed to generate DOCX");
    } finally {
      setIsExporting(false);
    }
  };

  useEffect(() => {
    if (!iframeRef.current) return;
    
    // We already have 'style' from the component scope, but useEffect needs to be robust
    const currentStyle = TYPOGRAPHY_STYLES.find(s => s.id === selectedStyleId) || TYPOGRAPHY_STYLES[0];

    const doc = iframeRef.current.contentDocument;
    if (doc) {
      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="${currentStyle.googleFontsImport}" rel="stylesheet">
          <style>
            body {
              background-color: #52525b;
              display: flex;
              justify-content: center;
              padding: 40px;
              margin: 0;
              font-family: sans-serif;
            }
            .page {
              background: white;
              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;
              
              /* Inject default body color to ensure visibility in dark themes */
              color: #${currentStyle.wordConfig.body.color};

              /* User Selected Typography */
              ${currentStyle.previewCss}
            }
            
            .page * { box-sizing: border-box; }
            .page img { max-width: 100%; }
            .page table { width: 100%; border-collapse: collapse; margin-bottom: 1em; }
            .page th, .page td { border: 1px solid #ddd; padding: 8px; text-align: left; }
          </style>
        </head>
        <body>
          <div class="page">
            ${htmlContent}
          </div>
        </body>
        </html>
      `;
      doc.open();
      doc.write(html);
      doc.close();
    }
  }, [htmlContent, paperSize, selectedStyleId]);

  return (
    <div className="h-screen flex flex-col bg-zinc-900">
      {/* Toolbar */}
      <div className="sticky top-0 z-50 bg-zinc-950/90 backdrop-blur-md border-b border-zinc-800 p-4">
        <div className="max-w-7xl mx-auto flex flex-col sm:flex-row justify-between items-center gap-4">
          <button 
            onClick={onBack}
            className="flex items-center gap-2 text-zinc-400 hover:text-white transition-colors"
          >
            <ArrowLeft size={20} />
            <span>Back to Editor</span>
          </button>

          <div className="flex flex-col sm:flex-row items-center gap-6">
            
            {/* Font List */}
            <div className="flex items-center gap-2 text-sm text-zinc-500">
              <span className="hidden md:inline">Fonts:</span>
              <div className="flex gap-2">
                {usedFonts.map(font => (
                  <a 
                    key={font}
                    href={`https://fonts.google.com/specimen/${font.replace(/\s+/g, '+')}`}
                    target="_blank"
                    rel="noopener noreferrer"
                    className="px-2 py-1 bg-zinc-900 border border-zinc-800 hover:border-zinc-600 rounded text-zinc-300 hover:text-white transition-all flex items-center gap-1.5 text-xs font-medium"
                    title={`Download ${font} from Google Fonts`}
                  >
                    {font}
                    <ExternalLink size={10} />
                  </a>
                ))}
              </div>
            </div>

            <div className="h-4 w-px bg-zinc-800 hidden sm:block" />

            <div className="flex items-center gap-4">
              <span className="text-zinc-500 text-sm hidden sm:inline">
                Format: {paperSize}
              </span>
              <button
                onClick={() => {
                   // Ensure we pass a string for styleId
                   const sid = selectedStyleId || 'swiss-grid';
                   generateDocx(sid);
                }}
                disabled={isExporting}
                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' : ''}`}
              >
                {successMsg ? (
                    <><CheckCircle2 size={18} /><span>Downloaded!</span></>
                ) : (
                    <><FileText size={18} /><span>{isExporting ? 'Generating...' : 'Download Word Doc'}</span></>
                )}
              </button>
            </div>
          </div>
        </div>
      </div>

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