const path = require('path');
const pptxgen = require('pptxgenjs');

const base = __dirname;
const outPath = path.join(base, 'prezentaciya-vampiricheskoe-tenevoe-pravitelstvo.pptx');
const assets = {
  title: path.join(base, 'assets', 'generated', '01-title-food-chain.png'),
  medieval: path.join(base, 'assets', 'generated', '02-medieval-origin.png'),
  classes: path.join(base, 'assets', 'generated', '03-vampire-classes.png'),
  failed: path.join(base, 'assets', 'generated', '04-failed-infection.png'),
  recognize: path.join(base, 'assets', 'generated', '05-recognize-vampire.png'),
  blood: path.join(base, 'assets', 'generated', '06-blood-economy.png'),
  artificial: path.join(base, 'assets', 'generated', '07-artificial-blood.png'),
  market: path.join(base, 'assets', 'generated', '08-hidden-donor-market.png'),
  donorHouse: path.join(base, 'assets', 'generated', '09-donor-house.png'),
  etiquette: path.join(base, 'assets', 'generated', '10-blood-etiquette.png'),
  zones: path.join(base, 'assets', 'generated', '11-feeding-zones-map.png'),
  chain: path.join(base, 'assets', 'generated', '12-food-chain-chart.png')
};

const pptx = new pptxgen();
pptx.layout = 'LAYOUT_WIDE';
pptx.author = 'Hermes Agent';
pptx.company = 'Nous Research';
pptx.subject = 'Псевдонаучная теория о гемозависимой элите';
pptx.title = 'Пищевая цепочка: от тебя до теневого правительства';
pptx.lang = 'ru-RU';
pptx.theme = {
  headFontFace: 'Aptos Display',
  bodyFontFace: 'Aptos',
  lang: 'ru-RU'
};

const C = {
  bgDark: '130B0D',
  bgLight: 'F4EEE7',
  card: 'FFF8F2',
  red: '7A1623',
  red2: 'A42A37',
  text: '24181A',
  cream: 'F5E6D3',
  gold: 'C7A56A',
  muted: '705A5D',
  line: 'D8C2B8',
  white: 'FFFFFF',
  ink: '2A1A1D'
};

function baseLight(slide, title, tag = 'Псевдонаучная реконструкция') {
  slide.background = { color: C.bgLight };
  slide.addShape(pptx.ShapeType.rect, { x: 0, y: 0, w: 13.333, h: 0.45, fill: { color: C.red }, line: { color: C.red } });
  slide.addText(title, { x: 0.55, y: 0.56, w: 9.2, h: 0.4, fontFace: 'Aptos Display', fontSize: 27, bold: true, color: C.ink, margin: 0 });
  slide.addText(tag, { x: 10.2, y: 0.6, w: 2.4, h: 0.18, fontSize: 10, color: C.red2, italic: true, align: 'right', margin: 0 });
}

function baseDark(slide, title, subtitle = '') {
  slide.background = { color: C.bgDark };
  slide.addShape(pptx.ShapeType.rect, { x: 0, y: 0, w: 13.333, h: 7.5, fill: { color: C.bgDark }, line: { color: C.bgDark } });
  slide.addText(title, { x: 0.9, y: 0.9, w: 8.8, h: 0.8, color: C.white, fontFace: 'Aptos Display', fontSize: 28, bold: true, margin: 0 });
  if (subtitle) {
    slide.addText(subtitle, { x: 0.92, y: 1.65, w: 7.7, h: 0.4, color: C.cream, fontSize: 17, italic: true, margin: 0 });
  }
}

function footer(slide, n) {
  slide.addText(String(n).padStart(2, '0'), { x: 12.45, y: 7.05, w: 0.35, h: 0.16, fontSize: 10, color: C.muted, align: 'right', margin: 0 });
}

function addBullets(slide, items, opts = {}) {
  const text = [];
  items.forEach((item) => text.push({ text: item, options: { bullet: { indent: 16 }, breakLine: true } }));
  slide.addText(text, {
    x: opts.x ?? 0.9,
    y: opts.y ?? 1.6,
    w: opts.w ?? 5.2,
    h: opts.h ?? 4.4,
    fontSize: opts.fontSize ?? 18,
    color: opts.color ?? C.text,
    paraSpaceAfterPt: opts.paraSpaceAfterPt ?? 8,
    margin: 0.04,
    valign: 'top'
  });
}

function addCallout(slide, text, opts = {}) {
  slide.addShape(pptx.ShapeType.roundRect, {
    x: opts.x ?? 0.9,
    y: opts.y ?? 5.8,
    w: opts.w ?? 11.4,
    h: opts.h ?? 0.6,
    rectRadius: 0.05,
    fill: { color: opts.fill ?? C.red },
    line: { color: opts.fill ?? C.red }
  });
  slide.addText(text, {
    x: (opts.x ?? 0.9) + 0.15,
    y: (opts.y ?? 5.8) + 0.14,
    w: (opts.w ?? 11.4) - 0.3,
    h: 0.22,
    align: 'center',
    color: C.white,
    fontSize: opts.fontSize ?? 21,
    bold: true,
    italic: opts.italic ?? true,
    margin: 0
  });
}

function addCard(slide, x, y, w, h, title, body, accent = C.red2) {
  slide.addShape(pptx.ShapeType.roundRect, { x, y, w, h, rectRadius: 0.06, fill: { color: C.card }, line: { color: accent, pt: 1.2 } });
  slide.addText(title, { x: x + 0.18, y: y + 0.16, w: w - 0.36, h: 0.24, fontSize: 17, bold: true, color: C.red, margin: 0 });
  slide.addText(body, { x: x + 0.18, y: y + 0.52, w: w - 0.36, h: h - 0.7, fontSize: 14.6, color: C.text, margin: 0.02, valign: 'mid' });
}

// 1 Title
{
  const s = pptx.addSlide();
  s.background = { color: C.bgDark };
  s.addImage({ path: assets.title, x: 0, y: 0, w: 13.333, h: 7.5 });
  s.addShape(pptx.ShapeType.rect, { x: 0, y: 0, w: 13.333, h: 7.5, fill: { color: '120A0D', transparency: 34 }, line: { color: '120A0D', transparency: 100 } });
  s.addShape(pptx.ShapeType.roundRect, { x: 0.72, y: 0.82, w: 6.95, h: 5.25, rectRadius: 0.06, fill: { color: '1B1114', transparency: 15 }, line: { color: C.red2, pt: 1.1, transparency: 20 } });
  s.addText('Пищевая цепочка:\nот тебя до теневого правительства', { x: 1.0, y: 1.15, w: 6.3, h: 1.5, color: C.white, fontFace: 'Aptos Display', fontSize: 25, bold: true, margin: 0 });
  s.addText('Расширенная версия: типы вампиров,\nкачественная кровь и скрытый рынок доноров', { x: 1.04, y: 2.95, w: 6.0, h: 0.75, color: C.cream, fontSize: 17.5, italic: true, margin: 0 });
  s.addText('Клуб шапочек из фольги\nПсевдонаучный доклад в академическом стиле', { x: 1.04, y: 4.0, w: 4.9, h: 0.8, color: 'E0D0C4', fontSize: 16, margin: 0 });
  footer(s, 1);
}

// 2 Hypothesis
{
  const s = pptx.addSlide();
  baseLight(s, 'Гипотеза исследования');
  addCard(s, 0.88, 1.55, 5.35, 2.15, 'Базовая идея', 'Теневое правительство — это не просто политическая сеть, а долгоживущая гемозависимая каста, превратившая власть в механизм стабильного питания.');
  addBullets(s, [
    'вирусное происхождение касты;',
    'долголетие как источник стратегического преимущества;',
    'кровь как ресурс, валюта и предмет селекции;',
    'власть как надстройка над пищевой цепочкой.'
  ], { x: 7.05, y: 1.72, w: 5.0, h: 3.6, fontSize: 18 });
  addCallout(s, 'Ключевая формула: власть = контроль кормовой инфраструктуры');
  footer(s, 2);
}

// 3 Virus
{
  const s = pptx.addSlide();
  baseLight(s, 'Sanguis Noctis Virus (SNV-12)');
  addBullets(s, [
    'латентная вирус-индуцированная вампиризация;',
    'хроническая антропогематофагия;',
    'гемозависимый постчеловеческий синдром;',
    'обратимая фототолерантность после кормления.'
  ], { x: 0.88, y: 1.7, w: 5.0, h: 3.8, fontSize: 18 });
  addCard(s, 6.8, 1.55, 5.3, 3.9, 'Ключевые эффекты', 'SNV-12 не делает человека мистическим существом мгновенно. Он перестраивает обменные пути, усиливает регенерацию, замедляет старение и формирует зависимость от человеческой крови как от носителя редких сигнальных молекул.');
  addCallout(s, 'Вампиризм здесь — не проклятие, а вирусная адаптация', { fill: 'A42A37' });
  footer(s, 3);
}

// 4 Middle Ages
{
  const s = pptx.addSlide();
  baseLight(s, 'Почему именно XII-XIV века');
  s.addImage({ path: assets.medieval, x: 0.78, y: 1.28, w: 6.9, h: 4.85 });
  addBullets(s, [
    'войны и миграции ускоряют перенос патогена;',
    'антисанитария скрывает аномальные случаи;',
    'массовая смертность маскирует новый фенотип;',
    'фольклор фиксирует ранние утечки в легенды.'
  ], { x: 8.0, y: 1.7, w: 4.2, h: 3.7, fontSize: 17.5 });
  addCallout(s, 'Там, где высокая смертность, новый патоген легче принять за обычное бедствие', { y: 6.02, fontSize: 19 });
  footer(s, 4);
}

// 5 Classes
{
  const s = pptx.addSlide();
  baseLight(s, 'Классы вампирической адаптации');
  s.addImage({ path: assets.classes, x: 0.78, y: 1.35, w: 7.0, h: 5.1 });
  addBullets(s, [
    'молодой носитель: нестабилен и голоден;',
    'старший адаптант: устойчив и дисциплинирован;',
    'гемарх: древняя элита, пьёт редко, но требует лучшее;',
    'ранний возраст заражения повышает шанс интеграции.'
  ], { x: 8.02, y: 1.7, w: 4.25, h: 3.9, fontSize: 16.8 });
  addCallout(s, 'Древность в этой системе — не возраст, а политический капитал', { y: 6.0, w: 12.0, x: 0.65, fontSize: 20 });
  footer(s, 5);
}

// 6 Failed infection
{
  const s = pptx.addSlide();
  baseLight(s, 'Не всякий укушенный становится вампиром');
  s.addImage({ path: assets.failed, x: 0.78, y: 1.28, w: 6.9, h: 4.9 });
  addBullets(s, [
    'феррогемный каскад запускает перегрев крови;',
    'летальная несовместимость отсеивает большинство;',
    'успешная вампиризация биологически редка;',
    'малочисленность касты имеет псевдонаучное объяснение.'
  ], { x: 8.0, y: 1.72, w: 4.2, h: 3.8, fontSize: 17 });
  addCallout(s, 'Не всякий укушенный становится вампиром; большинство становятся статистикой', { y: 6.0, fontSize: 18.5 });
  footer(s, 6);
}

// 7 Recognition
{
  const s = pptx.addSlide();
  baseLight(s, 'Как распознать вампира');
  s.addImage({ path: assets.recognize, x: 0.78, y: 1.28, w: 6.85, h: 4.95 });
  addBullets(s, [
    'клыки чуть длиннее нормы;',
    'странно медленное старение;',
    'в голоде — тёмный расширенный зрачок;',
    'закрытые клубы и слишком долгая карьера.'
  ], { x: 8.0, y: 1.7, w: 4.2, h: 3.6, fontSize: 17.3 });
  addCallout(s, 'Ни один симптом не доказывает ничего сам по себе — работает только совокупность', { y: 6.0, w: 12.0, x: 0.65, fontSize: 18.3 });
  footer(s, 7);
}

// 8 Blood economy
{
  const s = pptx.addSlide();
  baseLight(s, 'Экономика качественной крови');
  s.addImage({ path: assets.blood, x: 0.78, y: 1.3, w: 7.0, h: 4.95 });
  addBullets(s, [
    'массовая кровь — для периферии;',
    'стабильная кровь — от здоровых доноров;',
    'пиковая кровь — от молодых и сильных;',
    'династическая кровь — от особо ценных линий.'
  ], { x: 8.0, y: 1.65, w: 4.25, h: 3.8, fontSize: 16.9 });
  addCallout(s, 'Чем древнее вампир, тем реже он питается, но тем дороже обходится каждый акт питания', { y: 6.0, x: 0.65, w: 12.0, fontSize: 17.8 });
  footer(s, 8);
}

// 9 Artificial blood
{
  const s = pptx.addSlide();
  baseLight(s, 'Почему искусственная кровь им не подходит');
  s.addImage({ path: assets.artificial, x: 0.78, y: 1.28, w: 7.0, h: 4.95 });
  addBullets(s, [
    'живая кровь несёт гормоны и стрессовые маркеры;',
    'искусственный суррогат даёт только базовую функцию;',
    'у гемархов не возникает полноценного насыщения;',
    'фототолерантность и регенерация не восстанавливаются.'
  ], { x: 8.0, y: 1.67, w: 4.25, h: 3.8, fontSize: 16.8 });
  addCallout(s, 'Искусственная кровь для них — суррогат, а не решение', { y: 6.0, fontSize: 19 });
  footer(s, 9);
}

// 10 Donor market
{
  const s = pptx.addSlide();
  baseLight(s, 'Тайный рынок доноров');
  s.addImage({ path: assets.market, x: 0.78, y: 1.28, w: 6.95, h: 4.95 });
  addBullets(s, [
    'частные клиники и закрытые биобанки;',
    'элитные школы и клубы как фильтр линий;',
    'донорские дома и фонды наблюдения;',
    'качество для верхушки важнее объёма.'
  ], { x: 8.02, y: 1.72, w: 4.2, h: 3.5, fontSize: 17 });
  addCallout(s, 'Настоящая роскошь для гемархов — не золото, а доступ к правильно отсортированным живым донорам', { y: 6.0, x: 0.65, w: 12.0, fontSize: 17 });
  footer(s, 10);
}

// 11 Power capture
{
  const s = pptx.addSlide();
  baseLight(s, 'Почему захват власти рационален');
  s.addImage({ path: assets.donorHouse, x: 0.78, y: 1.28, w: 6.95, h: 4.95 });
  addBullets(s, [
    'обеспечить безопасный доступ к крови;',
    'скрыть своё существование;',
    'сортировать кровь по качеству;',
    'контролировать внутреннюю иерархию через снабжение.'
  ], { x: 8.0, y: 1.72, w: 4.2, h: 3.7, fontSize: 17.2 });
  addCallout(s, 'Власть здесь не цель, а технология питания', { y: 6.0, fontSize: 22 });
  footer(s, 11);
}

// 12 Internal discipline
{
  const s = pptx.addSlide();
  baseLight(s, 'Кровь как валюта и инструмент подчинения');
  s.addImage({ path: assets.etiquette, x: 0.78, y: 1.28, w: 6.95, h: 4.95 });
  addBullets(s, [
    'доступ к качественной крови = статус;',
    'плохое питание ломает самоконтроль низших носителей;',
    'снабжение превращается в механизм дисциплины;',
    'верхушка удерживает касту через монополию на лучший ресурс.'
  ], { x: 8.0, y: 1.68, w: 4.2, h: 3.8, fontSize: 16.9 });
  addCallout(s, 'Кровь внутри системы — это одновременно пища, валюта и инструмент подчинения', { y: 6.0, x: 0.65, w: 12.0, fontSize: 18 });
  footer(s, 12);
}

// 13 Geography
{
  const s = pptx.addSlide();
  baseLight(s, 'Геополитика кормовых зон');
  s.addImage({ path: assets.zones, x: 0.78, y: 1.28, w: 7.0, h: 4.98 });
  addBullets(s, [
    'резервуары населения;',
    'транспортные коридоры людей и биоресурсов;',
    'убежища древних династий;',
    'экспериментальные зоны селекции и наблюдения.'
  ], { x: 8.0, y: 1.7, w: 4.2, h: 3.7, fontSize: 17.1 });
  addCallout(s, 'Геополитика = распределение кормовых контуров', { y: 6.02, fontSize: 21 });
  footer(s, 13);
}

// 14 Chain
{
  const s = pptx.addSlide();
  baseLight(s, 'Пищевая цепочка: от тебя до теневого правительства');
  s.addImage({ path: assets.chain, x: 0.78, y: 1.28, w: 7.0, h: 4.98 });
  addBullets(s, [
    'человек — исходный биоресурс;',
    'системы учёта отсеивают пригодных доноров;',
    'рынок качества поднимает ресурс к верхушке;',
    'гемархи замыкают всю логистику на себе.'
  ], { x: 8.0, y: 1.72, w: 4.2, h: 3.7, fontSize: 17.1 });
  addCallout(s, 'Человек включён в систему не как гражданин, а как элемент глобальной донорской инфраструктуры', { y: 6.0, x: 0.65, w: 12.0, fontSize: 17.6 });
  footer(s, 14);
}

// 15 Conclusion
{
  const s = pptx.addSlide();
  baseDark(s, 'Вывод', 'Финальная формула псевдонаучной модели');
  s.addText('Если теория верна, вершина мировой политики — это не кабинет и не трон, а хорошо организованная столовая премиум-класса, где человечество давно числится в меню.', { x: 0.95, y: 2.0, w: 8.15, h: 1.9, fontSize: 24, color: C.cream, margin: 0.02, valign: 'mid' });
  s.addShape(pptx.ShapeType.roundRect, { x: 9.15, y: 1.6, w: 2.85, h: 3.4, rectRadius: 0.08, fill: { color: '2A1419' }, line: { color: C.gold, pt: 1.3 } });
  s.addText('Ключевые\nформулы', { x: 9.72, y: 2.0, w: 1.75, h: 0.6, align: 'center', fontSize: 20, bold: true, color: C.white, margin: 0 });
  s.addText('• власть = кормовая логистика\n• кровь = валюта\n• элита скрывает не власть, а рацион', { x: 9.45, y: 2.9, w: 2.25, h: 1.25, fontSize: 15.5, color: C.cream, margin: 0.02 });
  s.addText('Жанр: академически поданная псевдонаука для клуба шапочек из фольги', { x: 1.0, y: 6.45, w: 7.4, h: 0.22, fontSize: 13, color: 'D2B8A5', italic: true, margin: 0 });
  footer(s, 15);
}

async function main() {
  await pptx.writeFile({ fileName: outPath });
}

main().catch((err) => {
  console.error(err.stack || err.message || String(err));
  process.exit(1);
});
