import { isHTMLElement } from '../../utils/ui';
/**
 * StylePreservator handles CSP-compliant style management by temporarily converting
 * inline styles to data attributes during HTML parsing operations.
 *
 * @example
 * ```typescript
 * const context = StylePreservator.preserve('<div style="color: red;">Content</div>');
 * const safeHtml = context.getProcessedHtml();
 * context.restore(parsedElements);
 * ```
 */
export class StylePreservator {
  /**
   * Preserves inline styles by converting them to data attributes.
   *
   * @param {string} htmlString - The HTML string containing inline styles
   * @returns {StylePreservationContext} A context object for later style restoration
   */
  static preserve(htmlString) {
    const processedHtml = htmlString.replace(/\s+style=/g, ' data-style=');
    return new StylePreservationContext(processedHtml);
  }
}
/**
 * Context class that manages the lifecycle of preserved styles.
 */
export class StylePreservationContext {
  constructor(processedHtml) {
    this.processedHtml = processedHtml;
  }
  /**
   * Returns the HTML string with style attributes converted to data-style.
   *
   * @returns {string} The processed HTML string
   */
  getProcessedHtml() {
    return this.processedHtml;
  }
  /**
   * Restores data-style attributes back to style attributes.
   *
   * @param {HTMLElement[]} elements - Array of HTML elements to process
   * @returns {void}
   */
  restore(elements) {
    this.walkNodes(elements);
  }
  /**
   * Recursively walk through nodes and restore styles
   *
   * @param {HTMLElement[]} elements - list of nodes
   * @returns {void}
   */
  walkNodes(elements) {
    elements.forEach((element) => {
      if (isHTMLElement(element)) {
        // Restore data-style back to style
        const dataStyle = element.getAttribute('data-style');
        if (dataStyle) {
          element.style.cssText = dataStyle;
          element.removeAttribute('data-style');
        }
        // Recursively process child nodes
        if (element.children.length > 0) {
          this.walkNodes(Array.from(element.children));
        }
      }
    });
  }
}
