(function (window) {
  'use strict';

  // Кнопка «Продлить до конца года» — Telegram-бот.
  const BOT_URL = 'https://t.me/morozilkabot?start=dl-1790939901157';

  const SUBJECTS = { mat: 'Математика', rus: 'Русский язык', fis: 'Физика', inf: 'Информатика' };
  const SUBJECT_ORDER = ['mat', 'rus', 'fis', 'inf'];
  const TARIFFS = { '': 'без куратора', k: 'с куратором', r: 'с репетитором' };

  // Таблица «Цены 2026/2027», лист «Продления», столбец «На 2 модуль»:
  // 1-й предмет — модуль × 8 − скидка тарифа; 2-й и 3-й — год 1-го − 7000;
  // 4-й — год 1-го − 14000. Модуль 2-го и 3-го на 1000 дешевле 1-го, 4-го — на
  // 2000, поэтому то же самое через собственную цену модуля предмета:
  //   год = модуль × 8 − TARIFF_DISCOUNT[тариф] + POSITION_MARKUP[позиция].
  // Поменялись скидки на листе — правьте здесь.
  const TARIFF_DISCOUNT = { '': 2070, k: 2500, r: 8760 };
  const POSITION_MARKUP = [0, 1000, 1000, 2000];
  // Столбец «Ледокаин» для 1-го предмета; дальше минус та же надбавка позиции.
  const ICE_PRICE = { '': 5090, k: 7090, r: 7090 };

  // Месячный код предложения: предмет, тариф (пусто, k, r), «m», класс.
  const CODE_RE = /^(mat|rus|fis|inf)([kr]?)m\d\d/;

  // Ссылка общая на все предметы и одинакова во всех непустых полях *_prolong.
  function firstLink(dataLinks) {
    return String(dataLinks || '').trim().split(/\s+/)[0];
  }

  // Payload ссылки → { ключ: значение }; не разобрать — null. Подпись не
  // проверяется: окно только показывает цены, а заказ создаёт order.php, который
  // её проверяет.
  function decodePayload(link) {
    const m = /[?&]d=([A-Za-z0-9_-]+)\./.exec(link);
    if (!m) return null;
    let b64 = m[1].replace(/-/g, '+').replace(/_/g, '/');
    while (b64.length % 4) b64 += '=';
    try {
      const out = {};
      for (const pair of atob(b64).split('~')) {
        const dot = pair.indexOf('.');
        if (dot > 0) out[pair.slice(0, dot)] = decodeURIComponent(pair.slice(dot + 1));
      }
      return out;
    } catch (e) {
      return null;
    }
  }

  // Предметы ссылки по позициям: 1-я — самая дорогая, при равной цене — порядок
  // SUBJECT_ORDER. Служебные пары (s, h, o, e…) под CODE_RE не подходят.
  function parseSubjects(link) {
    const payload = decodePayload(link) || {};
    const items = [];
    for (const key of Object.keys(payload)) {
      const m = CODE_RE.exec(key);
      if (m) items.push({ subject: m[1], tariff: m[2], modulePrice: Number(payload[key]) });
    }
    return items.sort((a, b) => b.modulePrice - a.modulePrice
      || SUBJECT_ORDER.indexOf(a.subject) - SUBJECT_ORDER.indexOf(b.subject));
  }

  function buildOffer(items) {
    const rows = items.map((it, i) => ({
      subject: it.subject,
      tariff: it.tariff,
      position: i + 1,
      modulePrice: it.modulePrice,
      yearPrice: it.modulePrice * 8 - TARIFF_DISCOUNT[it.tariff] + POSITION_MARKUP[i],
      icePrice: ICE_PRICE[it.tariff] - POSITION_MARKUP[i],
    }));
    const sum = (key) => rows.reduce((s, r) => s + r[key], 0);
    const moduleTotal = sum('modulePrice');
    const yearTotal = sum('yearPrice');
    const iceTotal = sum('icePrice');
    return {
      rows,
      moduleTotal,
      yearTotal,
      iceTotal,
      eightModules: moduleTotal * 8,
      byModuleTotal: moduleTotal * 8 + iceTotal,
      overpay: moduleTotal * 8 + iceTotal - yearTotal,
    };
  }

  function money(n) {
    return new Intl.NumberFormat('ru-RU').format(n) + ' ₽';
  }

  // Код символа собирается на лету: готовые HTML-коды амперсанда и кавычки при
  // вставке файла в макет однажды раскодировались, и функция стала заменять
  // символ им же. Тест следит, чтобы готовых кодов в файле не было.
  function esc(s) {
    return String(s).replace(/[&"<>]/g, (c) => '&#' + c.charCodeAt(0) + ';');
  }

  // Разметка окна (содержимое #renewal-offer).
  function renderOffer(offer, link) {
    const n = offer.rows.length;
    const one = n === 1;
    const total = one ? 'Итого за 1 предмет' : `Итого за ${n} предмета`;
    const rows = (key) => offer.rows.map((r) => `<div class="ro-row"><span>${SUBJECTS[r.subject]}`
      + `<small>${r.position}-й предмет · ${TARIFFS[r.tariff]}</small></span>`
      + `<b>${money(r[key])}</b></div>`).join('');
    return `<div class="ro-dialog" role="dialog" aria-modal="true" aria-labelledby="ro-title">
<button type="button" class="ro-close" aria-label="Закрыть">×</button>
<div class="ro-eyebrow">ТВОЯ ПОДГОТОВКА К ЕГЭ 2027</div>
<h2 class="ro-title" id="ro-title">Продление на следующий модуль</h2>
<p class="ro-muted">${one ? 'Продли предмет — на модуль или до конца года.'
    : `Продли ${n} предмета одним заказом — на модуль или до конца года.`}</p>
<div class="ro-grid">
<article class="ro-plan">
<h3>На один модуль</h3>
<div class="ro-rows">${rows('modulePrice')}</div>
<span class="ro-small">${total}</span>
<div class="ro-price">${money(offer.moduleTotal)}</div>
<span class="ro-small">Следующий, второй модуль</span>
<div class="ro-comparison">
<strong>Если продлевать каждый модуль</strong>
<div class="ro-row"><span>8 модулей до конца года<small>${money(offer.moduleTotal)} × 8</small></span><b>${money(offer.eightModules)}</b></div>
<div class="ro-row"><span>«Ледокаин» в конце года<small>${one ? 'На 1 предмет' : `На все ${n} предмета`}</small></span><b>${money(offer.iceTotal)}</b></div>
<div class="ro-row ro-total"><span>Всего до конца года<small>Модули + интенсивы</small></span><b>${money(offer.byModuleTotal)}</b></div>
<p class="ro-difference">На ${money(offer.overpay)} дороже продления до конца года.</p>
</div>
<div class="ro-push">
<a class="ro-btn ro-btn-module" href="${esc(link)}">Продлить на модуль</a>
</div>
</article>
<article class="ro-plan ro-recommended">
<span class="ro-tag">ВЫГОДНО</span>
<h3>До конца учебного года</h3>
<p class="ro-muted">Вся дальнейшая подготовка одним платежом.</p>
<div class="ro-rows">${rows('yearPrice')}</div>
<span class="ro-small">${total}</span>
<div class="ro-price">${money(offer.yearTotal)}</div>
<div class="ro-benefit">Выгода ${money(offer.overpay)}</div>
<span class="ro-small">Оставшиеся 8 модулей · со 2-го по 9-й</span>
<div class="ro-gift">
<strong>«Ледокаин» в подарок</strong>
<p>Продли курс сейчас до конца года и получи в подарок целый курс-интенсив перед ЕГЭ.</p>
<p>Двухнедельный интенсив перед ЕГЭ с повторением тем и нарешкой всех прототипов заданий из банка заданий ЕГЭ, на котором ты получишь:</p>
<ul>
<li>повтор и разбор всех типов заданий</li>
<li>разбор вариантов Дальнего Востока прямо перед ЕГЭ</li>
<li>проверку пробников от действующего эксперта ЕГЭ</li>
<li>шпаргалку для экзамена</li>
</ul>
</div>
<div class="ro-push">
<a class="ro-btn ro-btn-year" href="${esc(BOT_URL)}" target="_blank" rel="noopener">Продлить до конца года</a>
</div>
</article>
</div>
</div>`;
  }

  // Стили окна. Всё под #renewal-offer, базовые свойства внутри сброшены — стили
  // кабинета GetCourse на окно не влияют. Цвета и размеры — из макета.
  const CSS = `
#renewal-offer[hidden]{display:none!important}
#renewal-offer{position:fixed;inset:0;z-index:2147483000;overflow-y:auto;padding:24px 16px;background:rgba(23,54,107,.55)}
#renewal-offer *{box-sizing:border-box;margin:0;padding:0;font-family:Arial,Helvetica,sans-serif;letter-spacing:normal;text-transform:none}
#renewal-offer .ro-dialog{position:relative;max-width:980px;margin:0 auto;padding:30px 28px 32px;border-radius:26px;background:#f7f3ff;color:#17366b;font-size:15px;line-height:1.5;text-align:left}
#renewal-offer .ro-close{position:absolute;top:16px;right:16px;width:40px;height:40px;border:0;border-radius:50%;background:#fff;color:#17366b;font-size:26px;line-height:40px;cursor:pointer;box-shadow:0 6px 18px #5137ff1a}
#renewal-offer .ro-close:hover{background:#eeebff}
#renewal-offer .ro-eyebrow{font-size:12px;font-weight:700;letter-spacing:.7px;color:#5137ff}
#renewal-offer .ro-title{margin:8px 48px 12px 0;font-size:36px;font-weight:800;line-height:1.16;letter-spacing:-.8px;color:#17366b}
#renewal-offer .ro-muted{margin:8px 0;color:#777591}
#renewal-offer .ro-grid{display:grid;grid-template-columns:1fr 1fr;gap:22px;align-items:stretch;margin-top:24px}
#renewal-offer .ro-plan{display:flex;flex-direction:column;padding:26px 23px;border:2px solid #fff;border-radius:28px;background:#fff;box-shadow:0 18px 42px #5137ff0b}
#renewal-offer .ro-recommended{border-color:#634aff}
#renewal-offer .ro-tag{align-self:flex-start;padding:7px 12px;border-radius:9px;background:#eeebff;color:#5137ff;font-size:12px;font-weight:700}
#renewal-offer .ro-recommended>.ro-tag{padding:5px 13px;border-radius:20px;background:#ff9013;color:#fff;box-shadow:0 5px 14px #ff90132e}
#renewal-offer .ro-plan h3{margin:12px 0;font-size:24px;font-weight:700;line-height:1.25;letter-spacing:-.4px;color:#17366b}
#renewal-offer .ro-rows{margin:18px 0}
#renewal-offer .ro-row{display:flex;justify-content:space-between;gap:12px;padding:13px 0;border-bottom:1px solid #edeaff}
#renewal-offer .ro-row small{display:block;margin-top:3px;font-size:12px;color:#7b7999}
#renewal-offer .ro-row b{white-space:nowrap;font-size:15px;font-weight:700}
#renewal-offer .ro-small{font-size:12px;color:#777591}
#renewal-offer .ro-price{margin:9px 0 5px;font-size:39px;font-weight:800;line-height:1.2;letter-spacing:-1px;color:#17366b}
#renewal-offer .ro-benefit{align-self:flex-start;margin:2px 0 10px;padding:6px 12px;border-radius:10px;background:#fff1e0;color:#e46f00;font-size:16px;font-weight:700}
#renewal-offer .ro-comparison{margin-top:22px;padding:17px;border:1px solid #e8e2ff;border-radius:18px;background:#f5f2ff}
#renewal-offer .ro-comparison>strong{font-size:15px}
#renewal-offer .ro-comparison .ro-row{font-size:13px}
#renewal-offer .ro-comparison .ro-row b{font-size:14px}
#renewal-offer .ro-comparison .ro-total{border-bottom:0;font-weight:700}
#renewal-offer .ro-comparison .ro-total b{font-size:21px}
#renewal-offer .ro-difference{margin-top:12px;padding:12px;border-radius:11px;background:#eae5ff;color:#5137ff;font-size:14px;font-weight:700;line-height:1.5}
#renewal-offer .ro-gift{margin-top:22px;padding:20px;border-radius:16px;background:#5137ff;color:#fff}
#renewal-offer .ro-gift strong{display:block;font-size:17px;line-height:1.4;color:#ffce70}
#renewal-offer .ro-gift p,#renewal-offer .ro-gift li{font-size:14px;line-height:1.6;color:#fff}
#renewal-offer .ro-gift p{margin:12px 0}
#renewal-offer .ro-gift ul{padding-left:20px;list-style:disc}
#renewal-offer .ro-push{margin-top:auto;padding-top:24px}
#renewal-offer .ro-btn{display:flex;align-items:center;justify-content:center;width:100%;min-height:54px;padding:15px 12px;border-radius:15px;font-size:15px;font-weight:700;line-height:1.4;text-align:center;text-decoration:none;cursor:pointer}
#renewal-offer .ro-btn-module,#renewal-offer .ro-btn-module:hover{color:#fff}
#renewal-offer .ro-btn-module{background:#5137ff;box-shadow:0 10px 23px #5137ff24}
#renewal-offer .ro-btn-module:hover{background:#442bdd}
#renewal-offer .ro-btn-year,#renewal-offer .ro-btn-year:hover{color:#fff}
#renewal-offer .ro-btn-year{background:#ff9013}
#renewal-offer .ro-btn-year:hover{background:#f58100}
@media (max-width:650px){
#renewal-offer{padding:12px 8px}
#renewal-offer .ro-dialog{padding:24px 14px;border-radius:22px}
#renewal-offer .ro-title{font-size:30px}
#renewal-offer .ro-grid{grid-template-columns:1fr;gap:20px}
#renewal-offer .ro-plan{padding:24px 20px;border-radius:24px}
#renewal-offer .ro-price{font-size:36px}
}`;

  let root = null;
  let savedOverflow = '';

  function mount(html) {
    if (!document.getElementById('renewal-offer-style')) {
      const style = document.createElement('style');
      style.id = 'renewal-offer-style';
      style.textContent = CSS;
      document.head.appendChild(style);
    }
    const el = document.createElement('div');
    el.id = 'renewal-offer';
    el.hidden = true;
    el.innerHTML = html;
    // Закрытие: клик по затемнению вокруг окна или по крестику.
    el.addEventListener('click', (e) => {
      if (e.target === el || e.target.closest('.ro-close')) hide();
    });
    document.body.appendChild(el);
    return el;
  }

  function onKey(e) {
    if (e.key === 'Escape') hide();
  }

  function show() {
    root.hidden = false;
    // Страница под окном не прокручивается — прокрутка внутри окна.
    savedOverflow = document.documentElement.style.overflow;
    document.documentElement.style.overflow = 'hidden';
    document.addEventListener('keydown', onKey);
    root.querySelector('.ro-close').focus();
  }

  function hide() {
    root.hidden = true;
    document.documentElement.style.overflow = savedOverflow;
    document.removeEventListener('keydown', onKey);
  }

  function init() {
    const banner = document.getElementById('banner-gift');
    const data = document.getElementById('renewal-offer-data');
    // Повторный запуск скрипта второй обработчик не вешает.
    if (!banner || !data || banner.hasAttribute('data-renewal-offer')) return;
    const link = firstLink(data.getAttribute('data-links'));
    const items = parseSubjects(link);
    // Нет ссылки (у админа поля пустые) или в ней нет предметов — окна нет.
    if (!items.length) return;
    banner.setAttribute('data-renewal-offer', 'on');
    banner.style.cursor = 'pointer';
    banner.addEventListener('click', (e) => {
      e.preventDefault();
      if (!root) root = mount(renderOffer(buildOffer(items), link));
      show();
    });
  }

  // Список тренингов открывается по нескольким адресам: пункт меню «Тренинги»
  // ведёт на /teach/control/stream, есть /teach/control и …/stream/index, бывает
  // и префикс /pl/.
  function isListPage(pathname) {
    return /^\/(pl\/)?teach\/control(\/stream(\/index)?)?\/?$/.test(pathname);
  }

  window.gcRenewalOffer = { BOT_URL, firstLink, decodePayload, parseSubjects, buildOffer, renderOffer, money, isListPage };

  // Макет подключает скрипт на всех страницах кабинета — работаем только в списке
  // тренингов.
  if (!isListPage(window.location.pathname)) return;

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', init);
  } else {
    init();
  }
})(window);
