from pathlib import Path

root = Path('/Users/bot1/Volumes/root_for_ai/AI工作区/良渚_详情页_渚咖咖啡杯_20260611_2318')
out = root / 'work' / 'commercial_v07'
out.mkdir(parents=True, exist_ok=True)

items = [
    {
        'idx': '01',
        'title': '主图01 总主图',
        'src': '../assets/web/p03_719A0886.jpg',
        'alt': '渚咖咖啡杯与礼盒主视觉',
        'phrase': '良渚文创',
        'position': '50% 78%',
        'scale': '113%',
        'left': '-6.5%',
        'fit_height': '100%'
    },
    {
        'idx': '02',
        'title': '主图02 两款同框',
        'src': '../assets/web/p05_719A0898.jpg',
        'alt': '渚咖咖啡杯两款同框展示',
        'phrase': '两款可选',
        'position': '50% 66%',
        'scale': '106%',
        'left': '-3%',
        'fit_height': '100%'
    },
    {
        'idx': '03',
        'title': '主图03 杯柄角度',
        'src': '../assets/web/p09_719A0953.jpg',
        'alt': '渚咖咖啡杯杯柄角度展示',
        'phrase': '顺手杯柄',
        'position': '50% 46%',
        'scale': '104%',
        'left': '-2%',
        'fit_height': '100%'
    },
    {
        'idx': '04',
        'title': '主图04 杯身纹样',
        'src': '../assets/web/p13_719A0999.jpg',
        'alt': '渚咖咖啡杯杯身良渚刻符纹样',
        'phrase': '良渚刻符',
        'position': '50% 56%',
        'scale': '104%',
        'left': '-2%',
        'fit_height': '100%'
    },
    {
        'idx': '05',
        'title': '主图05 礼盒场景',
        'src': '../assets/web/p01_719A0878.jpg',
        'alt': '渚咖咖啡杯杯碟与礼盒场景',
        'phrase': '雅致礼赠',
        'position': '50% 70%',
        'scale': '106%',
        'left': '-3%',
        'fit_height': '100%'
    },
]

html_tpl = '''<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<title>渚咖咖啡杯｜{title} 800×800</title>
<style>
@font-face{{font-family:XiqueZhaopai;src:url('../assets/fonts/XiqueZhaopai.ttf') format('truetype');font-display:block}}
@font-face{{font-family:XiqueJuzhen;src:url('../assets/fonts/XiqueJuzhen.ttf') format('truetype');font-display:block}}
*{{box-sizing:border-box}}
html,body{{margin:0;padding:0;background:#111;font-family:XiqueJuzhen,"PingFang SC",serif}}
#main-image{{position:relative;width:800px;height:800px;margin:0 auto;overflow:hidden;background:#15140f}}
.photo{{position:absolute;top:0;left:{left};width:{scale};height:{fit_height};object-fit:cover;object-position:{position}}}
.scrim{{position:absolute;left:0;right:0;top:0;height:232px;background:linear-gradient(180deg,rgba(10,9,7,.48) 0%,rgba(10,9,7,.18) 58%,rgba(10,9,7,0) 100%)}}
.logo{{position:absolute;top:34px;left:36px;width:150px;filter:drop-shadow(0 3px 7px rgba(0,0,0,.32))}}
.phrase{{position:absolute;top:42px;right:44px;writing-mode:vertical-rl;font-family:XiqueZhaopai,XiqueJuzhen,serif;font-weight:700;font-size:34px;line-height:1;letter-spacing:.32em;color:#F5E9D2;text-shadow:0 4px 16px rgba(0,0,0,.60)}}
</style>
</head>
<body>
<div id="main-image">
  <img class="photo" src="{src}" alt="{alt}" />
  <div class="scrim"></div>
  <img class="logo" src="../assets/brand/liangzhu_logo_thirdrow_first_ai_hires.png" alt="良渚文化" />
  <div class="phrase">{phrase}</div>
</div>
</body>
</html>
'''

for item in items:
    (out / f"main_{item['idx']}.html").write_text(html_tpl.format(**item), encoding='utf-8')

js = """const { chromium } = require('playwright');
const fs = require('fs');
const path = require('path');

const TARGETS = [
  { file: 'commercial_v07/main_01.html', selector: '#main-image', name: '渚咖咖啡杯_主图01_良渚文创_800x800', width: 800, height: 800 },
  { file: 'commercial_v07/main_02.html', selector: '#main-image', name: '渚咖咖啡杯_主图02_两款可选_800x800', width: 800, height: 800 },
  { file: 'commercial_v07/main_03.html', selector: '#main-image', name: '渚咖咖啡杯_主图03_顺手杯柄_800x800', width: 800, height: 800 },
  { file: 'commercial_v07/main_04.html', selector: '#main-image', name: '渚咖咖啡杯_主图04_良渚刻符_800x800', width: 800, height: 800 },
  { file: 'commercial_v07/main_05.html', selector: '#main-image', name: '渚咖咖啡杯_主图05_雅致礼赠_800x800', width: 800, height: 800 },
];

(async () => {
  const root = path.resolve(__dirname, '..');
  const outDir = path.join(root, 'deliverables', 'commercial_v07');
  fs.mkdirSync(outDir, { recursive: true });
  const browser = await chromium.launch({ channel: 'chrome', headless: true });
  const page = await browser.newPage({ viewport: { width: 1000, height: 1000 }, deviceScaleFactor: 1 });
  const results = [];
  let failed = false;

  for (const t of TARGETS) {
    const htmlPath = path.join(__dirname, t.file);
    await page.goto('file://' + htmlPath, { waitUntil: 'load' });
    await page.waitForLoadState('networkidle');
    await page.evaluate(async () => {
      if (document.fonts && document.fonts.ready) await document.fonts.ready;
      await Promise.all(Array.from(document.images).map(img => img.complete ? true : new Promise(resolve => { img.onload = img.onerror = resolve; })));
    });

    const box = await page.locator(t.selector).evaluate(el => ({ width: el.offsetWidth, height: el.offsetHeight }));
    const broken = await page.evaluate(() => Array.from(document.images).filter(i => !i.naturalWidth).map(i => i.getAttribute('src')));
    const fontsOk = await page.evaluate(() => document.fonts && document.fonts.status === 'loaded');
    const visibleText = await page.locator(t.selector).innerText();
    const noLogoPad = await page.evaluate(() => !document.querySelector('.logo-pad'));

    const pngPath = path.join(outDir, `${t.name}.png`);
    const jpgPath = path.join(outDir, `${t.name}.jpg`);
    await page.locator(t.selector).screenshot({ path: pngPath });
    await page.locator(t.selector).screenshot({ path: jpgPath, type: 'jpeg', quality: 92 });

    const checks = {
      sizeOk: box.width === t.width && box.height === t.height,
      noBrokenImages: broken.length === 0,
      fontsLoaded: fontsOk,
      noLogoPad,
      visibleText,
      visibleTextLength: Array.from(visibleText.trim()).length,
      pngBytes: fs.statSync(pngPath).size,
      jpgBytes: fs.statSync(jpgPath).size,
    };
    if (!checks.sizeOk || !checks.noBrokenImages || !checks.fontsLoaded || !checks.noLogoPad || checks.visibleTextLength > 4 || checks.pngBytes < 30000) failed = true;
    results.push({ ...t, box, broken, checks, png: pngPath, jpg: jpgPath });
  }

  await browser.close();
  fs.writeFileSync(path.join(outDir, 'export_manifest.json'), JSON.stringify({ results, exportedAt: new Date().toISOString() }, null, 2));
  console.log(JSON.stringify({ ok: !failed, results: results.map(r => ({ name: r.name, box: r.box, checks: r.checks })) }, null, 2));
  if (failed) process.exit(1);
})();
"""
(root / 'work' / 'export_commercial_v07.js').write_text(js, encoding='utf-8')

print('created', out)
print('created', root / 'work' / 'export_commercial_v07.js')
