/**
 * ESLint rule to forbid raw HTML in app/, components/, and templates/ directories
 * 
 * All HTML must be encapsulated in React components from ui/ directory
 * 
 * Rationale:
 * - app/ should only contain page/layout components
 * - components/ should use ui/ elements for all rendering
 * - templates/ should use ui/ elements for all rendering
 * - Raw HTML with styling violates separation of concerns
 * - UI elements ensure consistency and reusability
 */

module.exports = {
  meta: {
    type: 'problem',
    docs: {
      description: 'Forbid raw HTML with styling in app/, components/, and templates/ directories',
      category: 'Architecture',
      recommended: true,
    },
    fixable: null,
    schema: [],
    messages: {
      noRawHtml: 'Raw HTML with styling is forbidden. Use a UI element from ui/ directory.',
      noRawHtmlInApp: 'Raw HTML in app/ is forbidden. Use components/ or ui/ elements.',
      noRawHtmlInComponents: 'Raw HTML in components/ should use ui/ elements instead.',
      noRawHtmlInTemplates: 'Raw HTML in templates/ should use ui/ elements instead.',
    },
  },

  create(context) {
    const filename = context.getFilename();
    
    // Determine which layer we're in
    const isInApp = filename.includes('/app/');
    const isInComponents = filename.includes('/components/');
    const isInTemplates = filename.includes('/templates/');
    
    // Only apply to these UI layers
    if (!isInApp && !isInComponents && !isInTemplates) {
      return {};
    }

    // HTML tags that should be wrapped in UI elements
    const htmlTags = [
      'div', 'span', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
      'p', 'button', 'input', 'form', 'label', 'select', 'textarea',
      'ul', 'ol', 'li', 'table', 'tr', 'td', 'th', 'thead', 'tbody',
      'section', 'article', 'header', 'footer', 'nav', 'aside',
      'main', 'aside', 'figure', 'figcaption', 'blockquote', 'code',
      'pre', 'a', 'img', 'svg', 'path', 'g', 'rect', 'circle',
      'hr', 'br', 'strong', 'em', 'b', 'i', 'u', 'small', 'mark'
    ];

    // UI elements that are allowed (from ui/ directory)
    const allowedUiElements = [
      'Button', 'Input', 'Form', 'Label', 'Select', 'Textarea',
      'Card', 'Container', 'Grid', 'Stack', 'Box', 'Text', 'Heading',
      'List', 'Table', 'Section', 'Article', 'Header', 'Footer', 'Nav', 'Aside',
      'Link', 'Image', 'Icon', 'Avatar', 'Badge', 'Chip', 'Pill',
      'Modal', 'Dialog', 'Toast', 'Notification', 'Alert',
      'StepIndicator', 'Loading', 'Spinner', 'Progress'
    ];

    return {
      JSXElement(node) {
        const openingElement = node.openingElement;
        
        if (openingElement.name.type !== 'JSXIdentifier') return;
        
        const tagName = openingElement.name.name;
        
        // Skip allowed UI elements
        if (allowedUiElements.includes(tagName)) {
          return;
        }
        
        // Check if it's a raw HTML element (lowercase)
        if (htmlTags.includes(tagName) && tagName[0] === tagName[0].toLowerCase()) {
          
          // Check for styling attributes
          const hasClassName = openingElement.attributes.some(
            attr => attr.type === 'JSXAttribute' && attr.name.name === 'className'
          );
          const hasStyle = openingElement.attributes.some(
            attr => attr.type === 'JSXAttribute' && attr.name.name === 'style'
          );
          
          // Check for inline event handlers
          const hasInlineHandlers = openingElement.attributes.some(
            attr => attr.type === 'JSXAttribute' && 
                   attr.name.name && 
                   attr.name.name.startsWith('on')
          );
          
          // Check for other common attributes that suggest styling/behavior
          const hasCommonAttrs = openingElement.attributes.some(
            attr => attr.type === 'JSXAttribute' && 
                   ['id', 'role', 'aria-label', 'aria-hidden'].includes(attr.name.name)
          );
          
          if (hasClassName || hasStyle || hasInlineHandlers || hasCommonAttrs) {
            let messageId = 'noRawHtml';
            
            if (isInApp) {
              messageId = 'noRawHtmlInApp';
            } else if (isInComponents) {
              messageId = 'noRawHtmlInComponents';
            } else if (isInTemplates) {
              messageId = 'noRawHtmlInTemplates';
            }
            
            context.report({
              node,
              messageId,
            });
          }
        }
      },

      // Also check for dangerouslySetInnerHTML
      JSXAttribute(node) {
        if (node.name.name === 'dangerouslySetInnerHTML') {
          let messageId = 'noRawHtml';
          
          if (isInApp) {
            messageId = 'noRawHtmlInApp';
          } else if (isInComponents) {
            messageId = 'noRawHtmlInComponents';
          } else if (isInTemplates) {
            messageId = 'noRawHtmlInTemplates';
          }
          
          context.report({
            node,
            messageId,
          });
        }
      },

      // Check for HTML strings in JSX expressions
      JSXExpressionContainer(node) {
        if (node.expression.type === 'Literal' && typeof node.expression.value === 'string') {
          const value = node.expression.value.trim();
          
          // Check if it contains HTML-like content
          if (value.includes('<') && value.includes('>') && 
              (value.includes('class=') || value.includes('style=') || 
               value.match(/<\w+[^>]*>/))) {
            
            let messageId = 'noRawHtml';
            
            if (isInApp) {
              messageId = 'noRawHtmlInApp';
            } else if (isInComponents) {
              messageId = 'noRawHtmlInComponents';
            } else if (isInTemplates) {
              messageId = 'noRawHtmlInTemplates';
            }
            
            context.report({
              node,
              messageId,
            });
          }
        }
      },
    };
  },
};