import { sanitizeRichTextHtml } from '@/lib/customFormHtmlSanitizer';

const ORDERED_LIST_PATTERN = /^(\(?[0-9]+[.)]|[a-zA-Z][.)])\s+(.*)$/;
const UNORDERED_LIST_PATTERN = /^([*•\-–—▪◦●○■□])\s+(.*)$/;
const PRESERVED_PASTE_STYLE_PROPERTIES = new Set([
  'font-weight',
  'font-style',
  'text-decoration',
  'text-align',
]);

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

function normalizeTextValue(value = '') {
  return String(value)
    .replace(/\r\n?/g, '\n')
    .replace(/[\u200B-\u200D\uFEFF]/g, '')
    .replace(/\u00A0/g, ' ');
}

function joinWrappedLines(lines = []) {
  return lines
    .map((line) => normalizeTextValue(line).trim())
    .filter(Boolean)
    .reduce((result, line) => {
      if (!result) return line;
      if (/[\-\u2010-\u2015\/]$/.test(result)) return `${result}${line}`;
      return `${result} ${line}`;
    }, '');
}

function flushParagraph(blocks, lines) {
  const content = joinWrappedLines(lines);
  if (content) blocks.push({ type: 'p', content });
  lines.length = 0;
}

function flushList(blocks, listState) {
  if (!listState.type || listState.items.length === 0) return;

  blocks.push({
    type: listState.type,
    items: listState.items.map((itemLines) => joinWrappedLines(itemLines)).filter(Boolean),
  });

  listState.type = null;
  listState.items = [];
}

export function plainTextToRichHtml(text = '') {
  const normalized = normalizeTextValue(text);
  if (!normalized.trim()) return '';

  const blocks = [];
  const paragraphLines = [];
  const listState = { type: null, items: [] };

  normalized.split('\n').forEach((rawLine) => {
    const trimmed = rawLine.trim();

    if (!trimmed) {
      flushParagraph(blocks, paragraphLines);
      flushList(blocks, listState);
      return;
    }

    const unorderedMatch = trimmed.match(UNORDERED_LIST_PATTERN);
    const orderedMatch = trimmed.match(ORDERED_LIST_PATTERN);

    if (unorderedMatch || orderedMatch) {
      flushParagraph(blocks, paragraphLines);

      const type = orderedMatch ? 'ol' : 'ul';
      const itemText = orderedMatch?.[2] || unorderedMatch?.[2] || '';

      if (listState.type && listState.type !== type) flushList(blocks, listState);
      if (!listState.type) listState.type = type;
      listState.items.push([itemText]);
      return;
    }

    if (listState.type && listState.items.length > 0) {
      listState.items[listState.items.length - 1].push(trimmed);
      return;
    }

    paragraphLines.push(trimmed);
  });

  flushParagraph(blocks, paragraphLines);
  flushList(blocks, listState);

  return blocks
    .map((block) => {
      if (block.type === 'p') return `<p>${escapeHtml(block.content)}</p>`;

      return `<${block.type}>${block.items
        .map((item) => `<li>${escapeHtml(item)}</li>`)
        .join('')}</${block.type}>`;
    })
    .join('');
}

function sanitizePasteStyle(styleText = '') {
  return String(styleText)
    .split(';')
    .map((rule) => rule.trim())
    .filter(Boolean)
    .map((rule) => {
      const [rawProperty, ...rawValueParts] = rule.split(':');
      if (!rawProperty || rawValueParts.length === 0) return null;

      const property = rawProperty.trim().toLowerCase();
      const value = rawValueParts.join(':').trim();

      if (!PRESERVED_PASTE_STYLE_PROPERTIES.has(property)) return null;
      if (!value || /expression\s*\(|javascript:/i.test(value)) return null;

      return `${property}: ${value}`;
    })
    .filter(Boolean)
    .join('; ');
}

function unwrapElement(element) {
  const parent = element.parentNode;
  if (!parent) {
    element.remove();
    return;
  }

  while (element.firstChild) {
    parent.insertBefore(element.firstChild, element);
  }

  element.remove();
}

function normalizePastedNodeTree(root) {
  [...root.childNodes].forEach((child) => {
    if (child.nodeType === Node.TEXT_NODE) {
      child.textContent = normalizeTextValue(child.textContent);
      return;
    }

    if (child.nodeType !== Node.ELEMENT_NODE) return;

    const element = child;
    normalizePastedNodeTree(element);

    if (element.hasAttribute('style')) {
      const cleanedStyle = sanitizePasteStyle(element.getAttribute('style') || '');
      if (cleanedStyle) element.setAttribute('style', cleanedStyle);
      else element.removeAttribute('style');
    }

    if ((element.tagName.toLowerCase() === 'span' || element.tagName.toLowerCase() === 'font') && !element.attributes.length) {
      unwrapElement(element);
    }
  });
}

export function normalizePastedRichHtml(html = '', fallbackText = '') {
  const sanitizedHtml = sanitizeRichTextHtml(html || '');
  if (!sanitizedHtml) return plainTextToRichHtml(fallbackText);

  const parser = new DOMParser();
  const doc = parser.parseFromString(sanitizedHtml, 'text/html');
  const body = doc.body;

  if (!body) return plainTextToRichHtml(fallbackText);

  normalizePastedNodeTree(body);

  const normalizedHtml = body.innerHTML.trim();
  return normalizedHtml || plainTextToRichHtml(fallbackText);
}

export default normalizePastedRichHtml;