const crypto = require("crypto");
const sanitizeHtml = require("sanitize-html");
const slugify = require("slugify");

function escapeHtml(value = "") {
  return String(value)
    .replaceAll("&", "&amp;")
    .replaceAll("<", "&lt;")
    .replaceAll(">", "&gt;")
    .replaceAll('"', "&quot;")
    .replaceAll("'", "&#039;");
}

function cleanRichText(value = "") {
  return sanitizeHtml(String(value), {
    allowedTags: ["p", "br", "strong", "b", "em", "i", "h2", "h3", "h4", "ul", "ol", "li", "a"],
    allowedAttributes: {
      a: ["href", "target", "rel"]
    },
    allowedSchemes: ["http", "https", "mailto", "tel"],
    transformTags: {
      a: (tagName, attribs) => ({
        tagName,
        attribs: {
          href: attribs.href || "#",
          target: attribs.target === "_blank" ? "_blank" : undefined,
          rel: attribs.target === "_blank" ? "noopener noreferrer" : undefined
        }
      })
    }
  });
}

function makeSlug(value, fallback = "entry") {
  const slug = slugify(String(value || ""), { lower: true, strict: true, trim: true });
  return slug || `${fallback}-${Date.now()}`;
}

function token(size = 24) {
  return crypto.randomBytes(size).toString("hex");
}

function now() {
  return new Date().toISOString();
}

function bytes(n = 0) {
  if (n < 1024) return `${n} B`;
  if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
  if (n < 1024 * 1024 * 1024) return `${(n / 1024 / 1024).toFixed(1)} MB`;
  return `${(n / 1024 / 1024 / 1024).toFixed(1)} GB`;
}

function checkbox(value) {
  return value ? 1 : 0;
}

function listFromText(value = "") {
  return String(value)
    .split(/\r?\n|,/)
    .map((part) => part.trim())
    .filter(Boolean);
}

function safeJson(value, fallback = {}) {
  if (!value) return fallback;
  try {
    return JSON.parse(value);
  } catch {
    return fallback;
  }
}

module.exports = {
  escapeHtml,
  cleanRichText,
  makeSlug,
  token,
  now,
  bytes,
  checkbox,
  listFromText,
  safeJson
};
