/**
 * Rehype plugin to render Mermaid diagrams
 * 
 * This plugin processes code blocks with `language-mermaid` and replaces them
 * with structured HTML that will be enhanced client-side with interactive diagrams.
 */

import { visit } from 'unist-util-visit'
import type { Root, Element } from 'hast'
import type { Plugin } from 'unified'
import { MAX_CODE_LENGTH, validateMermaidSyntax, createErrorElement } from './security-constants'
import { logger } from '~/lib/logger'

interface MermaidOptions {
  // Options for Mermaid rendering
  theme?: string
  securityLevel?: string
}

const rehypeMermaid: Plugin<[MermaidOptions?], Root> = (options = {}) => { // eslint-disable-line @typescript-eslint/no-unused-vars
  return (tree: Root) => {
    const nodesToReplace: Array<{ parent: Root | Element; node: Element; index: number; mermaidCode: string }> = []

    visit(tree, 'element', (node: Element, index: number | undefined, parent: Root | Element | undefined) => {
      // Skip processing if we don't have necessary data
      if (parent === undefined || index === undefined) {
        return;
      }

      // Look for <pre><code class="language-mermaid">...</code></pre> patterns
      if (
        node.tagName === 'pre' &&
        node.children &&
        node.children.length === 1 &&
        node.children[0].type === 'element' &&
        node.children[0].tagName === 'code'
      ) {
        const codeElement = node.children[0] as Element
        
        // Check if it has the mermaid language class
        const className = codeElement.properties?.className as string[] | undefined
        if (className && className.includes('language-mermaid')) {
          // Extract Mermaid diagram code
          const textNode = codeElement.children?.[0]
          if (textNode && textNode.type === 'text') {
            const mermaidCode = textNode.value as string
            const trimmedCode = mermaidCode.trim()
            
            // Skip empty blocks
            if (!trimmedCode) return
            
            // Validate code length
            if (trimmedCode.length > MAX_CODE_LENGTH) {
              if (parent && index !== undefined) {
                parent.children[index] = createErrorElement(
                  'Mermaid diagram code exceeds maximum allowed length.',
                  'mermaid-diagram-error'
                )
              }
              return
            }
            
            // Validate Mermaid syntax for dangerous patterns
            if (!validateMermaidSyntax(trimmedCode)) {
              if (parent && index !== undefined) {
                parent.children[index] = createErrorElement(
                  'Mermaid diagram contains potentially unsafe content.',
                  'mermaid-diagram-error'
                )
              }
              return
            }
            
            nodesToReplace.push({
                parent,
                node,
                index,
                mermaidCode: mermaidCode.trim()
              })
            }
          }
      }
    })

    // Replace Mermaid code blocks with structured HTML
    nodesToReplace.forEach(({ parent, node, index, mermaidCode }) => { // eslint-disable-line @typescript-eslint/no-unused-vars
      try {
        // Generate a unique ID for this Mermaid diagram
        const id = `mermaid-diagram-${Math.random().toString(36).substr(2, 9)}`
        
        const wrapper: Element = {
          type: 'element',
          tagName: 'div',
          properties: {
            className: ['mermaid-diagram-wrapper', 'my-6', 'text-center', 'p-4', 'bg-gray-50', 'dark:bg-gray-800', 'rounded-lg', 'border', 'border-gray-200', 'dark:border-gray-700'],
            dataMermaidCode: mermaidCode,
            dataMermaidId: id
          },
          children: [
            {
              type: 'element',
              tagName: 'div',
              properties: {
                id,
                className: ['mermaid-diagram-container']
              },
              children: []
            },
            // Keep the original code as a fallback
            {
              type: 'element',
              tagName: 'details',
              properties: {
                className: ['mermaid-diagram-source', 'mt-4']
              },
              children: [
                {
                  type: 'element',
                  tagName: 'summary',
                  properties: {
                    className: ['text-sm', 'text-gray-600', 'dark:text-gray-400', 'cursor-pointer']
                  },
                  children: [
                    {
                      type: 'text',
                      value: 'Show Mermaid diagram source'
                    }
                  ]
                },
                {
                  type: 'element',
                  tagName: 'pre',
                  properties: {
                    className: ['mt-2', 'p-2', 'rounded', 'text-sm', 'overflow-auto']
                  },
                  children: [
                    {
                      type: 'element',
                      tagName: 'code',
                      properties: {},
                      children: [
                        {
                          type: 'text',
                          value: mermaidCode
                        }
                      ]
                    }
                  ]
                }
              ]
            }
          ]
        }

        // Replace the original pre/code block with our wrapper
        parent.children[index] = wrapper
      } catch (error) {
            logger.error({ error }, 'Error processing Mermaid diagram:')
            parent.children[index] = createErrorElement(
              'Failed to render diagram. Please check your syntax.',
              'mermaid-diagram-error'
            )
      }
    })
  }
}

export default rehypeMermaid