const JSZip = require('jszip');
const fs = require('fs');
const path = require('path');

// EMU to inches: 1 inch = 914400 EMU
// Slide: 9144000 x 5143500 EMU = 10" x 5.625"
const EMU = 914400;
const SLIDE_W = 9144000;
const SLIDE_H = 5143500;
const SCALE = 960 / 10; // 96px per inch (at 100%)

function emuToPx(emu) {
  return (emu / EMU) * SCALE;
}

function hexToRgb(hex) {
  if (!hex || hex.length < 6) return '#888888';
  return '#' + hex.slice(-6);
}

async function renderSlideHtml(xml, slideNum) {
  // Extract background color
  const bgMatch = xml.match(/p:bg>.*?<a:srgbClr val="([A-Fa-f0-9]{6})"/s);
  const bgColor = bgMatch ? '#' + bgMatch[1] : '#F5F7FA';
  
  // Parse all shapes and text boxes
  const shapes = [];
  
  // Find all spTree child elements (sp = shape/textbox, pic = image)
  const spPattern = /<p:sp>(.+?)<\/p:sp>/gs;
  let spMatch;
  while ((spMatch = spPattern.exec(xml)) !== null) {
    const spXml = spMatch[1];
    
    // Get position
    const offMatch = spXml.match(/<a:off x="(-?\d+)" y="(-?\d+)"/);
    const extMatch = spXml.match(/<a:ext cx="(\d+)" cy="(\d+)"/);
    if (!offMatch || !extMatch) continue;
    
    const x = emuToPx(parseInt(offMatch[1]));
    const y = emuToPx(parseInt(offMatch[2]));
    const w = emuToPx(parseInt(extMatch[1]));
    const h = emuToPx(parseInt(extMatch[2]));
    
    // Get fill color
    const fillMatch = spXml.match(/p:spPr[\s\S]*?<a:srgbClr val="([A-Fa-f0-9]{6})"/);
    const fillColor = fillMatch ? '#' + fillMatch[1] : null;
    
    // Get text content
    const texts = [];
    const paraPattern = /<a:p>([\s\S]*?)<\/a:p>/g;
    let paraMatch;
    while ((paraMatch = paraPattern.exec(spXml)) !== null) {
      const paraXml = paraMatch[1];
      const textMatches = [...paraXml.matchAll(/<a:t[^>]*>([^<]*)<\/a:t>/g)];
      const paraText = textMatches.map(m => m[1]).join('');
      if (paraText.trim()) texts.push(paraText.trim());
    }
    
    // Get font size
    const szMatch = spXml.match(/sz="(\d+)"/);
    const fontSize = szMatch ? parseInt(szMatch[1]) / 100 : 12;
    
    // Get text color
    const txtColorMatch = spXml.match(/<a:t>[\s\S]*?<a:srgbClr val="([A-Fa-f0-9]{6})"/);
    const txtColor = txtColorMatch ? '#' + txtColorMatch[1] : '#FFFFFF';
    
    shapes.push({ x, y, w, h, fillColor, texts, fontSize, txtColor });
  }
  
  // Build HTML
  let shapesHtml = '';
  for (const s of shapes) {
    const bgStyle = s.fillColor ? `background-color: ${s.fillColor};` : '';
    const textContent = s.texts.join('<br>');
    shapesHtml += `<div style="position:absolute;left:${s.x.toFixed(1)}px;top:${s.y.toFixed(1)}px;width:${s.w.toFixed(1)}px;height:${s.h.toFixed(1)}px;${bgStyle}overflow:hidden;box-sizing:border-box;padding:2px 4px;">
      <div style="font-size:${Math.min(s.fontSize, 20)}px;color:${s.txtColor};font-family:Arial,sans-serif;overflow:hidden;">${textContent}</div>
    </div>`;
  }
  
  return `<div style="position:relative;width:960px;height:540px;background-color:${bgColor};overflow:hidden;border:1px solid #333;flex-shrink:0;">
    <div style="position:absolute;top:2px;right:4px;font-size:10px;color:rgba(128,128,128,0.5);z-index:999">${slideNum}</div>
    ${shapesHtml}
  </div>`;
}

async function createPreview(pptxPath, outputPath) {
  const data = fs.readFileSync(pptxPath);
  const zip = await JSZip.loadAsync(data);
  
  const slideFiles = Object.keys(zip.files)
    .filter(f => f.match(/^ppt\/slides\/slide\d+\.xml$/))
    .sort((a, b) => {
      const na = parseInt(a.match(/slide(\d+)/)[1]);
      const nb = parseInt(b.match(/slide(\d+)/)[1]);
      return na - nb;
    });
  
  let slidesHtml = '';
  for (const sf of slideFiles) {
    const slideNum = parseInt(sf.match(/slide(\d+)/)[1]);
    const xml = await zip.file(sf).async('string');
    slidesHtml += await renderSlideHtml(xml, slideNum);
  }
  
  const html = `<!DOCTYPE html>
<html><head><meta charset="utf-8">
<title>${path.basename(pptxPath)}</title>
<style>
body { background: #1a1a1a; font-family: Arial; margin: 0; padding: 20px; }
h2 { color: #fff; font-size: 14px; margin-bottom: 10px; }
.slides { display: flex; flex-direction: column; gap: 16px; align-items: flex-start; }
</style>
</head><body>
<h2>${path.basename(pptxPath)}</h2>
<div class="slides">${slidesHtml}</div>
</body></html>`;
  
  fs.writeFileSync(outputPath, html);
  console.log(`Preview: ${outputPath} (${slideFiles.length} slides)`);
}

(async () => {
  await createPreview(
    'E:/test/삼성디스플레이 vs LG디스플레이 비교 분석 보고서_20260407_1958.pptx',
    'C:/Users/admin/AppData/Local/Temp/pptx_gen/preview1.html'
  );
  await createPreview(
    'E:/test/삼성디스플레이 사업 영역 및 제품 강점 분석 보고서_20260407_1956.pptx',
    'C:/Users/admin/AppData/Local/Temp/pptx_gen/preview2.html'
  );
})();
