import { useState, useRef, useEffect } from 'react';
import { Editor } from '@tinymce/tinymce-react';
import * as htmlToImage from 'html-to-image';
import { jsPDF } from 'jspdf';
import './App.css';

// Import TinyMCE
import 'tinymce/tinymce';
import 'tinymce/models/dom/model';
import 'tinymce/themes/silver';
import 'tinymce/icons/default';

// Import Plugins
import 'tinymce/plugins/advlist';
import 'tinymce/plugins/autolink';
import 'tinymce/plugins/lists';
import 'tinymce/plugins/link';
import 'tinymce/plugins/image';
import 'tinymce/plugins/charmap';
import 'tinymce/plugins/preview';
import 'tinymce/plugins/anchor';
import 'tinymce/plugins/searchreplace';
import 'tinymce/plugins/visualblocks';
import 'tinymce/plugins/code';
import 'tinymce/plugins/fullscreen';
import 'tinymce/plugins/insertdatetime';
import 'tinymce/plugins/media';
import 'tinymce/plugins/table';
import 'tinymce/plugins/help';
import 'tinymce/plugins/wordcount';

function App() {
  const [content, setContent] = useState('');
  const [width, setWidth] = useState(1100); // Print/Container Width
  const [contentWidth, setContentWidth] = useState(800); // Inner Content Width
  const [padding, setPadding] = useState(40); // New Padding State
  const [format, setFormat] = useState('png');
  const [backgroundColor, setBackgroundColor] = useState('#ffffff');
  const [fontFamily, setFontFamily] = useState('Batang'); // New Font State default: Batang
  const [previewUrl, setPreviewUrl] = useState(null);
  const [zoom, setZoom] = useState(1);
  const [isGenerating, setIsGenerating] = useState(false);
  const [isOptimized, setIsOptimized] = useState(true); // Default True
  const [lineHeight, setLineHeight] = useState(160); // Default 160%
  const [isFitToWidth, setIsFitToWidth] = useState(false); // Fit content to width
  const [editorKey, setEditorKey] = useState(0);
  const [windowSize, setWindowSize] = useState({ width: window.innerWidth, height: window.innerHeight });
  const [editorSize, setEditorSize] = useState({ width: 0, height: 0 });
  const editorRef = useRef(null);

  // Resize Listener
  useState(() => {
    const handleResize = () => {
      setWindowSize({ width: window.innerWidth, height: window.innerHeight });
      const container = document.querySelector('.editor-container');
      if (container) {
        setEditorSize({ width: container.clientWidth, height: container.clientHeight });
      }
    };
    window.addEventListener('resize', handleResize);
    // Initial check
    setTimeout(handleResize, 500);

    return () => window.removeEventListener('resize', handleResize);
  }, []);

  // Editor Resize Observer (for more accurate updates)
  useState(() => {
    const observer = new ResizeObserver(entries => {
      for (let entry of entries) {
        setEditorSize({ width: entry.contentRect.width, height: entry.contentRect.height });
      }
    });
    const container = document.querySelector('.editor-container');
    if (container) observer.observe(container);
    return () => observer.disconnect();
  }, []);

  // Settings Initialization & Sync
  useEffect(() => {
    async function initSettings() {
      if (window.electronAPI) {
        const saved = await window.electronAPI.getSettings();
        if (saved.appSettings) {
          const s = saved.appSettings;
          if (s.width) setWidth(s.width);
          if (s.contentWidth) setContentWidth(s.contentWidth);
          if (s.padding) setPadding(s.padding);
          if (s.backgroundColor) setBackgroundColor(s.backgroundColor);
          if (s.fontFamily) setFontFamily(s.fontFamily);
          if (s.lineHeight) setLineHeight(s.lineHeight);
          if (s.isOptimized !== undefined) setIsOptimized(s.isOptimized);
          if (s.isFitToWidth !== undefined) setIsFitToWidth(s.isFitToWidth);
        }
      }
    }
    initSettings();
  }, []);

  // Persist Settings on Change
  useEffect(() => {
    if (window.electronAPI) {
      const settings = {
        width,
        contentWidth,
        padding,
        backgroundColor,
        fontFamily,
        lineHeight,
        isOptimized,
        isFitToWidth
      };
      // Simple debounce to avoid too many writes
      const timeout = setTimeout(() => {
        window.electronAPI.updateSettings({ appSettings: settings });
      }, 500);
      return () => clearTimeout(timeout);
    }
  }, [width, contentWidth, padding, backgroundColor, fontFamily, lineHeight, isOptimized, isFitToWidth]);

  const fontOptions = [
    { value: 'Noto Sans KR', label: 'Noto Sans KR (Default)' },
    { value: 'Malgun Gothic', label: 'Malgun Gothic (맑은 고딕)' },
    { value: 'Dotum', label: 'Dotum (돋움)' },
    { value: 'Gulim', label: 'Gulim (굴림)' },
    { value: 'Batang', label: 'Batang (바탕)' },
    { value: 'Arial', label: 'Arial' },
  ];

  const handleImportHTML = async () => {
    if (window.electronAPI) {
      const result = await window.electronAPI.openFile();
      if (result.success) {
        // Simple extraction of body content if full HTML is provided
        let newContent = result.content;
        const bodyMatch = newContent.match(/<body[^>]*>([\s\S]*)<\/body>/i);
        if (bodyMatch && bodyMatch[1]) {
          newContent = bodyMatch[1];
        }
        setContent(newContent);
        setEditorKey(prev => prev + 1); // Force Editor Re-mount
        alert('파일을 불러왔습니다.');
      } else if (result.message !== 'Cancelled') {
        alert(`오류: ${result.message}`);
      }
    } else {
      alert('Electron 환경이 아닙니다.');
    }
  };



  const handleEditorChange = (newValue, editor) => {
    setContent(newValue);
  };

  const generateImage = async (overrideFormat = null) => {
    if (!content) {
      alert('내용을 먼저 입력해주세요.');
      return null;
    }

    const currentFormat = overrideFormat || format;
    setIsGenerating(true);

    try {
      // Revert: PixelRatio is controlled by Optimization (1 or 2)
      // Scale is now "Browser Zoom" handled via CSS
      const options = {
        width: parseInt(width),
        pixelRatio: isOptimized ? 1 : 2
      };

      const tempContainer = document.createElement('div');
      tempContainer.style.position = 'fixed';
      tempContainer.style.top = '0';
      tempContainer.style.left = '0';

      // Ensure width includes padding if we want 'width' to be the final image width
      // But html-to-image takes the element size. 
      // styling width matches user input.
      tempContainer.style.width = `${width}px`;
      tempContainer.style.backgroundColor = backgroundColor;
      tempContainer.style.zIndex = '-9999';
      tempContainer.style.visibility = 'visible';

      tempContainer.style.visibility = 'visible';

      // Dynamic Font Family
      const fontStack = `'${fontFamily}', 'Malgun Gothic', 'Dotum', Helvetica, Arial, sans-serif`;

      tempContainer.style.fontFamily = fontStack;
      tempContainer.style.fontSize = '14px';
      tempContainer.style.lineHeight = `${lineHeight / 100}`;

      // FIX: Truncation Issues & User Defined Padding
      tempContainer.style.paddingTop = `${padding}px`;
      tempContainer.style.paddingBottom = `${padding}px`;
      tempContainer.style.paddingLeft = `${padding}px`;
      tempContainer.style.paddingRight = `${parseInt(padding) + 30}px`; // Extra padding on right as requested
      tempContainer.style.boxSizing = 'border-box';
      tempContainer.style.color = '#333';

      // Inject Global Styles
      const styleBlock = document.createElement('style');
      styleBlock.innerHTML = `
        @font-face {
          font-family: 'Noto Sans KR';
          src: url('fonts/NotoSansKR-Regular.otf') format('opentype');
        }
        * {
           font-family: ${fontStack} !important;
           box-sizing: border-box !important; /* Critical for layout safety */
        }
        body, p, span, div, td, th, li {
          color: #000 !important;
          background-color: transparent !important; 
          overflow-wrap: break-word; /* Prevent right-side overflow */
          word-break: break-all; /* Break long words if necessary */
        }
        span[style*="color: white"], span[style*="color: #ffffff"], span[style*="color: #FFF"] {
          color: #000 !important;
        }
        /* Table Fixes */
        table {
          width: 95% !important; /* Conservative width as requested */
          max-width: 95% !important; /* Never exceed container */
          margin: 0 auto !important; /* Center tables, safe because of max-width */
          table-layout: fixed; /* Helps calculation */
        }
        td, th {
          border-color: #000 !important;
          overflow-wrap: break-word; /* Ensure cell content doesn't overflow */
        }
        img {
          max-width: 100% !important;
          height: auto !important;
        }
      `;
      tempContainer.appendChild(styleBlock);

      const contentWrapper = document.createElement('div');
      contentWrapper.className = 'export-content-wrapper';
      contentWrapper.style.width = `${contentWidth}px`; // Use explicit Content Width
      contentWrapper.style.maxWidth = '100%';
      contentWrapper.style.margin = '0 auto'; // Center it
      contentWrapper.style.height = 'auto';

      // Auto-Fit Logic: Scale content to fill container Width
      if (isFitToWidth) {
        const horizontalPadding = parseInt(padding) * 2 + 30;
        const availableWidth = Math.max(0, parseInt(width) - horizontalPadding);
        const scale = availableWidth / contentWidth;
        contentWrapper.style.zoom = scale;
      }

      contentWrapper.innerHTML = content;

      tempContainer.appendChild(contentWrapper);
      document.body.appendChild(tempContainer);

      await new Promise(resolve => setTimeout(resolve, 500));

      const contentHeight = tempContainer.scrollHeight;
      tempContainer.style.height = `${contentHeight}px`;

      const captureOptions = {
        ...options,
        height: contentHeight,
        backgroundColor: backgroundColor,
        style: {
          height: `${contentHeight}px`,
          overflow: 'visible',
          backgroundColor: backgroundColor
        }
      };

      const captureTarget = tempContainer;
      let dataUrl;

      if (currentFormat === 'pdf') {
        const imgData = await htmlToImage.toPng(captureTarget, captureOptions);
        const pdf = new jsPDF({
          orientation: width > contentHeight ? 'landscape' : 'portrait',
          unit: 'px',
          format: [width, contentHeight]
        });
        pdf.addImage(imgData, 'PNG', 0, 0, width, contentHeight);
        dataUrl = pdf.output('datauristring');
      } else if (currentFormat === 'html') {
        // HTML Export Logic with Data URI Images

        // 1. Convert all images in tempContainer to Data URIs
        const images = tempContainer.getElementsByTagName('img');
        for (let img of images) {
          try {
            // If it's already a data URL, skip
            if (img.src.startsWith('data:')) continue;

            if (isOptimized) {
              // Optimization: Draw to canvas and compress
              const canvas = document.createElement('canvas');
              canvas.width = img.naturalWidth;
              canvas.height = img.naturalHeight;
              const ctx = canvas.getContext('2d');
              ctx.drawImage(img, 0, 0);
              // Use JPEG quality 0.8 for good balance
              img.src = canvas.toDataURL('image/jpeg', 0.8);
            } else {
              // Original: Fetch blob and convert preserving original
              const response = await fetch(img.src);
              const blob = await response.blob();
              await new Promise((resolve, reject) => {
                const reader = new FileReader();
                reader.onloadend = () => {
                  img.src = reader.result;
                  resolve();
                };
                reader.onerror = reject;
                reader.readAsDataURL(blob);
              });
            }
          } catch (e) {
            console.warn('Failed to convert image to Data URI:', img.src, e);
          }
          // Ensure styles are inline for safety
          img.style.maxWidth = '100%';
          img.style.height = 'auto';
        }

        // 2. Wrap in proper HTML structure
        const fullHtml = `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
${styleBlock.innerHTML}
body { 
    margin: 0; 
    padding: 0; 
    background-color: ${backgroundColor}; 
    font-family: ${fontStack};
}
.export-content-wrapper {
    width: ${contentWidth}px;
    margin: 0 auto; /* Center it */
    padding: ${padding}px;
    background-color: #fff;
    box-sizing: border-box;
}
</style>
</head>
<body>
<div class="export-content-wrapper">
${contentWrapper.innerHTML}
</div>
</body>
</html>`;
        // 3. Convert string to Base64 Data URL
        dataUrl = `data:text/html;base64,${btoa(unescape(encodeURIComponent(fullHtml)))}`;

      } else {
        switch (currentFormat) {
          case 'jpeg':
            dataUrl = await htmlToImage.toJpeg(captureTarget, { ...captureOptions, backgroundColor: backgroundColor });
            break;
          case 'webp':
            dataUrl = await htmlToImage.toPng(captureTarget, captureOptions); // html-to-image doesn't have toWebp natively in all versions, sticking to Png for now or using Canvas if needed. 
            // Actually, let's just use Png as fallback as before.
            break;
          case 'png':
          default:
            dataUrl = await htmlToImage.toPng(captureTarget, captureOptions);
            break;
        }
      }

      document.body.removeChild(tempContainer);
      return dataUrl;

    } catch (error) {
      console.error('Generation failed:', error);
      alert('생성에 실패했습니다. 콘솔을 확인해주세요.');
      return null;
    } finally {
      setIsGenerating(false);
    }
  };

  const handlePreview = async () => {
    setZoom(1);
    // Always use PNG for the preview display itself
    const url = await generateImage();
    if (url) {
      setPreviewUrl(url);
    }
  };

  const handleSaveFormat = async (targetFormat) => {
    setIsGenerating(true);
    try {
      // We temporarily pass the target format to generateImage
      // Since generateImage uses the 'format' state, we could either update state or modify the function.
      // Let's modify generateImage slightly to accept an optional format override.
      const url = await generateImage(targetFormat);
      if (url) {
        if (window.electronAPI) {
          const result = await window.electronAPI.saveImage(url, targetFormat);
          if (result.success) {
            alert(`저장되었습니다: ${result.filePath}`);
          } else if (result.message !== 'Cancelled') {
            alert(`오류: ${result.message}`);
          }
        } else {
          alert('Electron API를 찾을 수 없습니다.');
        }
      }
    } finally {
      setIsGenerating(false);
    }
  };

  const handleClosePreview = () => {
    setPreviewUrl(null);
    setZoom(1);
  };

  const handleWheel = (e) => {
    // Only Zoom if CTRL is pressed
    if (e.ctrlKey) {
      e.preventDefault();
      const delta = e.deltaY * -0.001;
      setZoom(prev => Math.min(Math.max(0.1, prev + delta), 5));
    }
    // Otherwise Native Scroll happens automatically due to overflow: auto in CSS
  };

  const handleSaveFromPreview = async () => {
    if (!previewUrl) return;

    if (window.electronAPI) {
      const result = await window.electronAPI.saveImage(previewUrl, format);
      if (result.success) {
        alert(`저장되었습니다: ${result.filePath}`);
      } else if (result.message !== 'Cancelled') {
        alert(`오류: ${result.message}`);
      }
    } else {
      console.log('Exported Data URL (truncated):', previewUrl.slice(0, 50) + '...');
      alert('Electron API를 찾을 수 없습니다. 콘솔에서 Data URL을 확인하세요.');
    }
  };

  return (
    <div className="app-container">
      <header className="toolbar">
        <div className="toolbar-group">
          <span className="group-label">레이아웃</span>
          <label title="전체 이미지(인쇄물) 가로 사이즈">
            인쇄 너비:
            <input
              type="number"
              value={width}
              onChange={(e) => setWidth(e.target.value)}
              min="500"
              max="3000"
              className="compact-input"
            />
          </label>
          <label title="실제 텍스트가 들어가는 영역 너비">
            본문 너비:
            <input
              type="number"
              value={contentWidth}
              onChange={(e) => setContentWidth(e.target.value)}
              min="200"
              max={width} // Cannot exceed container
              className="compact-input"
            />
          </label>
          <label>
            여백:
            <input
              type="number"
              value={padding}
              onChange={(e) => setPadding(e.target.value)}
              min="0"
              max="500"
              className="compact-input"
            />
          </label>
          <label className="checkbox-label" title="본문을 인쇄 너비에 맞춰 확대합니다">
            <input
              type="checkbox"
              checked={isFitToWidth}
              onChange={(e) => setIsFitToWidth(e.target.checked)}
            />
            가로 맞춤
          </label>
        </div>

        <div className="toolbar-group">
          <span className="group-label">스타일</span>
          <label>
            글꼴:
            <select value={fontFamily} onChange={(e) => setFontFamily(e.target.value)} className="compact-select">
              {fontOptions.map(option => (
                <option key={option.value} value={option.value}>{option.label}</option>
              ))}
            </select>
          </label>
          <label title="배경색">
            배경:
            <input
              type="color"
              value={backgroundColor}
              onChange={(e) => setBackgroundColor(e.target.value)}
              className="color-input"
            />
          </label>
        </div>

        <div className="toolbar-group">
          <span className="group-label">저장 옵션</span>
          <label>
            줄 간격:
            <select value={lineHeight} onChange={(e) => setLineHeight(Number(e.target.value))} className="compact-select">
              {[100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 220, 250].map(h => (
                <option key={h} value={h}>{h}%</option>
              ))}
            </select>
          </label>
        </div>

        <div className="toolbar-actions">
          <button onClick={handleImportHTML} className="secondary-btn" disabled={isGenerating}>
            HTML 불러오기
          </button>
          <button onClick={handlePreview} className="primary-btn" disabled={isGenerating}>
            {isGenerating ? '생성 중...' : '미리보기 및 내보내기'}
          </button>
        </div>
      </header>

      <div className="editor-wrapper-outer">
        <div className="editor-container" style={{ backgroundColor: 'white' }}>
          <Editor
            key={editorKey} // Force re-mount when key changes (import)
            onInit={(evt, editor) => editorRef.current = editor}
            initialValue={content} // Use initialValue instead of value for IME
            onEditorChange={handleEditorChange}
            init={{
              height: '100%',
              width: '100%',
              menubar: true,
              plugins: [
                'advlist', 'autolink', 'lists', 'link', 'image', 'charmap',
                'preview', 'anchor', 'searchreplace', 'visualblocks', 'code',
                'fullscreen', 'insertdatetime', 'media', 'table', 'help', 'wordcount'
              ],
              toolbar: 'undo redo | blocks | ' +
                'fontfamily fontsize | ' +
                'bold italic forecolor | alignleft aligncenter ' +
                'alignright alignjustify | bullist numlist outdent indent | ' +
                'removeformat | table | image | help',
              content_style: `
                  @font-face {
                    font-family: 'Noto Sans KR';
                    src: url('fonts/NotoSansKR-Regular.otf') format('opentype');
                  }
                  /* Force text color to avoid 'White on White' from Word paste */
                  body { 
                    font-family: '${fontFamily}', 'Noto Sans KR', 'Malgun Gothic', 'Dotum', Helvetica, Arial, sans-serif; 
                    font-size: 14px; 
                    color: #333 !important; 
                    background-color: #fff !important;
                  }
                  /* Ensure spans from Word don't hide text if they are white */
                  span[style*="color: white"], span[style*="color: #ffffff"], span[style*="color: #FFF"] {
                    color: #333 !important;
                    background-color: #eee; /* Highlight originally white text slightly */
                  }
                `,
              font_formats: 'Noto Sans KR=Noto Sans KR;Malgun Gothic=Malgun Gothic;Dotum=Dotum;Gulim=Gulim;Batang=Batang;Arial=arial,helvetica,sans-serif;',
              branding: false,
              promotion: false,
              license_key: 'gpl',
              skin_url: 'tinymce/skins/ui/oxide',
            }}
          />
        </div>
      </div>

      <p className="hint">
        저장하기 전에 "미리보기 및 내보내기"를 클릭하여 이미지를 확인하세요.
      </p>

      {/* Loading Overlay */}
      {isGenerating && (
        <div className="loading-overlay">
          <div className="loading-content">
            <div className="loading-spinner"></div>
            <p>이미지 생성 중...</p>
          </div>
        </div>
      )}

      {/* Preview Modal */}
      {previewUrl && (
        <div className="preview-modal-overlay">
          <div className="preview-modal-content">
            <div className="preview-header">
              <div className="preview-title-group">
                <h3>이미지 미리보기</h3>
                <label className="checkbox-label" style={{ marginLeft: '20px' }}>
                  <input
                    type="checkbox"
                    checked={isOptimized}
                    onChange={(e) => setIsOptimized(e.target.checked)}
                  />
                  웹 최적화
                </label>
              </div>
              <div className="export-actions-group">
                <button onClick={() => handleSaveFormat('png')} className="format-btn">PNG 저장</button>
                <button onClick={() => handleSaveFormat('jpeg')} className="format-btn">JPEG 저장</button>
                <button onClick={() => handleSaveFormat('webp')} className="format-btn">WEBP 저장</button>
                <button onClick={() => handleSaveFormat('pdf')} className="format-btn">PDF 저장</button>
                <button onClick={() => handleSaveFormat('html')} className="format-btn html">HTML 저장</button>
                <button onClick={handleClosePreview} className="close-btn">닫기</button>
              </div>
            </div>
            <div className="preview-body" onWheel={handleWheel}>
              <div className="preview-scroll-container">
                <img
                  src={previewUrl}
                  alt="Preview"
                  style={{
                    width: `${zoom * 100}%`,
                    maxWidth: 'none',
                    height: 'auto',
                    transition: 'width 0.1s ease-out'
                  }}
                />
              </div>
            </div>
          </div>
        </div>
      )}
      {/* Status Bar */}
      <footer className="status-bar">
        <div className="status-item">Window: {windowSize.width} x {windowSize.height}</div>
        <div className="status-item">Editor: {Math.round(editorSize.width)} x {Math.round(editorSize.height)}</div>
        <div className="status-item">Zoom: {Math.round(zoom * 100)}%</div>
      </footer>
    </div>
  );
}

export default App;
