import sanitizeHtml from "sanitize-html";

const DESCRIPTION_SANITIZE_OPTIONS: sanitizeHtml.IOptions = {
  allowedTags: [
    "p",
    "br",
    "strong",
    "b",
    "em",
    "i",
    "u",
    "s",
    "del",
    "h1",
    "h2",
    "h3",
    "h4",
    "ul",
    "ol",
    "li",
    "blockquote",
    "pre",
    "code",
    "hr",
    "a",
    "span",
    "div",
  ],
  allowedAttributes: {
    a: ["href", "target", "rel"],
    p: ["style"],
    h1: ["style"],
    h2: ["style"],
    h3: ["style"],
    h4: ["style"],
    div: ["style"],
    span: ["style"],
  },
  allowedSchemes: ["http", "https", "mailto", "tel"],
  allowedSchemesAppliedToAttributes: ["href"],
  allowProtocolRelative: false,
  allowedStyles: {
    "*": {
      "text-align": [/^(left|right|center|justify)$/],
      color: [
        /^#[0-9a-fA-F]{3,8}$/,
        /^rgb\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*\)$/,
        /^rgba\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*,\s*(0(\.\d+)?|1(\.0+)?)\s*\)$/,
      ],
      "background-color": [
        /^#[0-9a-fA-F]{3,8}$/,
        /^rgb\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*\)$/,
        /^rgba\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*,\s*(0(\.\d+)?|1(\.0+)?)\s*\)$/,
      ],
    },
  },
  transformTags: {
    a: (tagName, attribs) => {
      const href = typeof attribs.href === "string" ? attribs.href.trim() : "";
      if (!href) {
        return {
          tagName: "span",
          attribs: {},
        };
      }
      return {
        tagName,
        attribs: {
          ...attribs,
          href,
          target: "_blank",
          rel: "noopener noreferrer nofollow",
        },
      };
    },
  },
};

function escapeHtml(value: string) {
  return value
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;")
    .replace(/'/g, "&#39;");
}

export function isLikelyHtml(value: string) {
  return /<\/?[a-z][\s\S]*>/i.test(value);
}

export function plainTextToDescriptionHtml(value: string) {
  const normalized = value.replace(/\r\n/g, "\n").trim();
  if (!normalized) return "";

  return normalized
    .split(/\n{2,}/)
    .map((paragraph) => {
      const content = paragraph
        .split("\n")
        .map((line) => escapeHtml(line))
        .join("<br>");
      return `<p>${content}</p>`;
    })
    .join("");
}

export function sanitizeProductDescription(value: unknown) {
  const raw = typeof value === "string" ? value : "";
  if (!raw.trim()) return "";
  const source = isLikelyHtml(raw) ? raw : plainTextToDescriptionHtml(raw);
  return sanitizeHtml(source, DESCRIPTION_SANITIZE_OPTIONS).trim();
}

export function descriptionToEditorHtml(value: unknown) {
  const raw = typeof value === "string" ? value : "";
  if (!raw.trim()) return "";
  return isLikelyHtml(raw) ? sanitizeProductDescription(raw) : plainTextToDescriptionHtml(raw);
}
