<template>
  <div ref="editorContainer" class="monaco-editor-container" :style="{ height: height }"></div>
</template>

<script>
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
import * as monaco from 'monaco-editor'
// Vite-friendly worker imports
import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
import JsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
import CssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker'
import HtmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'
import TsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'

// Register Twig language and completion once per app lifetime
let twigEnhancementsRegistered = false

function registerTwigLanguageAndCompletions() {
  if (twigEnhancementsRegistered) return
  try {
    // Register Twig language
    monaco.languages.register({ id: 'twig', extensions: ['.twig'], aliases: ['Twig', 'twig'] })

    // Basic Twig tokenizer
    monaco.languages.setMonarchTokensProvider('twig', {
      tokenPostfix: '.twig',
      defaultToken: '',
      brackets: [
        { open: '{{', close: '}}', token: 'delimiter.curly' },
        { open: '{%', close: '%}', token: 'delimiter.curly' },
        { open: '{#', close: '#}', token: 'comment' }
      ],
      keywords: [
        'if', 'elseif', 'else', 'endif',
        'for', 'endfor', 'in',
        'set', 'include', 'extends', 'with', 'only',
        'block', 'endblock', 'macro', 'import', 'from', 'filter', 'endfilter'
      ],
      filters: [
        'upper', 'lower', 'capitalize', 'title', 'trim', 'replace', 'default', 'length', 'escape', 'raw', 'number_format'
      ],
      tokenizer: {
        root: [
          [/\{#/, 'comment', '@comment'],
          [/\{\{/, 'delimiter.twig', '@variable'],
          [/\{%/, 'delimiter.twig', '@block'],
          [/[^\{]+/, ''],
          [/./, '']
        ],
        comment: [
          [/[^#}]+/, 'comment.content'],
          [/#\}/, 'comment', '@pop']
        ],
        variable: [
          [/\}\}/, 'delimiter.twig', '@pop'],
          [/\|\s*[a-zA-Z_][\w]*/, 'keyword'],
          [/\b([a-zA-Z_][\w]*)\b/, 'variable'],
          [/[^}]+/, '']
        ],
        block: [
          [/%\}/, 'delimiter.twig', '@pop'],
          [/\b(if|elseif|else|endif|for|endfor|in|set|include|extends|with|only|block|endblock|macro|import|from|filter|endfilter)\b/, 'keyword'],
          [/\b([a-zA-Z_][\w]*)\b/, 'identifier'],
          [/[^%]+/, '']
        ]
      }
    })

    // Twig variables for invoice templates (autocomplete)
    const twigVariables = [
      { label: 'company_name', detail: 'نام شرکت' },
      { label: 'invoice_number', detail: 'شماره فاکتور' },
      { label: 'invoice_date', detail: 'تاریخ فاکتور' },
      { label: 'customer_name', detail: 'نام مشتری' },
      { label: 'total_amount', detail: 'مبلغ کل' },
      { label: 'items_list', detail: 'لیست اقلام' }
    ]

    const twigKeywords = [
      { label: 'if', detail: 'ساختار شرطی' },
      { label: 'elseif', detail: 'شرط جایگزین' },
      { label: 'else', detail: 'بخش جایگزین' },
      { label: 'endif', detail: 'پایان if' },
      { label: 'for', detail: 'حلقه' },
      { label: 'endfor', detail: 'پایان for' },
      { label: 'in', detail: 'اپراتور in' },
      { label: 'set', detail: 'تعریف متغیر' },
      { label: 'include', detail: 'درج قالب' },
      { label: 'extends', detail: 'ارث‌بری قالب' },
      { label: 'block', detail: 'بلوک قالب' },
      { label: 'endblock', detail: 'پایان بلوک' },
      { label: 'filter', detail: 'اعمال فیلتر' },
      { label: 'endfilter', detail: 'پایان فیلتر' }
    ]

    const twigSnippets = [
      {
        label: 'if ... endif',
        detail: 'الگوی if',
        insertText: '{% if ${1:condition} %}\n  ${2:...}\n{% endif %}',
      },
      {
        label: 'for ... endfor',
        detail: 'الگوی for',
        insertText: '{% for ${1:item} in ${2:items} %}\n  ${3:...}\n{% endfor %}'
      }
    ]

    const mapToMonacoItems = (items, kind) => items.map((it) => ({
      label: it.label,
      kind,
      insertText: it.insertText || it.label,
      insertTextRules: it.insertText ? monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet : undefined,
      detail: it.detail
    }))

    // Utility: determine if cursor is inside a Twig pair on the current line
    function isInsideTwigContext(model, position) {
      const lineText = model.getLineContent(position.lineNumber)
      const textUntilPos = lineText.substring(0, position.column - 1)
      const openVar = textUntilPos.lastIndexOf('{{')
      const closeVar = textUntilPos.lastIndexOf('}}')
      const openBlock = textUntilPos.lastIndexOf('{%')
      const closeBlock = textUntilPos.lastIndexOf('%}')
      const inVar = openVar > -1 && openVar > closeVar
      const inBlock = openBlock > -1 && openBlock > closeBlock
      return inVar || inBlock
    }

    // Completion provider for Twig language
    monaco.languages.registerCompletionItemProvider('twig', {
      triggerCharacters: ['{', '%', ' ', '.', '_', '|'],
      provideCompletionItems(model, position) {
        const suggestions = [
          ...mapToMonacoItems(twigVariables, monaco.languages.CompletionItemKind.Variable),
          ...mapToMonacoItems(twigKeywords, monaco.languages.CompletionItemKind.Keyword),
          ...mapToMonacoItems(twigSnippets, monaco.languages.CompletionItemKind.Snippet)
        ]
        return { suggestions }
      }
    })

    // Also provide Twig suggestions while editing HTML (mixed content)
    monaco.languages.registerCompletionItemProvider('html', {
      triggerCharacters: ['{', '%', ' ', '.', '_', '|'],
      provideCompletionItems(model, position) {
        if (!isInsideTwigContext(model, position)) return { suggestions: [] }
        const suggestions = [
          ...mapToMonacoItems(twigVariables, monaco.languages.CompletionItemKind.Variable),
          ...mapToMonacoItems(twigKeywords, monaco.languages.CompletionItemKind.Keyword),
          ...mapToMonacoItems(twigSnippets, monaco.languages.CompletionItemKind.Snippet)
        ]
        return { suggestions }
      }
    })

    twigEnhancementsRegistered = true
  } catch (err) {
    console.warn('Failed to register Twig language/completions:', err)
  }
}

// تنظیمات MonacoEnvironment برای web workers (سازگار با Vite)
if (typeof self !== 'undefined') {
  self.MonacoEnvironment = {
    getWorker: function (moduleId, label) {
      try {
        if (label === 'json') return new JsonWorker()
        if (label === 'css' || label === 'scss' || label === 'less') return new CssWorker()
        if (label === 'html' || label === 'handlebars' || label === 'razor') return new HtmlWorker()
        if (label === 'typescript' || label === 'javascript') return new TsWorker()
        return new EditorWorker()
      } catch (error) {
        console.warn('Monaco Editor worker failed to start, falling back to main thread:', error)
        return undefined
      }
    }
  }
}

export default {
  name: 'MonacoEditor',
  props: {
    modelValue: {
      type: String,
      default: ''
    },
    language: {
      type: String,
      default: 'html'
    },
    theme: {
      type: String,
      default: 'vs-dark'
    },
    height: {
      type: String,
      default: '400px'
    },
    readOnly: {
      type: Boolean,
      default: false
    },
    options: {
      type: Object,
      default: () => ({})
    }
  },
  emits: ['update:modelValue', 'change'],
  setup(props, { emit }) {
    const editorContainer = ref(null)
    let editor = null

    const createEditor = () => {
      if (!editorContainer.value) return

      try {
        // Ensure Twig language and completions are available
        registerTwigLanguageAndCompletions()

        // تنظیمات پیش‌فرض
        const defaultOptions = {
          value: props.modelValue,
          language: props.language,
          theme: props.theme,
          readOnly: props.readOnly,
          automaticLayout: true,
          minimap: {
            enabled: false
          },
          scrollBeyondLastLine: false,
          fontSize: 14,
          fontFamily: 'Consolas, "Courier New", monospace',
          lineNumbers: 'on',
          roundedSelection: false,
          scrollbar: {
            vertical: 'visible',
            horizontal: 'visible'
          },
          folding: true,
          wordWrap: 'on',
          suggestOnTriggerCharacters: true,
          acceptSuggestionOnEnter: 'on',
          tabCompletion: 'on',
          wordBasedSuggestions: 'on',
          parameterHints: {
            enabled: true
          },
          autoIndent: 'full',
          formatOnPaste: true,
          formatOnType: false,
          quickSuggestions: true,
          hover: {
            enabled: true
          }
        }

        // ترکیب تنظیمات پیش‌فرض با تنظیمات سفارشی
        const editorOptions = { ...defaultOptions, ...props.options }

        editor = monaco.editor.create(editorContainer.value, editorOptions)

        // اضافه کردن event listener برای تغییرات
        editor.onDidChangeModelContent(() => {
          const value = editor.getValue()
          emit('update:modelValue', value)
          emit('change', value)
        })

        // تنظیم زبان فارسی برای RTL
        if (props.language === 'html') {
          monaco.editor.setModelLanguage(editor.getModel(), 'html')
        }
      } catch (error) {
        console.error('Error creating Monaco Editor:', error)
        // Fallback to a simple textarea if Monaco fails
        const textarea = document.createElement('textarea')
        textarea.value = props.modelValue
        textarea.style.width = '100%'
        textarea.style.height = '100%'
        textarea.style.fontFamily = 'Consolas, "Courier New", monospace'
        textarea.style.fontSize = '14px'
        textarea.style.border = 'none'
        textarea.style.outline = 'none'
        textarea.style.resize = 'none'
        
        textarea.addEventListener('input', (e) => {
          emit('update:modelValue', e.target.value)
          emit('change', e.target.value)
        })
        
        editorContainer.value.appendChild(textarea)
      }
    }

    const destroyEditor = () => {
      if (editor) {
        try {
          editor.dispose()
        } catch (error) {
          console.warn('Error disposing Monaco Editor:', error)
        }
        editor = null
      }
      
      // Clean up fallback textarea if it exists
      if (editorContainer.value) {
        const textarea = editorContainer.value.querySelector('textarea')
        if (textarea) {
          textarea.remove()
        }
      }
    }

    // تماشای تغییرات props
    watch(() => props.modelValue, (newValue) => {
      if (editor && newValue !== editor.getValue()) {
        editor.setValue(newValue)
      }
    })

    watch(() => props.language, (newLanguage) => {
      // Ensure Twig language is registered if needed when language changes
      registerTwigLanguageAndCompletions()
      if (editor) {
        monaco.editor.setModelLanguage(editor.getModel(), newLanguage)
      }
    })

    watch(() => props.theme, (newTheme) => {
      if (editor) {
        monaco.editor.setTheme(newTheme)
      }
    })

    watch(() => props.readOnly, (newReadOnly) => {
      if (editor) {
        editor.updateOptions({ readOnly: newReadOnly })
      }
    })

    onMounted(() => {
      createEditor()
    })

    onBeforeUnmount(() => {
      destroyEditor()
    })

    // متدهای عمومی برای دسترسی از خارج
    const getValue = () => {
      if (editor) {
        return editor.getValue()
      }
      // Fallback for textarea
      if (editorContainer.value) {
        const textarea = editorContainer.value.querySelector('textarea')
        return textarea ? textarea.value : ''
      }
      return ''
    }

    const setValue = (value) => {
      if (editor) {
        editor.setValue(value)
      } else if (editorContainer.value) {
        // Fallback for textarea
        const textarea = editorContainer.value.querySelector('textarea')
        if (textarea) {
          textarea.value = value
        }
      }
    }

    const focus = () => {
      if (editor) {
        editor.focus()
      }
    }

    const getEditor = () => {
      return editor
    }

    return {
      editorContainer,
      getValue,
      setValue,
      focus,
      getEditor
    }
  }
}
</script>

<style scoped>
.monaco-editor-container {
  width: 100%;
  border: 1px solid #e0e0e0;
  border-radius: 4px;
  overflow: hidden;
}

/* تنظیمات برای RTL */
.monaco-editor-container :deep(.monaco-editor) {
  direction: ltr;
}

.monaco-editor-container :deep(.monaco-editor .margin) {
  direction: ltr;
}

.monaco-editor-container :deep(.monaco-editor .monaco-editor-background) {
  direction: ltr;
}

/* تنظیمات برای تم تاریک */
.monaco-editor-container :deep(.vs-dark) {
  background-color: #1e1e1e;
}

/* تنظیمات برای تم روشن */
.monaco-editor-container :deep(.vs) {
  background-color: #ffffff;
}

/* تنظیمات برای تم HC */
.monaco-editor-container :deep(.hc-black) {
  background-color: #000000;
}
</style> 