/**
 * Enhanced htmlValidator Tests
 *
 * Additional comprehensive tests for HTML validation utility
 */

import {
  validateHTML,
  validateCSS,
  extractAndValidateCSS,
} from '../htmlValidator';

// Mock liquidTemplateSupport module
jest.mock('../liquidTemplateSupport', () => ({
  validateLiquidHTML: jest.fn(() => ({
    errors: [],
    warnings: [],
    info: [],
  })),
}));

// Mock console.warn to avoid noise in tests
const originalWarn = console.warn;
beforeAll(() => {
  console.warn = jest.fn();
});

afterAll(() => {
  console.warn = originalWarn;
});

describe('Enhanced htmlValidator Tests', () => {
  beforeEach(() => {
    jest.clearAllMocks();
  });

  describe('Advanced validateHTML Tests', () => {
    describe('Input Validation and Edge Cases', () => {
      it('returns proper structure for valid HTML', () => {
        const html = '<div>Valid content</div>';
        const result = validateHTML(html);

        expect(result).toHaveProperty('isValid');
        expect(result).toHaveProperty('errors');
        expect(result).toHaveProperty('warnings');
        expect(result).toHaveProperty('info');
        expect(Array.isArray(result.errors)).toBe(true);
        expect(Array.isArray(result.warnings)).toBe(true);
        expect(Array.isArray(result.info)).toBe(true);
      });

      it('handles empty HTML gracefully', () => {
        const result = validateHTML('');

        expect(result.isValid).toBe(true);
        expect(result.errors.length).toBe(0);
        expect(result.warnings.length).toBe(0);
        expect(result.info.length).toBe(0);
      });

      it('handles null HTML gracefully', () => {
        const result = validateHTML(null);

        expect(result.isValid).toBe(true);
        expect(result.errors.length).toBe(0);
      });

      it('handles undefined HTML gracefully', () => {
        const result = validateHTML(undefined);

        expect(result.isValid).toBe(true);
        expect(result.errors.length).toBe(0);
      });

      it('handles non-string HTML gracefully', () => {
        const result = validateHTML(123);

        expect(result.isValid).toBe(true);
        expect(result.errors.length).toBe(0);
      });

      it('handles very long HTML content', () => {
        const longHtml = `<p>${'a'.repeat(50000)}</p>`;
        const result = validateHTML(longHtml);

        expect(result).toBeDefined();
        expect(typeof result.isValid).toBe('boolean');
      });

      it('handles HTML with special characters', () => {
        const html = '<p>Special: &amp; &lt; &gt; &quot; &#39;</p>';
        const result = validateHTML(html);

        expect(result).toBeDefined();
        expect(typeof result.isValid).toBe('boolean');
      });

      it('handles HTML with unicode characters', () => {
        const html = '<p>Unicode: 你好 مرحبا 🎉 ñáéíóú</p>';
        const result = validateHTML(html);

        expect(result).toBeDefined();
        expect(typeof result.isValid).toBe('boolean');
      });
    });

    describe('Security-Related Validations', () => {
      it('detects potentially unsafe javascript protocol', () => {
        const html = '<a href="javascript:alert(1)">Click</a>';
        const result = validateHTML(html);

        // Unsafe protocols are BLOCKING ERRORS (sanitizer.dangerousProtocolDetected)
        expect(result.errors.length).toBeGreaterThan(0);
        expect(result.isValid).toBe(false);
        // Verify it's the correct rule
        const error = result.errors.find((e) => e.rule === 'sanitizer.dangerousProtocolDetected');
        expect(error).toBeDefined();
      });

      it('detects potentially unsafe data protocol', () => {
        const html = '<img src="data:image/svg+xml,<svg>...">';
        const result = validateHTML(html);

        // Unsafe protocols are BLOCKING ERRORS (sanitizer.dangerousProtocolDetected)
        expect(result.errors.length).toBeGreaterThan(0);
        expect(result.isValid).toBe(false);
        // Verify it's the correct rule
        const error = result.errors.find((e) => e.rule === 'sanitizer.dangerousProtocolDetected');
        expect(error).toBeDefined();
      });

      it('detects potentially unsafe vbscript protocol', () => {
        const html = '<a href="vbscript:msgbox(1)">Click</a>';
        const result = validateHTML(html);

        // Unsafe protocols are BLOCKING ERRORS (sanitizer.dangerousProtocolDetected)
        expect(result.errors.length).toBeGreaterThan(0);
        expect(result.isValid).toBe(false);
        // Verify it's the correct rule
        const error = result.errors.find((e) => e.rule === 'sanitizer.dangerousProtocolDetected');
        expect(error).toBeDefined();
      });

      it('handles script tags appropriately', () => {
        const html = '<script>alert("test");</script>';
        const result = validateHTML(html);

        expect(result).toBeDefined();
        expect(typeof result.isValid).toBe('boolean');
      });

      it('allows safe protocols', () => {
        const html = '<a href="https://example.com">Safe link</a>';
        const result = validateHTML(html);

        expect(result).toBeDefined();
        expect(typeof result.isValid).toBe('boolean');
      });
    });

    describe('Variant-Specific Validations', () => {
      describe('Email Variant', () => {
        it('processes email-specific content', () => {
          const html = '<canvas width="100" height="100"></canvas>';
          const result = validateHTML(html, 'email');

          expect(result).toBeDefined();
          expect(typeof result.isValid).toBe('boolean');
        });

        it('handles video elements in email context', () => {
          const html = '<video src="video.mp4"></video>';
          const result = validateHTML(html, 'email');

          expect(result).toBeDefined();
          expect(typeof result.isValid).toBe('boolean');
        });

        it('handles CSS media queries in email context', () => {
          const html = '<style>@media (max-width: 600px) { .mobile { display: block; } }</style>';
          const result = validateHTML(html, 'email');

          expect(result).toBeDefined();
          expect(typeof result.isValid).toBe('boolean');
        });

        it('handles SVG elements in email context', () => {
          const html = '<svg><circle r="10"></circle></svg>';
          const result = validateHTML(html, 'email');

          expect(result).toBeDefined();
          expect(typeof result.isValid).toBe('boolean');
        });
      });

      describe('InApp Variant', () => {
        it('processes inapp-specific content', () => {
          const html = '<object data="flash.swf"></object>';
          const result = validateHTML(html, 'inapp');

          expect(result).toBeDefined();
          expect(typeof result.isValid).toBe('boolean');
        });

        it('handles embed elements in inapp context', () => {
          const html = '<embed src="plugin.swf">';
          const result = validateHTML(html, 'inapp');

          expect(result).toBeDefined();
          expect(typeof result.isValid).toBe('boolean');
        });

        it('handles large dimensions in inapp context', () => {
          const html = '<div style="width: 800px; height: 600px;">Large content</div>';
          const result = validateHTML(html, 'inapp');

          expect(result).toBeDefined();
          expect(typeof result.isValid).toBe('boolean');
        });

        it('handles applet elements in inapp context', () => {
          const html = '<applet code="MyApplet.class"></applet>';
          const result = validateHTML(html, 'inapp');

          expect(result).toBeDefined();
          expect(typeof result.isValid).toBe('boolean');
        });
      });

      it('defaults to email variant when no variant specified', () => {
        const html = '<canvas></canvas>';
        const result = validateHTML(html); // No variant specified

        expect(result).toBeDefined();
        expect(typeof result.isValid).toBe('boolean');
      });

      it('handles unknown variant gracefully', () => {
        const html = '<div>Test</div>';
        const result = validateHTML(html, 'unknown-variant');

        expect(result).toBeDefined();
        expect(typeof result.isValid).toBe('boolean');
      });
    });

    describe('Complex HTML Structures', () => {
      it('handles deeply nested HTML', () => {
        let nestedHTML = '<div>';
        for (let i = 0; i < 50; i++) {
          nestedHTML += `<div class="level-${i}">`;
        }
        nestedHTML += 'Deep content';
        for (let i = 0; i < 50; i++) {
          nestedHTML += '</div>';
        }
        nestedHTML += '</div>';

        const result = validateHTML(nestedHTML);

        expect(result).toBeDefined();
        expect(typeof result.isValid).toBe('boolean');
      });

      it('handles HTML with mixed content types', () => {
        const html = `
          <!DOCTYPE html>
          <html>
          <head>
            <style>
              .test { color: red; }
            </style>
          </head>
          <body>
            <div class="test">
              <h1>Title</h1>
              <p>Paragraph with <strong>bold</strong> text</p>
              <img src="image.jpg" alt="Image">
              <a href="https://example.com">Link</a>
            </div>
          </body>
          </html>
        `;

        const result = validateHTML(html);

        expect(result).toBeDefined();
        expect(typeof result.isValid).toBe('boolean');
      });

      it('handles HTML fragments without doctype', () => {
        const html = `
          <div class="container">
            <h2>Fragment Title</h2>
            <p>This is a fragment without DOCTYPE</p>
          </div>
        `;

        const result = validateHTML(html);

        expect(result).toBeDefined();
        expect(typeof result.isValid).toBe('boolean');
      });

      it('handles HTML with comments and CDATA', () => {
        const html = `
          <!-- HTML Comment -->
          <div>
            <script>
              <![CDATA[
                var x = 1;
              ]]>
            </script>
          </div>
        `;

        const result = validateHTML(html);

        expect(result).toBeDefined();
        expect(typeof result.isValid).toBe('boolean');
      });
    });
  });

  describe('Enhanced validateCSS Tests', () => {
    describe('Input Validation', () => {
      it('handles empty CSS gracefully', () => {
        const result = validateCSS('');

        expect(result.isValid).toBe(true);
        expect(result.errors.length).toBe(0);
        expect(result.warnings.length).toBe(0);
        expect(result.info.length).toBe(0);
      });

      it('handles null CSS gracefully', () => {
        const result = validateCSS(null);

        expect(result.isValid).toBe(true);
        expect(result.errors.length).toBe(0);
      });

      it('handles undefined CSS gracefully', () => {
        const result = validateCSS(undefined);

        expect(result.isValid).toBe(true);
        expect(result.errors.length).toBe(0);
      });

      it('handles non-string CSS gracefully', () => {
        const result = validateCSS(123);

        expect(result.isValid).toBe(true);
        expect(result.errors.length).toBe(0);
      });

      it('handles whitespace-only CSS', () => {
        const result = validateCSS('   \n\t  ');

        expect(result.isValid).toBe(true);
      });
    });

    describe('CSS Validation Patterns', () => {
      it('validates well-formed CSS', () => {
        const css = `
          .class1 {
            color: red;
            background: blue;
          }

          .class2 {
            font-size: 16px;
            margin: 10px;
          }
        `;
        const result = validateCSS(css);

        expect(result).toBeDefined();
        expect(typeof result.isValid).toBe('boolean');
      });

      it('handles CSS with media queries', () => {
        const css = `
          @media (max-width: 600px) {
            .mobile {
              display: block;
            }
          }
        `;
        const result = validateCSS(css);

        expect(result).toBeDefined();
        expect(typeof result.isValid).toBe('boolean');
      });

      it('handles CSS with keyframes', () => {
        const css = `
          @keyframes slide {
            from { left: 0; }
            to { left: 100px; }
          }
        `;
        const result = validateCSS(css);

        expect(result).toBeDefined();
        expect(typeof result.isValid).toBe('boolean');
      });

      it('handles CSS with comments', () => {
        const css = `
          /* Main styles */
          .class {
            color: red; /* Red color */
          }
        `;
        const result = validateCSS(css);

        expect(result).toBeDefined();
        expect(typeof result.isValid).toBe('boolean');
      });

      it('handles CSS with special characters', () => {
        const css = `.unicode-class { content: "🎉"; }`;
        const result = validateCSS(css);

        expect(result).toBeDefined();
        expect(typeof result.isValid).toBe('boolean');
      });

      it('handles very long CSS content', () => {
        const longCSS = `.long { ${'color: red; '.repeat(1000)}}`;
        const result = validateCSS(longCSS);

        expect(result).toBeDefined();
        expect(typeof result.isValid).toBe('boolean');
      });
    });

    describe('Malformed CSS Detection', () => {
      it('detects unclosed braces', () => {
        const css = `
          .class1 {
            color: red;
          .class2 {
            background: blue;
        `;
        const result = validateCSS(css);

        expect(result).toBeDefined();
        // CSS validation issues are WARNINGS (not blocking errors)
        expect(result.warnings.length).toBeGreaterThan(0);
        // isValid can be true if only warnings exist (warnings don't block)
        expect(typeof result.isValid).toBe('boolean');
      });

      it('detects empty rules', () => {
        const css = `
          .empty1 { }
          .empty2 {  }
        `;
        const result = validateCSS(css);

        expect(result).toBeDefined();
        // CSS validation issues are WARNINGS (not blocking errors)
        expect(result.warnings.length).toBeGreaterThan(0);
        // isValid can be true if only warnings exist (warnings don't block)
        expect(typeof result.isValid).toBe('boolean');
      });
    });
  });

  describe('Enhanced extractAndValidateCSS Tests', () => {
    describe('Style Tag Extraction', () => {
      it('handles HTML without style tags', () => {
        const html = '<div>No styles here</div>';
        const result = extractAndValidateCSS(html);

        expect(result.isValid).toBe(true);
        expect(result.errors.length).toBe(0);
        expect(result.warnings.length).toBe(0);
        expect(result.info.length).toBe(0);
      });

      it('handles empty HTML', () => {
        const result = extractAndValidateCSS('');

        expect(result.isValid).toBe(true);
        expect(result.errors.length).toBe(0);
      });

      it('handles null HTML', () => {
        const result = extractAndValidateCSS(null);

        expect(result.isValid).toBe(true);
        expect(result.errors.length).toBe(0);
      });

      it('extracts and validates single style tag', () => {
        const html = `
          <style>
            .class1 { color: red; }
          </style>
        `;
        const result = extractAndValidateCSS(html);

        expect(result).toBeDefined();
        expect(typeof result.isValid).toBe('boolean');
      });

      it('extracts and validates multiple style tags', () => {
        const html = `
          <style>.class1 { color: red; }</style>
          <div>Content</div>
          <style>.class2 { background: blue; }</style>
        `;
        const result = extractAndValidateCSS(html);

        expect(result).toBeDefined();
        expect(typeof result.isValid).toBe('boolean');
      });

      it('handles style tags with attributes', () => {
        const html = `
          <style type="text/css" media="screen">
            .screen-only { display: block; }
          </style>
        `;
        const result = extractAndValidateCSS(html);

        expect(result).toBeDefined();
        expect(typeof result.isValid).toBe('boolean');
      });

      it('handles empty style tags', () => {
        const html = '<style></style>';
        const result = extractAndValidateCSS(html);

        expect(result.isValid).toBe(true);
      });

      it('handles case-insensitive style tags', () => {
        const html = '<STYLE>.uppercase { color: red; }</STYLE>';
        const result = extractAndValidateCSS(html);

        expect(result).toBeDefined();
        expect(typeof result.isValid).toBe('boolean');
      });

      it('handles malformed style tags', () => {
        const html = '<style>Incomplete CSS without closing';
        const result = extractAndValidateCSS(html);

        expect(result).toBeDefined();
        // CSS validation issues are WARNINGS (not blocking errors)
        expect(result.warnings.length).toBeGreaterThan(0);
        // isValid can be true if only warnings exist (warnings don't block)
        expect(typeof result.isValid).toBe('boolean');
      });
    });

    describe('Complex CSS Extraction Scenarios', () => {
      it('handles style tags with CDATA', () => {
        const html = `
          <style>
            <![CDATA[
              .cdata-style { color: blue; }
            ]]>
          </style>
        `;
        const result = extractAndValidateCSS(html);

        expect(result).toBeDefined();
        expect(typeof result.isValid).toBe('boolean');
      });

      it('merges results from multiple style tags', () => {
        const html = `
          <style>.valid { color: red; }</style>
          <style>.another { background: blue; }</style>
        `;
        const result = extractAndValidateCSS(html);

        expect(result).toBeDefined();
        expect(typeof result.isValid).toBe('boolean');
      });
    });
  });

  describe('Error Handling and Edge Cases', () => {
    it('handles HTMLHint validation errors gracefully', () => {
      // Mock HTMLHint to throw an error
      const originalHTMLHint = require('htmlhint').HTMLHint;
      const mockHTMLHint = {
        verify: jest.fn(() => {
          throw new Error('HTMLHint validation failed');
        }),
      };

      // Temporarily replace HTMLHint
      require('htmlhint').HTMLHint = mockHTMLHint;

      const html = '<div>Test content</div>';
      const result = validateHTML(html);

      // HTMLHint errors are caught and handled gracefully - result should still be defined
      // When HTMLHint throws, it's caught and a warning is added (not an error)
      expect(result).toBeDefined();
      expect(typeof result.isValid).toBe('boolean');
      // HTMLHint errors are converted to warnings in the catch block
      expect(result.warnings.length).toBeGreaterThan(0);
      expect(result.warnings[0].message).toContain('HTMLHint validation failed');

      // Restore original HTMLHint
      require('htmlhint').HTMLHint = originalHTMLHint;
    });

    it('handles Liquid validation errors gracefully', () => {
      // Get the mocked module and set it to throw an error
      const { validateLiquidHTML } = require('../liquidTemplateSupport');
      validateLiquidHTML.mockImplementation(() => {
        throw new Error('Liquid validation failed');
      });

      const html = '<div>{{ liquid.template }}</div>';
      const result = validateHTML(html);

      // Should not fail the entire validation
      expect(result).toBeDefined();
      expect(typeof result.isValid).toBe('boolean');

      // Reset the mock after test
      validateLiquidHTML.mockReset();
    });

    it('handles CSS validation errors gracefully', () => {
      // Test CSS validation with try-catch error handling
      const css = 'invalid css that causes error';

      // Mock getLineNumber to throw an error to trigger the catch block
      const originalGetLineNumber = require('../htmlValidator').getLineNumber;

      // We can't directly mock the internal function, so let's create a scenario
      // that would cause the validation to fail and enter the catch block
      const result = validateCSS(css);

      // The CSS itself should be processed normally since it doesn't contain invalid patterns
      expect(result).toBeDefined();
      expect(typeof result.isValid).toBe('boolean');
    });
  });

  describe('Message Formatter Tests', () => {
    it('uses custom message formatter when provided', () => {
      const customFormatter = jest.fn((key, values) => `Custom: ${key} - ${JSON.stringify(values)}`);

      const html = '<a href="javascript:alert(1)">Unsafe link</a>';
      const result = validateHTML(html, 'email', customFormatter);

      expect(customFormatter).toHaveBeenCalled();
      expect(result.errors.length).toBeGreaterThan(0);
    });

    it('falls back to default formatter when custom formatter fails', () => {
      const failingFormatter = jest.fn((key, values) =>
        // Don't throw error, just return the key as fallback behavior
        key);

      const html = '<a href="javascript:alert(1)">Unsafe link</a>';
      const result = validateHTML(html, 'email', failingFormatter);

      expect(failingFormatter).toHaveBeenCalled();
      expect(result).toBeDefined();
      expect(typeof result.isValid).toBe('boolean');
    });

    it('handles unknown message keys in default formatter', () => {
      const html = '<div>Test</div>';
      const result = validateHTML(html);

      // Test that default formatter handles unknown keys
      expect(result).toBeDefined();
    });
  });

  describe('Line Number Utility Tests', () => {
    it('handles edge cases in getLineNumber function', () => {
      // Test with undefined position
      const html = 'line1\nline2\nline3';

      // We need to test the internal getLineNumber function
      // Since it's not exported, we'll test it indirectly through validation
      const htmlWithError = '<a href="javascript:alert(1)">Test</a>';
      const result = validateHTML(htmlWithError);

      expect(result.errors.length).toBeGreaterThan(0);
      expect(result.errors[0].line).toBeGreaterThanOrEqual(1);
    });

    it('calculates correct line numbers for multi-line content', () => {
      const multiLineHtml = `line1
line2
<a href="javascript:alert(1)">line3</a>
line4`;

      const result = validateHTML(multiLineHtml);

      expect(result.errors.length).toBeGreaterThan(0);
      // Line number calculation depends on the position of the unsafe protocol
      expect(result.errors[0].line).toBeGreaterThanOrEqual(1);
    });

    it('handles negative position in line number calculation', () => {
      // This tests the edge case where position < 0
      const html = '<a href="javascript:alert(1)">Test</a>';
      const result = validateHTML(html);

      expect(result.errors.length).toBeGreaterThan(0);
      expect(result.errors[0].line).toBeGreaterThanOrEqual(1);
    });
  });

  describe('Regex Pattern Edge Cases', () => {
    it('handles zero-length matches in unsafe protocols', () => {
      // Test content that might cause zero-length matches
      const html = '<a href="javascript:">Empty script</a>';
      const result = validateHTML(html);

      expect(result.errors.length).toBeGreaterThan(0);
      expect(result.isValid).toBe(false);
    });

    it('handles zero-length matches in script tags', () => {
      const html = '<script></script>';
      const result = validateHTML(html);

      // Should handle empty script tags
      expect(result).toBeDefined();
    });

    it('handles zero-length matches in CSS validation', () => {
      const css = '.class { }';
      const result = validateCSS(css);

      // CSS validation issues are WARNINGS (not blocking errors)
      expect(result.warnings.length).toBeGreaterThan(0);
      // isValid can be true if only warnings exist (warnings don't block)
      expect(typeof result.isValid).toBe('boolean');
    });

    it('handles multiple consecutive unsafe protocols', () => {
      const html = `
        <a href="javascript:alert(1)">Link 1</a>
        <a href="javascript:alert(2)">Link 2</a>
        <img src="data:image/svg+xml,<svg>">
      `;
      const result = validateHTML(html);

      // Should detect at least one unsafe protocol
      expect(result.errors.length).toBeGreaterThanOrEqual(1);
      expect(result.isValid).toBe(false);
    });

    it('handles multiple script tags', () => {
      const html = `
        <script>alert(1);</script>
        <script>alert(2);</script>
      `;
      const result = validateHTML(html);

      // Should detect at least one script tag warning
      expect(result.warnings.length).toBeGreaterThanOrEqual(1);
    });
  });

  describe('Liquid Validation Integration', () => {
    it('merges liquid validation results correctly', () => {
      // Get the mocked module and set it to return specific results
      const { validateLiquidHTML } = require('../liquidTemplateSupport');
      validateLiquidHTML.mockImplementation(() => ({
        errors: [{
          type: 'error', message: 'Liquid error', line: 1, column: 1, rule: 'liquid-test', severity: 'error', source: 'liquid',
        }],
        warnings: [{
          type: 'warning', message: 'Liquid warning', line: 1, column: 1, rule: 'liquid-test', severity: 'warning', source: 'liquid',
        }],
        info: [{
          type: 'info', message: 'Liquid info', line: 1, column: 1, rule: 'liquid-test', severity: 'info', source: 'liquid',
        }],
      }));

      const html = '<div>{{ liquid.template }}</div>';
      const result = validateHTML(html);

      // Should merge liquid results
      expect(result).toBeDefined();
      expect(typeof result.isValid).toBe('boolean');

      // Reset the mock after test
      validateLiquidHTML.mockReset();
    });

    it('handles liquid validation with no results', () => {
      // Get the mocked module and set it to return empty results
      const { validateLiquidHTML } = require('../liquidTemplateSupport');
      validateLiquidHTML.mockImplementation(() => ({}));

      const html = '<div>{{ liquid.template }}</div>';
      const result = validateHTML(html);

      expect(result).toBeDefined();
      expect(typeof result.isValid).toBe('boolean');

      // Reset the mock after test
      validateLiquidHTML.mockReset();
    });

    it('handles liquid validation with partial results', () => {
      // Get the mocked module and set it to return only some result types
      const { validateLiquidHTML } = require('../liquidTemplateSupport');
      validateLiquidHTML.mockImplementation(() => ({
        errors: [{
          type: 'error', message: 'Liquid error', line: 1, column: 1, rule: 'liquid-test', severity: 'error', source: 'liquid',
        }],
        // Missing warnings and info arrays
      }));

      const html = '<div>{{ liquid.template }}</div>';
      const result = validateHTML(html);

      expect(result).toBeDefined();
      expect(typeof result.isValid).toBe('boolean');

      // Reset the mock after test
      validateLiquidHTML.mockReset();
    });

    it('handles liquid validation with only warnings', () => {
      // Get the mocked module and set it to return only warnings
      const { validateLiquidHTML } = require('../liquidTemplateSupport');
      validateLiquidHTML.mockImplementation(() => ({
        warnings: [{
          type: 'warning', message: 'Liquid warning', line: 1, column: 1, rule: 'liquid-test', severity: 'warning', source: 'liquid',
        }],
      }));

      const html = '<div>{{ liquid.template }}</div>';
      const result = validateHTML(html);

      expect(result).toBeDefined();
      expect(typeof result.isValid).toBe('boolean');

      // Reset the mock after test
      validateLiquidHTML.mockReset();
    });

    it('handles liquid validation with only info', () => {
      // Get the mocked module and set it to return only info
      const { validateLiquidHTML } = require('../liquidTemplateSupport');
      validateLiquidHTML.mockImplementation(() => ({
        info: [{
          type: 'info', message: 'Liquid info', line: 1, column: 1, rule: 'liquid-test', severity: 'info', source: 'liquid',
        }],
      }));

      const html = '<div>{{ liquid.template }}</div>';
      const result = validateHTML(html);

      expect(result).toBeDefined();
      expect(typeof result.isValid).toBe('boolean');

      // Reset the mock after test
      validateLiquidHTML.mockReset();
    });
  });

  describe('Advanced CSS Validation Edge Cases', () => {
    it('handles CSS with multiple unclosed braces', () => {
      const css = `
        .class1 {
          color: red;
        .class2 {
          background: blue;
        .class3 {
          font-size: 16px;
      `;
      const result = validateCSS(css);

      // CSS validation issues are WARNINGS (not blocking errors)
      expect(result.warnings.length).toBeGreaterThan(0);
      // isValid can be true if only warnings exist (warnings don't block)
      expect(typeof result.isValid).toBe('boolean');
    });

    it('handles CSS with nested braces', () => {
      const css = `
        @media (max-width: 600px) {
          .mobile {
            color: red;
      `;
      const result = validateCSS(css);

      // CSS validation issues are WARNINGS (not blocking errors)
      expect(result.warnings.length).toBeGreaterThan(0);
      // isValid can be true if only warnings exist (warnings don't block)
      expect(typeof result.isValid).toBe('boolean');
    });

    it('handles CSS with mixed valid and invalid rules', () => {
      const css = `
        .valid { color: red; }
        .empty1 { }
        .another-valid { background: blue; }
        .empty2 {  }
      `;
      const result = validateCSS(css);

      // CSS validation issues are WARNINGS (not blocking errors)
      // Should detect at least one empty rule as warning
      expect(result.warnings.length).toBeGreaterThanOrEqual(1);
      // isValid can be true if only warnings exist (warnings don't block)
      expect(typeof result.isValid).toBe('boolean');
    });

    it('handles CSS validation exception scenarios', () => {
      // Test with extremely malformed CSS that might cause regex issues
      const malformedCSS = 'invalid{{{{{css}}}}}content';
      const result = validateCSS(malformedCSS);

      expect(result).toBeDefined();
      expect(typeof result.isValid).toBe('boolean');
    });
  });

  describe('Severity Level Classification', () => {
    it('classifies different error types correctly', () => {
      // Test HTML that triggers different severity levels
      const htmlWithErrors = `
        <DIV id="test" id="duplicate">
          <IMG src="">
          <p>Unclosed paragraph
        </div>
      `;

      const result = validateHTML(htmlWithErrors);

      expect(result).toBeDefined();
      expect(result.errors.length + result.warnings.length + result.info.length).toBeGreaterThan(0);
    });

    it('handles unknown rule IDs in severity classification', () => {
      // This tests the default case in getSeverityLevel
      const html = '<div>Test content</div>';
      const result = validateHTML(html);

      expect(result).toBeDefined();
      expect(typeof result.isValid).toBe('boolean');
    });
  });

  describe('getSeverityLevel edge cases (lines 112-118, 159-166)', () => {
    it('categorizes warning-level HTMLHint rules as warnings', () => {
      // Test with HTML that triggers known warning rules like tag-pair
      const html = '<p>Unclosed paragraph tag';
      const result = validateHTML(html);

      // Should have warnings for unclosed tag
      expect(result).toBeDefined();
      expect(result.warnings.length).toBeGreaterThanOrEqual(0);
    });

    it('categorizes attr-no-duplication rule as warning', () => {
      const html = '<div class="test" class="duplicate">Duplicate attribute</div>';
      const result = validateHTML(html);

      expect(result).toBeDefined();
      // Should categorize as warning based on warningRules list
      expect(typeof result.isValid).toBe('boolean');
    });

    it('categorizes id-unique rule as warning', () => {
      const html = '<div id="unique"><span id="unique">Duplicate ID</span></div>';
      const result = validateHTML(html);

      expect(result).toBeDefined();
      expect(typeof result.isValid).toBe('boolean');
    });

    it('categorizes spec-char-escape rule as warning', () => {
      const html = '<p>Special characters & < ></p>';
      const result = validateHTML(html);

      expect(result).toBeDefined();
      expect(typeof result.isValid).toBe('boolean');
    });

    it('categorizes tagname-lowercase rule as warning', () => {
      const html = '<DIV><P>Uppercase tags</P></DIV>';
      const result = validateHTML(html);

      expect(result).toBeDefined();
      expect(typeof result.isValid).toBe('boolean');
    });

    it('categorizes alt-require rule as warning', () => {
      const html = '<img src="test.jpg">';
      const result = validateHTML(html);

      expect(result).toBeDefined();
      expect(typeof result.isValid).toBe('boolean');
    });

    it('downgrades HTMLHint error type to warning (line 163-164)', () => {
      // HTMLHint "error" types that are not in warningRules should be downgraded to warning
      // This covers the case where type === 'error' returns 'warning'
      const htmlWithStructuralError = '<div><span>Missing closing span</div>';
      const result = validateHTML(htmlWithStructuralError);

      expect(result).toBeDefined();
      // Structural HTML errors are downgraded to warnings
      expect(typeof result.isValid).toBe('boolean');
    });

    it('returns info for non-warning, non-error types (line 166)', () => {
      // Test content that would produce info-level issues
      const simpleHtml = '<div></div>';
      const result = validateHTML(simpleHtml);

      expect(result).toBeDefined();
      expect(typeof result.isValid).toBe('boolean');
      // Info array should exist
      expect(Array.isArray(result.info)).toBe(true);
    });

    it('processes multiple issues with different severity levels (lines 112-118)', () => {
      // HTML that produces multiple issues with different severities
      const mixedHtml = `
        <DIV class="test" class="dup">
          <IMG src="">
          <P>Text
        </DIV>
      `;
      const result = validateHTML(mixedHtml);

      expect(result).toBeDefined();
      // Should process and categorize issues correctly
      expect(Array.isArray(result.errors)).toBe(true);
      expect(Array.isArray(result.warnings)).toBe(true);
      expect(Array.isArray(result.info)).toBe(true);
    });

    it('pushes warning severity to warnings array (line 112-113)', () => {
      // This specifically tests when error.severity === 'warning'
      const htmlWithWarnings = '<DIV></DIV>'; // Uppercase tag names
      const result = validateHTML(htmlWithWarnings);

      expect(result).toBeDefined();
      // Warnings should be in the warnings array
      expect(Array.isArray(result.warnings)).toBe(true);
    });

    it('pushes info severity to info array (line 114-115)', () => {
      // Content that produces info-level validation results
      const simpleContent = '<div><p>Valid content</p></div>';
      const result = validateHTML(simpleContent);

      expect(result).toBeDefined();
      expect(Array.isArray(result.info)).toBe(true);
    });

    it('pushes other severities to warnings array as fallback (line 116-117)', () => {
      // This covers the else branch where unknown severities go to warnings
      const html = '<div>Test</div>';
      const result = validateHTML(html);

      expect(result).toBeDefined();
      expect(Array.isArray(result.warnings)).toBe(true);
    });

    it('routes warning-severity issues to warnings array — exact item check (line 112-113)', () => {
      // Mock HTMLHint to return an issue with a warningRule ruleId
      // getSeverityLevel('error', 'tag-pair') → 'warning' (warningRules match)
      const htmlhint = require('htmlhint');
      const original = htmlhint.HTMLHint.verify;
      htmlhint.HTMLHint.verify = jest.fn(() => ([
        {
          type: 'error',
          message: 'Tag must be paired',
          line: 1,
          col: 5,
          rule: { id: 'tag-pair' },
        },
      ]));

      const result = validateHTML('<p>unclosed');

      expect(result.warnings.length).toBeGreaterThanOrEqual(1);
      const item = result.warnings.find((w) => w.rule === 'tag-pair');
      expect(item).toBeDefined();
      expect(item.severity).toBe('warning');

      htmlhint.HTMLHint.verify = original;
    });

    it('routes info-severity issues to info array — exact item check (line 114-115)', () => {
      // getSeverityLevel('warning', 'space-tab-mixed-disabled') → 'info'
      // (not in warningRules, type !== 'error')
      const htmlhint = require('htmlhint');
      const original = htmlhint.HTMLHint.verify;
      htmlhint.HTMLHint.verify = jest.fn(() => ([
        {
          type: 'warning',
          message: 'Mixed spaces and tabs',
          line: 1,
          col: 1,
          rule: { id: 'space-tab-mixed-disabled' },
        },
      ]));

      const result = validateHTML('<div>test</div>');

      expect(result.info.length).toBeGreaterThanOrEqual(1);
      const item = result.info.find((i) => i.rule === 'space-tab-mixed-disabled');
      expect(item).toBeDefined();
      expect(item.severity).toBe('info');

      htmlhint.HTMLHint.verify = original;
    });

    it('downgrades HTMLHint error type to warning for non-warningRule (line 163-164) — exact item check', () => {
      // getSeverityLevel('error', 'src-not-empty') → 'warning' (not in warningRules, but type === 'error')
      const htmlhint = require('htmlhint');
      const original = htmlhint.HTMLHint.verify;
      htmlhint.HTMLHint.verify = jest.fn(() => ([
        {
          type: 'error',
          message: 'The src attribute cannot be empty',
          line: 1,
          col: 1,
          rule: { id: 'src-not-empty' },
        },
      ]));

      const result = validateHTML('<img src="">');

      // Should be downgraded to warning (not error)
      expect(result.warnings.length).toBeGreaterThanOrEqual(1);
      const item = result.warnings.find((w) => w.rule === 'src-not-empty');
      expect(item).toBeDefined();
      expect(item.severity).toBe('warning');
      // Should NOT be in errors
      expect(result.errors.find((e) => e.rule === 'src-not-empty')).toBeUndefined();

      htmlhint.HTMLHint.verify = original;
    });

    it('returns info for HTMLHint warning type with unknown ruleId (line 165-166)', () => {
      // getSeverityLevel('warning', 'unknown-rule') → 'info' (no warningRules match, type !== 'error')
      const htmlhint = require('htmlhint');
      const original = htmlhint.HTMLHint.verify;
      htmlhint.HTMLHint.verify = jest.fn(() => ([
        {
          type: 'warning',
          message: 'Some custom warning',
          line: 2,
          col: 3,
          rule: { id: 'unknown-custom-rule' },
        },
      ]));

      const result = validateHTML('<div>test</div>');

      expect(result.info.length).toBeGreaterThanOrEqual(1);
      const item = result.info.find((i) => i.rule === 'unknown-custom-rule');
      expect(item).toBeDefined();
      expect(item.severity).toBe('info');
      expect(item.line).toBe(2);
      expect(item.column).toBe(3);
      // Should NOT be in errors or warnings
      expect(result.errors.find((e) => e.rule === 'unknown-custom-rule')).toBeUndefined();
      expect(result.warnings.find((w) => w.rule === 'unknown-custom-rule')).toBeUndefined();

      htmlhint.HTMLHint.verify = original;
    });

    it('processes multiple HTMLHint issues with mixed severity correctly (lines 101-118)', () => {
      const htmlhint = require('htmlhint');
      const original = htmlhint.HTMLHint.verify;
      htmlhint.HTMLHint.verify = jest.fn(() => ([
        { type: 'error', message: 'Tag pair', line: 1, col: 1, rule: { id: 'tag-pair' } },           // → warning
        { type: 'error', message: 'Src empty', line: 2, col: 1, rule: { id: 'src-not-empty' } },     // → warning (downgrade)
        { type: 'warning', message: 'Mixed tabs', line: 3, col: 1, rule: { id: 'space-tab-mixed-disabled' } }, // → info
      ]));

      const result = validateHTML('<div>test</div>');

      const tagPair = result.warnings.find((w) => w.rule === 'tag-pair');
      expect(tagPair).toBeDefined();
      expect(tagPair.severity).toBe('warning');

      const srcEmpty = result.warnings.find((w) => w.rule === 'src-not-empty');
      expect(srcEmpty).toBeDefined();
      expect(srcEmpty.severity).toBe('warning');

      const mixedTabs = result.info.find((i) => i.rule === 'space-tab-mixed-disabled');
      expect(mixedTabs).toBeDefined();
      expect(mixedTabs.severity).toBe('info');

      htmlhint.HTMLHint.verify = original;
    });
  });

  describe('extractAndValidateCSS Advanced Tests', () => {
    it('handles multiple style tags with mixed validity', () => {
      const html = `
        <style>.valid { color: red; }</style>
        <div>Content</div>
        <style>.empty { }</style>
        <style>.another-valid { background: blue; }</style>
      `;
      const result = extractAndValidateCSS(html);

      // CSS validation issues are WARNINGS (not blocking errors)
      expect(result.warnings.length).toBeGreaterThan(0);
      // isValid can be true if only warnings exist (warnings don't block)
      expect(typeof result.isValid).toBe('boolean');
    });

    it('handles style tags with complex CSS', () => {
      const html = `
        <style>
          @media (max-width: 600px) {
            .mobile { display: block; }
          }
          .desktop { display: none; }
          .empty { }
        </style>
      `;
      const result = extractAndValidateCSS(html);

      // CSS validation issues are WARNINGS (not blocking errors)
      expect(result.warnings.length).toBeGreaterThan(0);
      // isValid can be true if only warnings exist (warnings don't block)
      expect(typeof result.isValid).toBe('boolean');
    });

    it('correctly identifies unclosed style tags', () => {
      const html = '<style>.test { color: red; }';
      const result = extractAndValidateCSS(html);

      // CSS validation issues are WARNINGS (not blocking errors)
      expect(result.warnings.length).toBeGreaterThan(0);
      expect(result.warnings.some((warning) => warning.rule === 'unclosed-style-tag')).toBe(true);
      // isValid can be true if only warnings exist (warnings don't block)
      expect(typeof result.isValid).toBe('boolean');
    });

    it('handles multiple unclosed style tags', () => {
      const html = `
        <style>.test1 { color: red; }
        <div>Content</div>
        <style>.test2 { background: blue; }
      `;
      const result = extractAndValidateCSS(html);

      // CSS validation issues are WARNINGS (not blocking errors)
      expect(result.warnings.length).toBeGreaterThan(0);
      // isValid can be true if only warnings exist (warnings don't block)
      expect(typeof result.isValid).toBe('boolean');
    });
  });

  describe('Performance and Integration Tests', () => {
    it('handles complex HTML with all validation types', () => {
      const html = `
        <!DOCTYPE html>
        <html>
        <head>
          <style>
            .valid { color: red; }
            .test { background: blue; }
          </style>
        </head>
        <body>
          <div class="test">
            <h1>Title</h1>
            <p>Content with <a href="https://example.com">safe link</a></p>
            <img src="image.jpg" alt="Image">
          </div>
        </body>
        </html>
      `;

      const result = validateHTML(html, 'email');

      expect(result).toBeDefined();
      expect(typeof result.isValid).toBe('boolean');
    });

    it('maintains performance with multiple validation runs', () => {
      const html = '<div class="test">Performance test</div>';

      const startTime = performance.now();
      for (let i = 0; i < 50; i++) {
        validateHTML(html);
      }
      const endTime = performance.now();
      const duration = endTime - startTime;

      // Should complete 50 validations reasonably quickly
      expect(duration).toBeGreaterThan(0);
      expect(duration).toBeLessThan(5000); // 5 seconds should be more than enough
    });

    it('handles validation of different content types', () => {
      const testCases = [
        '<div>Simple HTML</div>',
        '<table><tr><td>Table content</td></tr></table>',
        '<form><input type="text"><button>Submit</button></form>',
        '<ul><li>List item 1</li><li>List item 2</li></ul>',
        '<article><header><h1>Article</h1></header><p>Content</p></article>',
      ];

      testCases.forEach((html) => {
        const result = validateHTML(html);
        expect(result).toBeDefined();
        expect(typeof result.isValid).toBe('boolean');
      });
    });

    it('validates both email and inapp variants consistently', () => {
      const html = '<div class="container"><p>Test content</p></div>';

      const emailResult = validateHTML(html, 'email');
      const inappResult = validateHTML(html, 'inapp');

      expect(emailResult).toBeDefined();
      expect(inappResult).toBeDefined();
      expect(typeof emailResult.isValid).toBe('boolean');
      expect(typeof inappResult.isValid).toBe('boolean');
    });
  });
});
