<template>
  <div class="script-node-config">
    <div class="config-content">
      <!-- Header -->
      <div class="config-header">
        <h3 class="text-lg font-semibold text-gray-800">Script Task Configuration</h3>
        <p class="text-sm text-gray-600">Configure JavaScript code to transform data and variables</p>
      </div>

      <!-- Basic Info Section -->
      <div class="config-section">
        <h4 class="section-title">Basic Information</h4>
        <div class="section-content">
          <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
            <FormKit
              type="text"
              label="Script Name"
              name="label"
              v-model="localNodeData.label"
              help="Display name for this script task"
              :classes="{ outer: 'field-wrapper' }"
              placeholder="e.g., Process API Response, Transform Data"
              validation="required"
            />
            
            <FormKit
              type="textarea"
              label="Description"
              name="description"
              v-model="localNodeData.description"
              help="Describe what this script does"
              :classes="{ outer: 'field-wrapper' }"
              placeholder="e.g., Transforms API response data into process variables"
              rows="2"
            />
          </div>
        </div>
      </div>

      <!-- Script Code Section -->
      <div class="config-section">
        <h4 class="section-title">Script Code</h4>
        <div class="section-content">
          <div class="mb-4">
            <label class="block text-sm font-medium text-gray-700 mb-2">
              JavaScript Code
            </label>
            <div class="script-editor-container">
              <RsCodeMirror
                v-model="localNodeData.scriptCode"
                :options="{
                  mode: 'javascript',
                  theme: 'default',
                  lineNumbers: true,
                  lineWrapping: true,
                  autoCloseBrackets: true,
                  matchBrackets: true,
                  indentUnit: 2,
                  tabSize: 2
                }"
                class="script-editor"
                placeholder="// Available objects:
// - processVariables: object containing all process variables
// - console: for debugging (console.log)
// 
// Example - Transform API response:
// const apiData = processVariables.apiResponse;
// processVariables.applicantStatus = apiData.data.status;
// processVariables.approvalRequired = apiData.data.score < 70;
//
// Example - Extract specific fields:
// processVariables.firstName = processVariables.text3?.split(' ')[0];
// processVariables.documentCount = processVariables.apiResponse?.data?.documents?.length || 0;"
              />
            </div>
            <p class="text-xs text-gray-500 mt-2">
              💡 Use <code>processVariables</code> to access and modify process data. 
              Available variables: {{ availableVariableNames.join(', ') || 'None' }}
            </p>
          </div>

          <!-- Error Handling -->
          <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
            <FormKit
              type="checkbox"
              label="Continue on Error"
              name="continueOnError"
              v-model="localNodeData.continueOnError"
              help="If enabled, process continues even if script fails"
              :classes="{ outer: 'field-wrapper' }"
            />
            
            <FormKit
              v-if="!localNodeData.continueOnError"
              type="text"
              label="Error Variable"
              name="errorVariable"
              v-model="localNodeData.errorVariable"
              help="Variable to store error information"
              :classes="{ outer: 'field-wrapper' }"
              placeholder="e.g., scriptError"
            />
          </div>
        </div>
      </div>

      <!-- Variables Section -->
      <div class="config-section">
        <h4 class="section-title">Variable Management</h4>
        <div class="section-content">
          <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
            <!-- Input Variables -->
            <div>
              <label class="block text-sm font-medium text-gray-700 mb-2">
                Input Variables
              </label>
              <div class="variable-list">
                <div 
                  v-for="variable in availableVariables" 
                  :key="variable.name"
                  class="variable-item"
                  :class="{ 'selected': isInputVariable(variable.name) }"
                  @click="toggleInputVariable(variable.name)"
                >
                  <div class="variable-info">
                    <span class="variable-name">{{ variable.name }}</span>
                    <span class="variable-type">{{ variable.type }}</span>
                  </div>
                  <span class="variable-description">{{ variable.description }}</span>
                </div>
              </div>
              <p class="text-xs text-gray-500 mt-2">
                Click to select variables this script will read from
              </p>
            </div>

            <!-- Output Variables -->
            <div>
              <label class="block text-sm font-medium text-gray-700 mb-2">
                Output Variables
              </label>
              <div class="space-y-2">
                <div
                  v-for="(output, index) in localNodeData.outputVariables"
                  :key="index"
                  class="flex items-center space-x-2"
                >
                  <FormKit
                    type="text"
                    v-model="output.name"
                    placeholder="Variable name"
                    :classes="{ outer: 'flex-1' }"
                  />
                  <FormKit
                    type="select"
                    v-model="output.type"
                    :options="[
                      { label: 'String', value: 'string' },
                      { label: 'Number', value: 'number' },
                      { label: 'Boolean', value: 'boolean' },
                      { label: 'Object', value: 'object' },
                      { label: 'Array', value: 'array' }
                    ]"
                    :classes="{ outer: 'flex-1' }"
                  />
                  <button
                    @click="removeOutputVariable(index)"
                    class="p-2 text-red-600 hover:bg-red-50 rounded"
                  >
                    <Icon name="material-symbols:delete-outline" class="w-4 h-4" />
                  </button>
                </div>
                
                <button
                  @click="addOutputVariable"
                  class="flex items-center space-x-2 px-3 py-2 text-blue-600 hover:bg-blue-50 rounded border border-dashed border-blue-300"
                >
                  <Icon name="material-symbols:add" class="w-4 h-4" />
                  <span class="text-sm">Add Output Variable</span>
                </button>
              </div>
              <p class="text-xs text-gray-500 mt-2">
                Define variables this script will create or modify
              </p>
            </div>
          </div>
        </div>
      </div>

      <!-- Script Testing Section -->
      <div class="config-section">
        <h4 class="section-title">Script Testing</h4>
        <div class="section-content">
          <div class="test-container p-4 bg-gray-50 rounded-lg">
            <div class="flex items-center justify-between mb-3">
              <h5 class="font-medium text-gray-700">Test Script Execution</h5>
              <button
                @click="testScript"
                :disabled="!localNodeData.scriptCode.trim()"
                class="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 disabled:bg-gray-400 disabled:cursor-not-allowed"
              >
                Test Script
              </button>
            </div>
            
            <div v-if="testResult" class="test-result">
              <div class="flex items-center space-x-2 mb-2">
                <Icon 
                  :name="testResult.success ? 'material-symbols:check-circle' : 'material-symbols:error'" 
                  :class="testResult.success ? 'text-green-600' : 'text-red-600'"
                  class="w-5 h-5"
                />
                <span :class="testResult.success ? 'text-green-700' : 'text-red-700'" class="font-medium">
                  {{ testResult.success ? 'Script executed successfully' : 'Script execution failed' }}
                </span>
              </div>
              
              <div v-if="testResult.error" class="error-details p-3 bg-red-50 border border-red-200 rounded text-sm text-red-700">
                {{ testResult.error }}
              </div>
              
              <div v-if="testResult.result" class="result-details">
                <h6 class="font-medium text-gray-700 mb-2">Modified Variables:</h6>
                <pre class="text-xs bg-white p-3 border border-gray-200 rounded overflow-auto max-h-32">{{ JSON.stringify(testResult.result, null, 2) }}</pre>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, watch, nextTick } from 'vue'

// Props and emits
const props = defineProps({
  nodeData: {
    type: Object,
    default: () => ({})
  },
  availableVariables: {
    type: Array,
    default: () => []
  }
})

const emit = defineEmits(['update'])

// Local state
const localNodeData = ref({
  label: '',
  description: '',
  scriptCode: '// Transform API response or process variables\n// Example:\n// processVariables.newVariable = processVariables.apiResponse.data.field;\n',
  scriptLanguage: 'javascript',
  inputVariables: [],
  outputVariables: [],
  continueOnError: false,
  errorVariable: 'scriptError'
})

const testResult = ref(null)

// Computed properties
const availableVariableNames = computed(() => {
  return props.availableVariables.map(v => v.name)
})

// Methods
const isInputVariable = (variableName) => {
  return localNodeData.value.inputVariables.includes(variableName)
}

const toggleInputVariable = (variableName) => {
  const index = localNodeData.value.inputVariables.indexOf(variableName)
  if (index > -1) {
    localNodeData.value.inputVariables.splice(index, 1)
  } else {
    localNodeData.value.inputVariables.push(variableName)
  }
  emitUpdate()
}

const addOutputVariable = () => {
  localNodeData.value.outputVariables.push({
    name: '',
    type: 'string',
    description: ''
  })
  emitUpdate()
}

const removeOutputVariable = (index) => {
  localNodeData.value.outputVariables.splice(index, 1)
  emitUpdate()
}

const testScript = () => {
  try {
    // Create a test environment with mock process variables
    const mockProcessVariables = {}
    
    // Add mock values for available variables
    props.availableVariables.forEach(variable => {
      mockProcessVariables[variable.name] = variable.value || getMockValueForType(variable.type)
    })
    
    // Create a safe execution context
    const scriptFunction = new Function('processVariables', 'console', localNodeData.value.scriptCode)
    
    // Mock console for testing
    const mockConsole = {
      log: (...args) => console.log('[Script Test]', ...args),
      error: (...args) => console.error('[Script Test]', ...args),
      warn: (...args) => console.warn('[Script Test]', ...args)
    }
    
    // Execute the script
    scriptFunction(mockProcessVariables, mockConsole)
    
    testResult.value = {
      success: true,
      result: mockProcessVariables,
      error: null
    }
  } catch (error) {
    testResult.value = {
      success: false,
      result: null,
      error: error.message
    }
  }
}

const getMockValueForType = (type) => {
  switch (type) {
    case 'string': return 'mock_value'
    case 'number': return 42
    case 'boolean': return true
    case 'object': return { data: { field: 'value' } }
    case 'array': return ['item1', 'item2']
    default: return 'mock_value'
  }
}

const emitUpdate = () => {
  emit('update', localNodeData.value)
}

// Add a flag to prevent recursive updates
const isUpdatingFromProps = ref(false)

// Watch for prop changes
watch(
  () => props.nodeData,
  (newData) => {
    if (newData && Object.keys(newData).length > 0) {
      isUpdatingFromProps.value = true
      localNodeData.value = {
        label: newData.label || 'Script Task',
        description: newData.description || '',
        scriptCode: newData.scriptCode || '// Transform API response or process variables\n// Example:\n// processVariables.newVariable = processVariables.apiResponse.data.field;\n',
        scriptLanguage: newData.scriptLanguage || 'javascript',
        inputVariables: newData.inputVariables || [],
        outputVariables: newData.outputVariables || [],
        continueOnError: newData.continueOnError || false,
        errorVariable: newData.errorVariable || 'scriptError'
      }
      // Reset the flag after the update
      nextTick(() => {
        isUpdatingFromProps.value = false
      })
    }
  },
  { immediate: true, deep: true }
)

// Watch for changes in localNodeData and emit updates
watch(
  localNodeData,
  () => {
    // Only emit if we're not currently updating from props
    if (!isUpdatingFromProps.value) {
      emitUpdate()
    }
  },
  { deep: true }
)

// Reset test result when script changes
watch(
  () => localNodeData.value.scriptCode,
  () => {
    testResult.value = null
  }
)
</script>

<style scoped>
.script-node-config {
  @apply max-w-6xl mx-auto bg-white;
}

.config-content {
  @apply p-6 space-y-8;
}

.config-header {
  @apply border-b border-gray-200 pb-4;
}

.config-section {
  @apply space-y-4;
}

.section-title {
  @apply text-base font-semibold text-gray-800 mb-3;
}

.section-content {
  @apply space-y-4;
}

.script-editor-container {
  @apply border border-gray-300 rounded-lg overflow-hidden;
}

.variable-list {
  @apply space-y-1 max-h-48 overflow-y-auto border border-gray-200 rounded-lg p-2;
}

.variable-item {
  @apply p-2 rounded cursor-pointer hover:bg-gray-50 border border-transparent;
}

.variable-item.selected {
  @apply bg-blue-50 border-blue-200;
}

.variable-info {
  @apply flex items-center justify-between;
}

.variable-name {
  @apply font-medium text-gray-800;
}

.variable-type {
  @apply text-xs text-gray-500 bg-gray-100 px-2 py-1 rounded;
}

.variable-description {
  @apply text-xs text-gray-600 mt-1;
}

.test-container {
  @apply border border-gray-200;
}

.field-wrapper {
  @apply mb-0;
}
</style> 