import MarkdownIt from 'markdown-it';
import { generatePrivacyPolicy, type PrivacyPolicyInput } from '@platform-modules/content/privacy';

// `generatePrivacyPolicy` interpolates admin-supplied fields into markdown with ZERO escaping, so it is
// the stored-XSS sink (host-templates spec §5). markdown-it with `html: false` (the secure default)
// renders any raw HTML in the markdown source as ESCAPED TEXT — an admin-injected `<script>` in a field
// becomes `&lt;script&gt;`, never live markup. The url-bearing markdown rules (`image`, `link`,
// `autolink`) are disabled below so a generated policy can never emit `<img>`/`<a>` regardless of what
// the (media-widened) allowlist sanitizer permits — symmetric defense-in-depth at the generation
// boundary. (`linkify:false` only disables bare-text autolinking, NOT the link/autolink rules — those
// must be disabled explicitly.) This is the FIRST of two defenses; `sanitizeContentBody` (allowlist)
// re-checks at the content.put trust boundary.
const md = new MarkdownIt({ html: false, linkify: false, breaks: false });
md.disable(['image', 'link', 'autolink']);

/**
 * Convert a generated privacy policy (markdown) into HTML for storage as a `content` page body.
 * Pure + server-safe (markdown-it is pure JS, runs under nodejs_compat; this module is imported only
 * by the admin endpoint, never shipped to the client bundle).
 */
export function privacyPolicyToHtml(input: PrivacyPolicyInput): string {
  return md.render(generatePrivacyPolicy(input));
}

/**
 * Stable short hash (FNV-1a, 32-bit) of the rendered policy body + consent categories. Used as the
 * consent `version` token: a CHANGED policy or category set yields a new version → returning visitors
 * re-prompt; a no-op re-save yields the SAME version → NO spurious re-prompt (the consent-quality
 * footgun the robust path avoids). Category order is normalized so reordering does not bump the version.
 * NOT a security primitive — purely a cache-bust token; collisions are harmless (worst case = no re-prompt
 * on a near-identical change, which a real edit to the body avoids anyway).
 */
export function policyVersion(body: string, categories: string[]): string {
  const input = `${body}\n${[...categories].sort().join(',')}`;
  let h = 0x811c9dc5;
  for (let i = 0; i < input.length; i++) {
    h ^= input.charCodeAt(i);
    h = Math.imul(h, 0x01000193);
  }
  return (h >>> 0).toString(16);
}
