<template>
  <div class="child-html-renderer">
    <!-- HTML Header -->
    <div v-if="htmlTitle || htmlDescription" class="html-header mb-4">
      <h3 v-if="htmlTitle" class="text-lg font-semibold text-gray-900 mb-2">
        {{ htmlTitle }}
      </h3>
      <p v-if="htmlDescription" class="text-sm text-gray-600">
        {{ htmlDescription }}
      </p>
    </div>

    <!-- HTML Content -->
    <div class="html-content-container">
      <div 
        v-if="interpolatedHtmlContent" 
        v-html="interpolatedHtmlContent"
        class="custom-html-content"
        ref="htmlContentRef"
      ></div>
      
      <!-- Empty State -->
      <div v-else class="empty-html-state text-center py-8">
        <Icon name="material-symbols:code" class="w-12 h-12 text-gray-300 mx-auto mb-2" />
        <p class="text-gray-500 text-sm">No HTML content configured</p>
        <p class="text-gray-400 text-xs mt-1">Component ID: {{ childNode.nodeId || 'Not set' }}</p>
      </div>
    </div>

    <!-- HTML Actions (if defined in HTML) -->
    <div v-if="showActions" class="html-actions mt-4 flex justify-end space-x-2">
      <button
        v-for="action in availableActions"
        :key="action.id"
        @click="handleHtmlAction(action)"
        :class="getActionButtonClasses(action)"
        :disabled="action.disabled"
      >
        <Icon v-if="action.icon" :name="action.icon" class="w-4 h-4 mr-2" />
        {{ action.label }}
      </button>
    </div>

    <!-- Debug Info (if enabled) -->
    <div v-if="showDebugInfo && isDevelopment" class="html-debug mt-4 p-3 bg-gray-50 border border-gray-200 rounded text-xs text-gray-600">
      <div><strong>Variables Available:</strong> {{ Object.keys(processVariables).join(', ') || 'None' }}</div>
      <div><strong>HTML Length:</strong> {{ (childNode.htmlCode || '').length }} characters</div>
      <div><strong>CSS Length:</strong> {{ (childNode.cssCode || '').length }} characters</div>
      <div><strong>JS Length:</strong> {{ (childNode.jsCode || '').length }} characters</div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, watch, onMounted, onUnmounted, nextTick } from 'vue'
import { Icon } from '#components'

const props = defineProps({
  childNode: {
    type: Object,
    required: true
  },
  processVariables: {
    type: Object,
    default: () => ({})
  },
  showActions: {
    type: Boolean,
    default: true
  },
  showDebugInfo: {
    type: Boolean,
    default: false
  }
})

const emit = defineEmits(['html-action', 'variable-update'])

// Reactive data
const htmlContentRef = ref(null)
const availableActions = ref([])
const isDevelopment = process.env.NODE_ENV === 'development'

// Style and script elements for cleanup
let customStyleElement = null
let customScriptElement = null

// Computed properties
const htmlTitle = computed(() => {
  return props.childNode.title || props.childNode.htmlTitle || null
})

const htmlDescription = computed(() => {
  return props.childNode.description || props.childNode.htmlDescription || null
})

const rawHtmlContent = computed(() => {
  return props.childNode.htmlCode || props.childNode.htmlContent || ''
})

const interpolatedHtmlContent = computed(() => {
  let content = rawHtmlContent.value
  
  if (!content) return ''

  // Replace process variables in the HTML content
  // Format: {{variableName}} or ${variableName}
  content = content.replace(/\{\{(\w+)\}\}/g, (match, varName) => {
    const value = props.processVariables[varName]
    return value !== undefined ? String(value) : match
  })

  content = content.replace(/\$\{(\w+)\}/g, (match, varName) => {
    const value = props.processVariables[varName]
    return value !== undefined ? String(value) : match
  })

  return content
})

const customCSS = computed(() => {
  return props.childNode.cssCode || ''
})

const customJS = computed(() => {
  return props.childNode.jsCode || ''
})

// Methods
const injectCustomCSS = (cssCode) => {
  // Remove existing style element
  if (customStyleElement) {
    customStyleElement.remove()
    customStyleElement = null
  }

  // Inject new styles if provided
  if (cssCode && cssCode.trim()) {
    customStyleElement = document.createElement('style')
    customStyleElement.setAttribute('data-child-html-css', props.childNode.id)
    
    // Scope CSS to this component by prefixing with component class
    const scopedCSS = cssCode.replace(/([^}]+\{)/g, (match, selector) => {
      // Don't scope selectors that already contain the component class or are global
      if (selector.includes('.custom-html-content') || selector.trim().startsWith('@')) {
        return match
      }
      return `.custom-html-content ${selector}`
    })
    
    customStyleElement.textContent = scopedCSS
    document.head.appendChild(customStyleElement)
  }
}

const executeCustomJS = (jsCode) => {
  if (!jsCode || !jsCode.trim()) return

  try {
    // Create a safe execution context
    const context = {
      // Available variables
      processVariables: { ...props.processVariables },
      
      // Helper functions
      updateVariable: (variable, value) => {
        emit('variable-update', { variable, value })
      },
      
      triggerAction: (actionId, data = {}) => {
        emit('html-action', { type: 'custom', actionId, data })
      },
      
      showMessage: (message, type = 'info') => {
        emit('html-action', { type: 'message', message, messageType: type })
      },
      
      // DOM element reference
      element: htmlContentRef.value,
      
      // Utility functions
      console: {
        log: (...args) => console.log('[Child HTML JS]', ...args),
        warn: (...args) => console.warn('[Child HTML JS]', ...args),
        error: (...args) => console.error('[Child HTML JS]', ...args)
      }
    }

    // Execute the custom JavaScript with context
    const func = new Function('context', `
      const { processVariables, updateVariable, triggerAction, showMessage, element, console } = context;
      ${jsCode}
    `)
    
    func(context)
  } catch (error) {
    console.error('Error executing child HTML JavaScript:', error)
    emit('html-action', { 
      type: 'error', 
      error: error.message,
      source: 'custom-js'
    })
  }
}

const setupEventListeners = () => {
  if (!htmlContentRef.value) return

  // Set up click event listeners for buttons with data-action attributes
  const actionButtons = htmlContentRef.value.querySelectorAll('[data-action]')
  
  actionButtons.forEach(button => {
    button.addEventListener('click', (event) => {
      event.preventDefault()
      
      const action = {
        type: 'button-click',
        actionId: button.getAttribute('data-action'),
        value: button.getAttribute('data-value') || null,
        data: button.dataset || {}
      }
      
      handleHtmlAction(action)
    })
  })

  // Set up form submission listeners
  const forms = htmlContentRef.value.querySelectorAll('form[data-action]')
  
  forms.forEach(form => {
    form.addEventListener('submit', (event) => {
      event.preventDefault()
      
      const formData = new FormData(form)
      const data = {}
      
      for (let [key, value] of formData.entries()) {
        data[key] = value
      }
      
      const action = {
        type: 'form-submit',
        actionId: form.getAttribute('data-action'),
        data
      }
      
      handleHtmlAction(action)
    })
  })

  // Set up input change listeners for real-time variable updates
  const variableInputs = htmlContentRef.value.querySelectorAll('[data-variable]')
  
  variableInputs.forEach(input => {
    input.addEventListener('input', (event) => {
      const variable = input.getAttribute('data-variable')
      const value = event.target.value
      
      emit('variable-update', { variable, value })
    })
  })
}

const handleHtmlAction = (action) => {
  console.log('HTML action triggered:', action)
  emit('html-action', action)
}

const getActionButtonClasses = (action) => {
  const baseClasses = 'px-4 py-2 rounded-md text-sm font-medium focus:outline-none focus:ring-2 focus:ring-offset-2'
  
  switch (action.type || 'default') {
    case 'primary':
      return `${baseClasses} bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-500`
    case 'secondary':
      return `${baseClasses} bg-gray-200 text-gray-900 hover:bg-gray-300 focus:ring-gray-500`
    case 'danger':
      return `${baseClasses} bg-red-600 text-white hover:bg-red-700 focus:ring-red-500`
    case 'success':
      return `${baseClasses} bg-green-600 text-white hover:bg-green-700 focus:ring-green-500`
    default:
      return `${baseClasses} bg-gray-100 text-gray-700 hover:bg-gray-200 focus:ring-gray-500`
  }
}

// Watch for HTML content changes
watch(interpolatedHtmlContent, () => {
  nextTick(() => {
    setupEventListeners()
  })
})

// Watch for CSS changes
watch(customCSS, (newCSS) => {
  nextTick(() => {
    injectCustomCSS(newCSS)
  })
}, { immediate: true })

// Watch for JS changes
watch(customJS, (newJS) => {
  nextTick(() => {
    executeCustomJS(newJS)
  })
})

// Watch for process variable changes and re-execute JS
watch(() => props.processVariables, () => {
  if (customJS.value) {
    nextTick(() => {
      executeCustomJS(customJS.value)
    })
  }
}, { deep: true })

// Setup on mount
onMounted(() => {
  nextTick(() => {
    setupEventListeners()
    if (customJS.value) {
      executeCustomJS(customJS.value)
    }
  })
})

// Cleanup on unmount
onUnmounted(() => {
  if (customStyleElement) {
    customStyleElement.remove()
    customStyleElement = null
  }
  
  if (customScriptElement) {
    customScriptElement.remove()
    customScriptElement = null
  }
})
</script>

<style scoped>
.child-html-renderer {
  width: 100%;
  min-height: 200px;
}

.html-header {
  border-bottom: 1px solid #f3f4f6;
  padding-bottom: 0.75rem;
}

.html-content-container {
  width: 100%;
  position: relative;
}

.custom-html-content {
  width: 100%;
  line-height: 1.6;
}

.empty-html-state {
  min-height: 150px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.html-actions {
  border-top: 1px solid #f3f4f6;
  padding-top: 1rem;
}

.html-debug {
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
}

/* Global styles for HTML content */
:deep(.custom-html-content) {
  /* Typography */
  h1, h2, h3, h4, h5, h6 {
    margin-top: 1.5em;
    margin-bottom: 0.5em;
    font-weight: 600;
    line-height: 1.25;
  }
  
  h1 { font-size: 2em; }
  h2 { font-size: 1.5em; }
  h3 { font-size: 1.25em; }
  h4 { font-size: 1.125em; }
  
  p {
    margin-bottom: 1em;
  }
  
  /* Lists */
  ul, ol {
    margin-bottom: 1em;
    padding-left: 1.5em;
  }
  
  /* Links */
  a {
    color: #3b82f6;
    text-decoration: underline;
  }
  
  a:hover {
    color: #1d4ed8;
  }
  
  /* Forms */
  input, textarea, select {
    width: 100%;
    padding: 0.5rem;
    border: 1px solid #d1d5db;
    border-radius: 0.375rem;
    font-size: 0.875rem;
  }
  
  input:focus, textarea:focus, select:focus {
    outline: none;
    ring: 2px;
    ring-color: #3b82f6;
    border-color: #3b82f6;
  }
  
  button {
    padding: 0.5rem 1rem;
    background-color: #3b82f6;
    color: white;
    border: none;
    border-radius: 0.375rem;
    cursor: pointer;
    font-size: 0.875rem;
  }
  
  button:hover {
    background-color: #1d4ed8;
  }
  
  button:disabled {
    opacity: 0.5;
    cursor: not-allowed;
  }
  
  /* Tables */
  table {
    width: 100%;
    border-collapse: collapse;
    margin-bottom: 1em;
  }
  
  th, td {
    padding: 0.5rem;
    text-align: left;
    border-bottom: 1px solid #e5e7eb;
  }
  
  th {
    font-weight: 600;
    background-color: #f9fafb;
  }
  
  /* Images */
  img {
    max-width: 100%;
    height: auto;
  }
  
  /* Code */
  code {
    background-color: #f3f4f6;
    padding: 0.125rem 0.25rem;
    border-radius: 0.25rem;
    font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
    font-size: 0.875em;
  }
  
  pre {
    background-color: #f3f4f6;
    padding: 1rem;
    border-radius: 0.5rem;
    overflow-x: auto;
    margin-bottom: 1em;
  }
  
  pre code {
    background: none;
    padding: 0;
  }
}
</style>