/**
 * scripts/ai-hero-thumbnails.js
 *
 * Generate 10 AI feature thumbnails for blog posts. Each:
 *   - 16:9 landscape (matches the article-hero CSS aspect-ratio)
 *   - 1K resolution (we resize to 1600px wide after download)
 *   - Soft pastel palette aligned with the brand glassmorphism
 *   - No text, no letters, no words, no people (or only abstract faces)
 *   - Visually relevant to the post topic
 *
 * Result: CDN URL per prompt. We download to public/og/blog/<slug>.png,
 * resize with sharp, then update the blog_posts row.
 *
 * Run: node scripts/ai-hero-thumbnails.js
 */

'use strict';

const https = require('https');
const fs    = require('fs');
const path  = require('path');
const sharp = require('sharp');
const { spawnSync } = require('child_process');
const { db } = require('../config/db');

// 10 prompts, one per blog post slug. Each ends with a "no text / no
// people" guardrail so the model doesn't render words or recognisable
// faces. Brand palette: soft lavender → peach → coral, with indigo
// accents on a soft white field. All "16:9", "modern minimal".
const TOPICS = [
  ['ncii-takedown-complete-dmca-workflow-guide-2026',
    'Abstract illustration of a structured workflow: connected nodes and arrows flowing left to right across the composition, soft pastel gradient background of lavender to peach with indigo accent lines, no text, no words, no letters, no people, modern minimal design, 16:9 landscape'],

  ['how-to-remove-non-consensual-intimate-images-survivor-guide',
    'Abstract illustration of a protective glass shield with soft light passing through, surrounded by a soft halo, gentle lavender to peach gradient, no text, no words, no letters, no people, no faces, modern minimal design, 16:9 landscape'],

  ['onlyfans-dmca-protection-stop-leaks-at-scale',
    'Abstract illustration of a digital content library represented as a grid of soft glowing rectangles being protected by a translucent barrier, soft pastel gradient of coral and indigo, no text, no words, no letters, no people, modern minimal design, 16:9 landscape'],

  ['fansly-leak-detection-dmca-takedown-creator-workflow',
    'Abstract illustration of a detection radar sweeping across a network of nodes, soft purple and coral gradient, no text, no words, no letters, no people, modern minimal design, 16:9 landscape'],

  ['ai-generated-ncii-deepfakes-legal-landscape-2026',
    'Abstract illustration of geometric shapes fragmenting into digital pixel noise, soft pastel gradient of lavender and coral, no text, no words, no letters, no recognisable faces, no people, modern minimal design, 16:9 landscape'],

  ['chain-of-custody-digital-evidence-courts-accept',
    'Abstract illustration of a chain made of crystalline connected nodes with soft glow, soft indigo and lavender gradient, no text, no words, no letters, no people, modern minimal design, 16:9 landscape'],

  ['reverse-image-search-leak-detection-methodology',
    'Abstract illustration of concentric ripples expanding outward from a single point, soft pastel gradient of purple to coral on a soft white field, no text, no words, no letters, no people, modern minimal design, 16:9 landscape'],

  ['bulk-dmca-dispatch-agency-workflow-1000-takedowns-week',
    'Abstract illustration of multiple envelopes or paper planes fanning out from a central point, soft pastel gradient of coral and indigo, no text, no words, no letters, no people, modern minimal design, 16:9 landscape'],

  ['ncii-laws-comparison-us-eu-uk-australia-india',
    'Abstract world map made of soft glowing dots and connecting lines across continents, soft purple and coral gradient, no text, no words, no letters, no country labels, no people, modern minimal design, 16:9 landscape'],

  ['webcam-model-protection-chaturbate-stripchat-independent',
    'Abstract illustration of a camera lens with concentric circles and a soft iris, soft pastel gradient of lavender to peach, no text, no words, no letters, no people, modern minimal design, 16:9 landscape'],
];

function callMcp(req) {
  // Call the matrix MCP via the mavis CLI. Use --file to pass the
  // JSON payload — avoids any shell escaping of quotes.
  const payload = JSON.stringify(req);
  const tmp = path.join(require('os').tmpdir(), 'matrix_req_' + Date.now() + '_' + Math.random().toString(36).slice(2) + '.json');
  fs.writeFileSync(tmp, payload);
  try {
    const r = spawnSync(
      'C:/Users/shafp/.mavis/bin/mavis.cmd',
      ['mcp', 'call', 'matrix', 'matrix_generate_image', '--file', tmp],
      { encoding: 'utf8', maxBuffer: 32 * 1024 * 1024, shell: true }
    );
    if (r.status !== 0) {
      throw new Error('mavis exit ' + r.status + ': ' + (r.stderr || r.stdout || '').slice(0, 500));
    }
    return JSON.parse(r.stdout);
  } finally {
    try { fs.unlinkSync(tmp); } catch (_) {}
  }
}

function download(url, dest) {
  return new Promise((resolve, reject) => {
    const file = fs.createWriteStream(dest);
    function get(u) {
      https.get(u, { headers: { 'User-Agent': 'takedowns-app/1.6' } }, res => {
        if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
          return get(res.headers.location);
        }
        if (res.statusCode !== 200) {
          file.close();
          return reject(new Error('HTTP ' + res.statusCode + ' for ' + u));
        }
        res.pipe(file);
        file.on('finish', () => file.close(() => resolve(dest)));
      }).on('error', err => { fs.unlink(dest, () => {}); reject(err); });
    }
    get(url);
  });
}

async function generateOne(slug, prompt) {
  const result = callMcp({
    requests: [{
      prompt,
      aspect_ratio: '16:9',
      resolution: '1K',
    }],
  });
  const item = result && result.success_items && result.success_items[0];
  if (!item || !item.output_url) {
    return { slug, status: 'gen-failed', detail: JSON.stringify(result).slice(0, 200) };
  }
  const dest = path.join(__dirname, '..', 'public', 'og', 'blog', slug + '.png');
  await download(item.output_url, dest);
  // Resize to 1600px wide for web
  const tmp = dest + '.tmp';
  await sharp(dest).resize({ width: 1600, withoutEnlargement: true }).png({ quality: 90, compressionLevel: 9 }).toFile(tmp);
  fs.renameSync(tmp, dest);
  const stat = fs.statSync(dest);
  const relPath = '/public/og/blog/' + slug + '.png';
  db.prepare('UPDATE blog_posts SET hero_image_url = ?, og_image_url = ?, updated_at = ? WHERE slug = ?')
    .run(relPath, relPath, Date.now(), slug);
  return { slug, status: 'ok', url: item.output_url, size: stat.size };
}

(async () => {
  fs.mkdirSync(path.join(__dirname, '..', 'public', 'og', 'blog'), { recursive: true });
  for (const [slug, prompt] of TOPICS) {
    try {
      const r = await generateOne(slug, prompt);
      console.log(JSON.stringify(r));
    } catch (err) {
      console.log(JSON.stringify({ slug, status: 'error', error: err.message }));
    }
  }
})();
