import { marked } from 'marked';

/** LegalDoc is one language variant of a legal document: its markdown source and page title. */
export interface LegalDoc {
  md: string;
  title: string;
}

/**
 * renderLegalHtml renders a bilingual (RU + EN) legal document as a standalone, self-contained HTML
 * page with a header language + theme switcher, mirroring the landing: a 🌐 language toggle and a
 * ☼/☾ theme toggle, no "back". Both language bodies are rendered into the page; a small inline
 * ES5 script toggles between them client-side (no reload), defaults to Russian (never the browser
 * language, like the landing) and persists the choice, and applies the theme (system default plus a
 * persisted manual override). On the offer page (`bodyClass === 'offer'`) it also transliterates the
 * Cyrillic left in the EN body — the live price list is spliced in Russian, so the product names are
 * transliterated for the English view. It backs every public legal page — the offer at `/offer/`, the
 * privacy policy at `/privacy/`, the EULA at `/eula/` — served by the render sidecar.
 *
 * The markdown is trusted repository content plus the backend's own catalog projection, not user
 * input, so the rendered HTML is deliberately not sanitised. The page carries its own minimal styling
 * and script, so it needs neither the app bundle nor `app.css`.
 */
export function renderLegalHtml(doc: { ru: LegalDoc; en: LegalDoc; canonical: string; bodyClass?: string }): string {
  const ruBody = marked.parse(doc.ru.md, { async: false }) as string;
  const enBody = marked.parse(doc.en.md, { async: false }) as string;
  return `<!doctype html>
<html lang="ru" data-title-ru="${attr(doc.ru.title)}" data-title-en="${attr(doc.en.title)}">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>${doc.ru.title}</title>
    <link rel="canonical" href="${doc.canonical}" />
    <meta name="theme-color" media="(prefers-color-scheme: light)" content="#f3f4f6" />
    <meta name="theme-color" media="(prefers-color-scheme: dark)" content="#0f1115" />
    <style>
      :root {
        color-scheme: light dark;
        --bg: #ffffff;
        --text: #1a1c20;
        --accent: #2563eb;
        --rule: #e5e7eb;
        --cell-border: #d1d5db;
      }
      /* Dark palette: the system default (unless the reader forced light) and the manual override. */
      @media (prefers-color-scheme: dark) {
        :root:not([data-theme='light']) {
          --bg: #0f1115;
          --text: #e7e9ee;
          --accent: #6ea8fe;
          --rule: #242832;
          /* A muted grey — the section rules vanish on dark, so table cells get a firmer border. */
          --cell-border: #3a4250;
        }
      }
      :root[data-theme='dark'] {
        --bg: #0f1115;
        --text: #e7e9ee;
        --accent: #6ea8fe;
        --rule: #242832;
        --cell-border: #3a4250;
      }
      * {
        box-sizing: border-box;
      }
      body {
        margin: 0;
        background: var(--bg);
        color: var(--text);
        font: 16px/1.6 system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
      }
      /* The language + theme switcher sits at the top and stays reachable down a long document. */
      .legalbar {
        position: sticky;
        top: 0;
        z-index: 2;
        display: flex;
        justify-content: flex-end;
        gap: 8px;
        padding: 10px 20px;
        background: var(--bg);
        border-bottom: 1px solid var(--rule);
      }
      .tgl {
        min-width: 40px;
        height: 36px;
        padding: 0 12px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        font: 600 14px/1 system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
        color: var(--text);
        background: transparent;
        border: 1px solid var(--cell-border);
        border-radius: 8px;
        cursor: pointer;
      }
      main {
        max-width: 760px;
        margin: 0 auto;
        padding: 24px 20px 64px;
      }
      main[hidden] {
        display: none;
      }
      a {
        color: var(--accent);
      }
      h1 {
        font-size: 1.6rem;
        text-align: center;
      }
      h2 {
        font-size: 1.2rem;
        margin-top: 2em;
        padding-top: 1em;
        border-top: 1px solid var(--rule);
      }
      h3 {
        font-size: 1.05rem;
        margin-top: 1.5em;
      }
      ul {
        padding-left: 1.25em;
      }
      li {
        margin: 0.25em 0;
      }
      /* Tables span the full content width (the offer price list §4.4, the privacy data table). */
      table {
        width: 100%;
        border-collapse: collapse;
        margin: 0.75em 0 1.25em;
        font-size: 0.95rem;
      }
      th,
      td {
        border: 1px solid var(--cell-border);
        padding: 6px 10px;
        /* Top-align: the privacy data table's prose cells differ in height per row. */
        vertical-align: top;
      }
      /* Offer only: the product-name column shrinks to its content and never wraps; the price columns
         share the rest of the width (width:1% is the shrink-to-fit idiom paired with width:100%). Other
         legal tables (the privacy data table) keep the default auto layout so their prose cells wrap. */
      .offer th:first-child,
      .offer td:first-child {
        width: 1%;
        white-space: nowrap;
      }
      /* Right-aligned price columns. marked emits the alignment from the "---:" separator; this rule
         keeps it applied whether that surfaces as an align attribute or an inline style. */
      th[align='right'],
      td[align='right'] {
        text-align: right;
      }
    </style>
  </head>
  <body${doc.bodyClass ? ' class="' + doc.bodyClass + '"' : ''}>
    <header class="legalbar">
      <button type="button" id="legal-lang" class="tgl"></button>
      <button type="button" id="legal-theme" class="tgl" aria-label="Theme"></button>
    </header>
    <main data-lang="ru">
      ${ruBody}
    </main>
    <main data-lang="en" hidden>
      ${enBody}
    </main>
    <script>
      (function () {
        'use strict';
        var html = document.documentElement;
        var K_LANG = 'erudit.legal.lang', K_THEME = 'erudit.legal.theme';
        function get(k) { try { return localStorage.getItem(k); } catch (e) { return null; } }
        function set(k, v) { try { localStorage.setItem(k, v); } catch (e) {} }
        var langBtn = document.getElementById('legal-lang');
        var themeBtn = document.getElementById('legal-theme');

        // Offer only: the price list is spliced in Russian. Its section headings and column headers
        // are translated to English (PRICE_TR — the exact strings the backend projects); the product
        // names fall through to transliteration.
        var PRICE_TR = {
          'Приобретение внутриигровой валюты «Фишка»:': 'Purchase of the «Chip» in-game currency:',
          'Использование внутриигровой валюты «Фишка»:': 'Use of the «Chip» in-game currency:',
          'Наименование': 'Item',
          'Рубли': 'Roubles',
          'Голоса в VK': 'VK Votes',
          'Stars в Telegram': 'Telegram Stars',
          '«Фишки»': '«Chips»'
        };
        function translit(s) {
          var m = { 'а':'a','б':'b','в':'v','г':'g','д':'d','е':'e','ё':'e','ж':'zh','з':'z','и':'i',
            'й':'y','к':'k','л':'l','м':'m','н':'n','о':'o','п':'p','р':'r','с':'s','т':'t','у':'u',
            'ф':'f','х':'kh','ц':'ts','ч':'ch','ш':'sh','щ':'shch','ъ':'','ы':'y','ь':'','э':'e',
            'ю':'yu','я':'ya' };
          return s.replace(/[а-яё]/gi, function (c) {
            var lower = c.toLowerCase(), r = m[lower];
            if (r === undefined) return c;
            return c !== lower && r ? r.charAt(0).toUpperCase() + r.slice(1) : r;
          });
        }
        function translitEn() {
          var en = document.querySelector('main[data-lang="en"]');
          if (!en || !document.createTreeWalker) return;
          var w = document.createTreeWalker(en, NodeFilter.SHOW_TEXT, null, false), n, tr;
          while ((n = w.nextNode())) {
            tr = PRICE_TR[n.nodeValue];
            if (typeof tr === 'string') { n.nodeValue = tr; continue; }
            if (/[а-яё]/i.test(n.nodeValue)) n.nodeValue = translit(n.nodeValue);
          }
        }

        function applyLang(l) {
          html.lang = l;
          set(K_LANG, l);
          var mains = document.querySelectorAll('main[data-lang]');
          for (var i = 0; i < mains.length; i++) {
            mains[i].hidden = mains[i].getAttribute('data-lang') !== l;
          }
          var t = html.getAttribute('data-title-' + l);
          if (t) document.title = t;
          // The button shows the OTHER language — what a click switches to.
          langBtn.textContent = l === 'ru' ? 'English' : 'Русский';
        }
        function applyTheme(t) {
          html.setAttribute('data-theme', t);
          set(K_THEME, t);
          themeBtn.textContent = t === 'light' ? '☼' : '☾';
        }

        // Default language is Russian (never the browser language), like the landing; persisted wins.
        var lang = get(K_LANG) === 'en' ? 'en' : 'ru';
        // Theme: a persisted choice wins, else the system scheme.
        var theme = get(K_THEME);
        if (theme !== 'light' && theme !== 'dark') {
          theme = window.matchMedia && matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
        }
        if (document.body.classList.contains('offer')) translitEn();
        applyLang(lang);
        applyTheme(theme);
        langBtn.onclick = function () { applyLang(html.lang === 'ru' ? 'en' : 'ru'); };
        themeBtn.onclick = function () { applyTheme(html.getAttribute('data-theme') === 'light' ? 'dark' : 'light'); };
      })();
    </script>
  </body>
</html>
`;
}

/** attr escapes a trusted string for use inside a double-quoted HTML attribute value. */
function attr(s: string): string {
  return s.replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;');
}

/**
 * renderOfferHtml renders the public-offer page (its Russian price list already spliced into both
 * language sources) as the standalone `/offer/` page — the offer preset over {@link renderLegalHtml}.
 */
export function renderOfferHtml(ruMd: string, enMd: string): string {
  return renderLegalHtml({
    ru: { md: ruMd, title: 'Публичная оферта — Эрудит' },
    en: { md: enMd, title: 'Public offer — Erudit' },
    canonical: 'https://erudit-game.ru/offer/',
    bodyClass: 'offer',
  });
}
