import assert from 'node:assert/strict';
import test from 'node:test';
import {
  buildFeedThumbnailSvg,
  buildThumbnailSvg,
  ensureHtmlThumbnail,
  extractCoverSignals,
  generateHtmlThumbnail,
  isModernFeedThumbnail,
  resolveCoverDataUri,
  shouldUseScenicBackground,
} from './mindspace-thumbnails.mjs';
import fs from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';

test('buildThumbnailSvg escapes title text', () => {
  const svg = buildThumbnailSvg({
    title: '<script>alert(1)</script>',
    subtitle: '测试',
    accent: '#2f6f57',
  });
  assert.doesNotMatch(svg, /<script>alert/);
  assert.match(svg, /&lt;script&gt;alert/);
});

test('generateHtmlThumbnail writes svg file', async () => {
  const root = await fs.mkdtemp(path.join(os.tmpdir(), 'mindspace-thumb-'));
  const key = 'users/u1/assets/a1/thumbnail.svg';
  await generateHtmlThumbnail(
    root,
    key,
    '<!doctype html><html><head><title>测试页面</title></head><body></body></html>',
    { subtitle: 'HTML' },
  );
  const written = await fs.readFile(path.join(root, key), 'utf8');
  assert.match(written, /测试页面/);
});

test('extractCoverSignals reads mindspace-cover meta and html colors', () => {
  const html = `<!doctype html><html><head>
    <title>🇲🇾 马来西亚旅游攻略</title>
    <meta name="mindspace-cover" content='{"tag":"旅行","accent":"#ff6b35","emoji":"🇲🇾"}' />
    <style>body { background: linear-gradient(135deg, #0f0c29, #24243e); }</style>
    </head><body><h1>马来西亚旅游攻略</h1><p>沙滩、美食与城市漫步。</p></body></html>`;
  const signals = extractCoverSignals(html);
  assert.equal(signals.tag, '旅行');
  assert.equal(signals.emoji, '🇲🇾');
  assert.equal(signals.accent, '#ff6b35');
  assert.match(signals.subtitle, /沙滩/);
});

test('buildFeedThumbnailSvg uses portrait 3:4 canvas', () => {
  const svg = buildFeedThumbnailSvg({
    title: '2026 市场趋势分析',
    subtitle: 'AI 生成的研究报告',
    tag: '报告',
    emoji: '📊',
    accent: '#2f6f57',
    accent2: '#18211d',
    mood: 'report',
  });
  assert.match(svg, /width="540" height="720"/);
  assert.match(svg, /2026 市场趋势分析/);
  assert.match(svg, /filter id="grain"/);
});

test('extractCoverSignals reads cover image from mindspace-cover meta', () => {
  const html = `<!doctype html><html><head>
    <meta name="mindspace-cover" content='{"cover":"assets/hero.png","tag":"旅行"}' />
    </head><body></body></html>`;
  const signals = extractCoverSignals(html);
  assert.equal(signals.image, 'assets/hero.png');
  assert.equal(signals.tag, '旅行');
});

test('buildFeedThumbnailSvg embeds photo cover layer', () => {
  const dataUri =
    'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==';
  const svg = buildFeedThumbnailSvg(
    {
      title: '实拍封面',
      subtitle: '底图测试',
      tag: '旅行',
      accent: '#2f6f57',
      accent2: '#18211d',
    },
    { coverDataUri: dataUri },
  );
  assert.match(svg, /preserveAspectRatio="xMidYMid slice"/);
  assert.match(svg, /href="data:image\/png;base64,/);
  assert.doesNotMatch(svg, /M0 470 L90 404/);
});

test('generateHtmlThumbnail resolves relative cover image', async () => {
  const root = await fs.mkdtemp(path.join(os.tmpdir(), 'mindspace-thumb-cover-'));
  const png = Buffer.from(
    'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAFUlEQVR42mNk+M9Qz0AEYBxVSF+FABJADveWkH6oAAAAAElFTkSuQmCC',
    'base64',
  );
  await fs.mkdir(path.join(root, 'users', 'u1', 'pages', 'p1', 'versions'), { recursive: true });
  await fs.writeFile(path.join(root, 'users', 'u1', 'pages', 'p1', 'versions', 'hero.png'), png);
  const html = `<!doctype html><html><head>
    <title>封面页</title>
    <meta name="mindspace-cover" content='{"cover":"hero.png","tag":"旅行"}' />
    </head><body></body></html>`;
  const key = 'users/u1/pages/p1/thumbnail.svg';
  await generateHtmlThumbnail(root, key, html, {
    contentStorageKey: 'users/u1/pages/p1/versions/page.html',
  });
  const written = await fs.readFile(path.join(root, key), 'utf8');
  assert.match(written, /preserveAspectRatio="xMidYMid slice"/);
  assert.match(written, /href="data:image\/png;base64,/);
});

test('extractCoverSignals infers sport tag for pilates pages', () => {
  const html = '<!doctype html><html><head><title>普拉提618</title></head><body></body></html>';
  const signals = extractCoverSignals(html);
  assert.equal(signals.tag, '运动');
});

test('buildFeedThumbnailSvg uses theme gradient for sport pages', () => {
  const signals = extractCoverSignals(
    '<!doctype html><html><head><title>普拉提618</title><style>body{color:#eeb04e;background:#1a0a2e}</style></head><body></body></html>',
  );
  assert.equal(shouldUseScenicBackground(signals), false);
  const svg = buildFeedThumbnailSvg(signals);
  assert.match(svg, /id="theme"/);
  assert.doesNotMatch(svg, /M0 470 L90 404/);
});

test('isModernFeedThumbnail detects legacy landscape thumbnails', () => {
  const legacy = `<?xml version="1.0"?><svg width="640" height="400"></svg>`;
  const modern = buildFeedThumbnailSvg({
    title: '新封面',
    subtitle: '副标题',
    tag: '网页',
    accent: '#2f6f57',
    accent2: '#18211d',
  });
  assert.equal(isModernFeedThumbnail(legacy), false);
  assert.equal(isModernFeedThumbnail(modern), true);
});

test('ensureHtmlThumbnail upgrades legacy thumbnail file', async () => {
  const root = await fs.mkdtemp(path.join(os.tmpdir(), 'mindspace-thumb-upgrade-'));
  const key = 'users/u1/pages/p1/thumbnail.svg';
  const legacy = `<?xml version="1.0"?><svg width="640" height="400"><text>旧版</text></svg>`;
  await fs.mkdir(path.dirname(path.join(root, key)), { recursive: true });
  await fs.writeFile(path.join(root, key), legacy, 'utf8');
  const html = '<!doctype html><html><head><title>升级测试</title></head><body></body></html>';
  const svg = await ensureHtmlThumbnail(root, key, html, { title: '升级测试', tag: '网页' });
  assert.equal(isModernFeedThumbnail(svg), true);
  assert.match(svg, /升级测试/);
});

test('resolveCoverDataUri rejects paths outside content base', async () => {
  const root = await fs.mkdtemp(path.join(os.tmpdir(), 'mindspace-thumb-guard-'));
  const dataUri = await resolveCoverDataUri({
    storageRoot: root,
    contentStorageKey: 'users/u1/pages/p1/versions/page.html',
    imageUrl: '../../../secret.png',
  });
  assert.equal(dataUri, null);
});
