import type { Monaco } from '@monaco-editor/react';

export function getMonacoLanguage(language?: string): string {
  if (!language) return 'python';
  const norm = language.toLowerCase().trim();
  const map: Record<string, string> = {
    'c++': 'cpp',
    'cpp': 'cpp',
    'cxx': 'cpp',
    'c#': 'csharp',
    'cs': 'csharp',
    'csharp': 'csharp',
    'js': 'javascript',
    'javascript': 'javascript',
    'ts': 'typescript',
    'typescript': 'typescript',
    'py': 'python',
    'python': 'python',
    'rs': 'rust',
    'rust': 'rust',
    'golang': 'go',
    'go': 'go',
    'html': 'html',
    'java': 'java',
    'lua': 'lua',
  };
  return map[norm] || norm;
}

export function getLanguageFileName(language?: string): string {
  const lang = getMonacoLanguage(language);
  const extMap: Record<string, string> = {
    python: 'main.py',
    csharp: 'Program.cs',
    cpp: 'main.cpp',
    java: 'Main.java',
    javascript: 'main.js',
    typescript: 'main.ts',
    rust: 'main.rs',
    lua: 'main.lua',
    html: 'index.html',
    go: 'main.go',
  };
  return extMap[lang] || 'main.txt';
}

function extractDocumentSymbols(code: string): string[] {
  const words = code.match(/[a-zA-Z_][a-zA-Z0-9_]*/g) || [];
  const unique = new Set<string>();
  const reserved = new Set([
    'if', 'else', 'for', 'while', 'return', 'import', 'from', 'def', 'class',
    'public', 'private', 'protected', 'static', 'void', 'int', 'double', 'float',
    'bool', 'boolean', 'char', 'const', 'let', 'var', 'func', 'package', 'struct',
  ]);
  for (const w of words) {
    if (w.length > 2 && !reserved.has(w)) {
      unique.add(w);
    }
  }
  return Array.from(unique);
}

let registered = false;

export function registerMonacoCompletions(monaco: Monaco) {
  if (registered) return;
  registered = true;

  // ── JAVA COMPLETER ──────────────────────────────────────────
  monaco.languages.registerCompletionItemProvider('java', {
    triggerCharacters: ['.'],
    provideCompletionItems: (model, position) => {
      const lineUntilPosition = model.getValueInRange({
        startLineNumber: position.lineNumber,
        startColumn: 1,
        endLineNumber: position.lineNumber,
        endColumn: position.column,
      });

      const word = model.getWordUntilPosition(position);
      const range = {
        startLineNumber: position.lineNumber,
        endLineNumber: position.lineNumber,
        startColumn: word.startColumn,
        endColumn: word.endColumn,
      };

      const code = model.getValue();
      const dotMatch = lineUntilPosition.match(/([a-zA-Z_][a-zA-Z0-9_]*)\.\s*$/);

      if (dotMatch) {
        const objName = dotMatch[1];
        const lowerName = objName.toLowerCase();
        let targetType = 'unknown';

        if (new RegExp(`Map<|HashMap<|TreeMap<`, 'i').test(code) && (lowerName.includes('map') || lowerName.includes('dict'))) {
          targetType = 'map';
        } else if (new RegExp(`List<|ArrayList<|LinkedList<`, 'i').test(code) && (lowerName.includes('list') || lowerName.includes('arr') || lowerName.includes('items'))) {
          targetType = 'list';
        } else if (new RegExp(`Set<|HashSet<`, 'i').test(code) && lowerName.includes('set')) {
          targetType = 'set';
        } else if (lowerName === 'out' || objName === 'System') {
          targetType = 'system';
        } else if (lowerName.includes('str') || lowerName.includes('text') || lowerName.includes('name') || lowerName.includes('msg')) {
          targetType = 'string';
        } else {
          if (lowerName.includes('map') || lowerName.includes('dict')) targetType = 'map';
          else if (lowerName.includes('list') || lowerName.includes('arr')) targetType = 'list';
          else if (lowerName.includes('set')) targetType = 'set';
          else targetType = 'general';
        }

        const mapMethods = [
          { label: 'put', insertText: 'put(${1:key}, ${2:value})', doc: 'Associates specified value with key in map.' },
          { label: 'get', insertText: 'get(${1:key})', doc: 'Returns value mapped to specified key.' },
          { label: 'containsKey', insertText: 'containsKey(${1:key})', doc: 'Returns true if map contains key.' },
          { label: 'containsValue', insertText: 'containsValue(${1:value})', doc: 'Returns true if map contains value.' },
          { label: 'size', insertText: 'size()', doc: 'Returns number of key-value mappings.' },
          { label: 'isEmpty', insertText: 'isEmpty()', doc: 'Returns true if map contains no mappings.' },
          { label: 'keySet', insertText: 'keySet()', doc: 'Returns Set view of keys in map.' },
          { label: 'values', insertText: 'values()', doc: 'Returns Collection view of values in map.' },
          { label: 'entrySet', insertText: 'entrySet()', doc: 'Returns Set view of mappings in map.' },
          { label: 'remove', insertText: 'remove(${1:key})', doc: 'Removes mapping for key.' },
          { label: 'clear', insertText: 'clear()', doc: 'Removes all mappings from map.' },
          { label: 'getOrDefault', insertText: 'getOrDefault(${1:key}, ${2:defaultValue})', doc: 'Returns mapped value or default.' },
        ];

        const listMethods = [
          { label: 'add', insertText: 'add(${1:element})', doc: 'Appends element to end of list.' },
          { label: 'get', insertText: 'get(${1:index})', doc: 'Returns element at index.' },
          { label: 'size', insertText: 'size()', doc: 'Returns number of elements.' },
          { label: 'remove', insertText: 'remove(${1:index})', doc: 'Removes element at index.' },
          { label: 'contains', insertText: 'contains(${1:element})', doc: 'Returns true if list contains element.' },
          { label: 'indexOf', insertText: 'indexOf(${1:element})', doc: 'Returns index of element.' },
          { label: 'isEmpty', insertText: 'isEmpty()', doc: 'Returns true if list contains no elements.' },
          { label: 'clear', insertText: 'clear()', doc: 'Removes all elements.' },
        ];

        const stringMethods = [
          { label: 'length', insertText: 'length()', doc: 'Returns length of string.' },
          { label: 'substring', insertText: 'substring(${1:beginIndex})', doc: 'Returns substring starting at beginIndex.' },
          { label: 'charAt', insertText: 'charAt(${1:index})', doc: 'Returns char value at index.' },
          { label: 'toLowerCase', insertText: 'toLowerCase()', doc: 'Converts to lowercase.' },
          { label: 'toUpperCase', insertText: 'toUpperCase()', doc: 'Converts to uppercase.' },
          { label: 'trim', insertText: 'trim()', doc: 'Removes leading/trailing whitespace.' },
          { label: 'split', insertText: 'split("${1:regex}")', doc: 'Splits string around matches.' },
          { label: 'contains', insertText: 'contains("${1:str}")', doc: 'Returns true if contains string.' },
          { label: 'startsWith', insertText: 'startsWith("${1:prefix}")', doc: 'Checks if starts with prefix.' },
          { label: 'equals', insertText: 'equals(${1:anObject})', doc: 'Compares to specified object.' },
        ];

        const systemMethods = [
          { label: 'println', insertText: 'println(${1:value});', doc: 'Prints value and terminates line.' },
          { label: 'printf', insertText: 'printf("${1:%s}\\n", ${2:args});', doc: 'Prints formatted string.' },
          { label: 'print', insertText: 'print(${1:value});', doc: 'Prints value.' },
        ];

        let selected = mapMethods;
        if (targetType === 'list') selected = listMethods;
        else if (targetType === 'string') selected = stringMethods;
        else if (targetType === 'system') selected = systemMethods;
        else if (targetType === 'general') selected = [...mapMethods, ...listMethods, ...stringMethods];

        return {
          suggestions: selected.map(m => ({
            label: m.label,
            kind: monaco.languages.CompletionItemKind.Method,
            insertText: m.insertText,
            insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
            documentation: m.doc,
            range,
          })),
        };
      }

      const symbols = extractDocumentSymbols(code);
      const suggestions = [
        { label: 'System.out.println', kind: monaco.languages.CompletionItemKind.Snippet, insertText: 'System.out.println(${1:value});', range },
        { label: 'HashMap', kind: monaco.languages.CompletionItemKind.Class, insertText: 'Map<${1:String}, ${2:Integer}> ${3:map} = new HashMap<>();', range },
        { label: 'ArrayList', kind: monaco.languages.CompletionItemKind.Class, insertText: 'List<${1:String}> ${2:list} = new ArrayList<>();', range },
        ...symbols.map(s => ({ label: s, kind: monaco.languages.CompletionItemKind.Variable, insertText: s, range })),
      ];

      return { suggestions };
    },
  });

  // ── PYTHON COMPLETER ────────────────────────────────────────
  monaco.languages.registerCompletionItemProvider('python', {
    triggerCharacters: ['.'],
    provideCompletionItems: (model, position) => {
      const lineUntilPosition = model.getValueInRange({
        startLineNumber: position.lineNumber,
        startColumn: 1,
        endLineNumber: position.lineNumber,
        endColumn: position.column,
      });

      const word = model.getWordUntilPosition(position);
      const range = {
        startLineNumber: position.lineNumber,
        endLineNumber: position.lineNumber,
        startColumn: word.startColumn,
        endColumn: word.endColumn,
      };

      const code = model.getValue();
      const dotMatch = lineUntilPosition.match(/([a-zA-Z_][a-zA-Z0-9_]*)\.\s*$/);

      if (dotMatch) {
        const objName = dotMatch[1].toLowerCase();
        let methods = [
          { label: 'get', insertText: 'get(${1:key})', doc: 'Returns value for key.' },
          { label: 'keys', insertText: 'keys()', doc: 'Returns dictionary keys.' },
          { label: 'values', insertText: 'values()', doc: 'Returns dictionary values.' },
          { label: 'items', insertText: 'items()', doc: 'Returns key-value pairs.' },
          { label: 'append', insertText: 'append(${1:item})', doc: 'Appends item to list.' },
          { label: 'pop', insertText: 'pop(${1:index})', doc: 'Removes and returns item.' },
          { label: 'split', insertText: 'split("${1:sep}")', doc: 'Splits string.' },
          { label: 'join', insertText: 'join(${1:iterable})', doc: 'Joins elements.' },
        ];
        if (objName.includes('map') || objName.includes('dict')) {
          methods = [
            { label: 'get', insertText: 'get(${1:key})', doc: 'Returns value for key.' },
            { label: 'keys', insertText: 'keys()', doc: 'Returns dictionary keys.' },
            { label: 'values', insertText: 'values()', doc: 'Returns dictionary values.' },
            { label: 'items', insertText: 'items()', doc: 'Returns key-value pairs.' },
            { label: 'update', insertText: 'update(${1:dict})', doc: 'Updates dictionary.' },
            { label: 'pop', insertText: 'pop(${1:key})', doc: 'Removes key.' },
          ];
        } else if (objName.includes('list') || objName.includes('arr')) {
          methods = [
            { label: 'append', insertText: 'append(${1:item})', doc: 'Appends item.' },
            { label: 'extend', insertText: 'extend(${1:iterable})', doc: 'Extends list.' },
            { label: 'insert', insertText: 'insert(${1:index}, ${2:item})', doc: 'Inserts item.' },
            { label: 'remove', insertText: 'remove(${1:item})', doc: 'Removes item.' },
            { label: 'sort', insertText: 'sort()', doc: 'Sorts list.' },
          ];
        }

        return {
          suggestions: methods.map(m => ({
            label: m.label,
            kind: monaco.languages.CompletionItemKind.Method,
            insertText: m.insertText,
            insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
            documentation: m.doc,
            range,
          })),
        };
      }

      const symbols = extractDocumentSymbols(code);
      const suggestions = [
        { label: 'print', kind: monaco.languages.CompletionItemKind.Function, insertText: 'print(${1:value})', range },
        { label: 'len', kind: monaco.languages.CompletionItemKind.Function, insertText: 'len(${1:obj})', range },
        { label: 'range', kind: monaco.languages.CompletionItemKind.Function, insertText: 'range(${1:stop})', range },
        { label: 'enumerate', kind: monaco.languages.CompletionItemKind.Function, insertText: 'enumerate(${1:iterable})', range },
        ...symbols.map(s => ({ label: s, kind: monaco.languages.CompletionItemKind.Variable, insertText: s, range })),
      ];

      return { suggestions };
    },
  });

  // ── C++ COMPLETER ───────────────────────────────────────────
  monaco.languages.registerCompletionItemProvider('cpp', {
    triggerCharacters: ['.', ':', '>'],
    provideCompletionItems: (model, position) => {
      const lineUntilPosition = model.getValueInRange({
        startLineNumber: position.lineNumber,
        startColumn: 1,
        endLineNumber: position.lineNumber,
        endColumn: position.column,
      });

      const word = model.getWordUntilPosition(position);
      const range = {
        startLineNumber: position.lineNumber,
        endLineNumber: position.lineNumber,
        startColumn: word.startColumn,
        endColumn: word.endColumn,
      };

      const code = model.getValue();
      const dotMatch = lineUntilPosition.match(/([a-zA-Z_][a-zA-Z0-9_]*|\bstd\b)(\.|\:\:|->)\s*$/);

      if (dotMatch) {
        const objName = dotMatch[1].toLowerCase();
        let methods = [
          { label: 'push_back', insertText: 'push_back(${1:val})', doc: 'Appends element.' },
          { label: 'pop_back', insertText: 'pop_back()', doc: 'Removes last element.' },
          { label: 'size', insertText: 'size()', doc: 'Returns number of elements.' },
          { label: 'empty', insertText: 'empty()', doc: 'Checks if container is empty.' },
          { label: 'find', insertText: 'find(${1:key})', doc: 'Finds element.' },
          { label: 'insert', insertText: 'insert(${1:val})', doc: 'Inserts element.' },
          { label: 'clear', insertText: 'clear()', doc: 'Clears all elements.' },
        ];
        if (objName === 'std') {
          methods = [
            { label: 'cout', insertText: 'cout << ${1:value} << std::endl;', doc: 'Standard output stream.' },
            { label: 'cin', insertText: 'cin >> ${1:var};', doc: 'Standard input stream.' },
            { label: 'vector', insertText: 'vector<${1:int}> ${2:vec};', doc: 'Dynamic array container.' },
            { label: 'map', insertText: 'map<${1:string}, ${2:int}> ${3:map};', doc: 'Sorted associative container.' },
            { label: 'sort', insertText: 'sort(${1:begin}, ${2:end});', doc: 'Sorts elements.' },
          ];
        }

        return {
          suggestions: methods.map(m => ({
            label: m.label,
            kind: monaco.languages.CompletionItemKind.Method,
            insertText: m.insertText,
            insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
            documentation: m.doc,
            range,
          })),
        };
      }

      const symbols = extractDocumentSymbols(code);
      return {
        suggestions: [
          { label: 'std::cout', kind: monaco.languages.CompletionItemKind.Snippet, insertText: 'std::cout << ${1:value} << std::endl;', range },
          { label: 'std::vector', kind: monaco.languages.CompletionItemKind.Class, insertText: 'std::vector<${1:int}> ${2:vec};', range },
          ...symbols.map(s => ({ label: s, kind: monaco.languages.CompletionItemKind.Variable, insertText: s, range })),
        ],
      };
    },
  });

  // ── C# COMPLETER ────────────────────────────────────────────
  monaco.languages.registerCompletionItemProvider('csharp', {
    triggerCharacters: ['.'],
    provideCompletionItems: (model, position) => {
      const lineUntilPosition = model.getValueInRange({
        startLineNumber: position.lineNumber,
        startColumn: 1,
        endLineNumber: position.lineNumber,
        endColumn: position.column,
      });

      const word = model.getWordUntilPosition(position);
      const range = {
        startLineNumber: position.lineNumber,
        endLineNumber: position.lineNumber,
        startColumn: word.startColumn,
        endColumn: word.endColumn,
      };

      const code = model.getValue();
      const dotMatch = lineUntilPosition.match(/([a-zA-Z_][a-zA-Z0-9_]*)\.\s*$/);

      if (dotMatch) {
        const objName = dotMatch[1].toLowerCase();
        let methods = [
          { label: 'Add', insertText: 'Add(${1:val});', doc: 'Adds value.' },
          { label: 'Remove', insertText: 'Remove(${1:val});', doc: 'Removes value.' },
          { label: 'ContainsKey', insertText: 'ContainsKey(${1:key})', doc: 'Checks if dictionary contains key.' },
          { label: 'Count', insertText: 'Count', doc: 'Gets number of elements.' },
          { label: 'Clear', insertText: 'Clear()', doc: 'Removes all elements.' },
        ];
        if (objName === 'console') {
          methods = [
            { label: 'WriteLine', insertText: 'WriteLine(${1:value});', doc: 'Writes value to standard output.' },
            { label: 'ReadLine', insertText: 'ReadLine()', doc: 'Reads next line.' },
            { label: 'Write', insertText: 'Write(${1:value});', doc: 'Writes value.' },
          ];
        }

        return {
          suggestions: methods.map(m => ({
            label: m.label,
            kind: monaco.languages.CompletionItemKind.Method,
            insertText: m.insertText,
            insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
            documentation: m.doc,
            range,
          })),
        };
      }

      const symbols = extractDocumentSymbols(code);
      return {
        suggestions: [
          { label: 'Console.WriteLine', kind: monaco.languages.CompletionItemKind.Method, insertText: 'Console.WriteLine(${1:value});', range },
          { label: 'Dictionary', kind: monaco.languages.CompletionItemKind.Class, insertText: 'Dictionary<${1:string}, ${2:int}> ${3:dict} = new Dictionary<${1:string}, ${2:int}>();', range },
          ...symbols.map(s => ({ label: s, kind: monaco.languages.CompletionItemKind.Variable, insertText: s, range })),
        ],
      };
    },
  });

  // ── JS & TS COMPLETER ───────────────────────────────────────
  ['javascript', 'typescript'].forEach((lang) => {
    monaco.languages.registerCompletionItemProvider(lang, {
      triggerCharacters: ['.'],
      provideCompletionItems: (model, position) => {
        const lineUntilPosition = model.getValueInRange({
          startLineNumber: position.lineNumber,
          startColumn: 1,
          endLineNumber: position.lineNumber,
          endColumn: position.column,
        });

        const word = model.getWordUntilPosition(position);
        const range = {
          startLineNumber: position.lineNumber,
          endLineNumber: position.lineNumber,
          startColumn: word.startColumn,
          endColumn: word.endColumn,
        };

        const code = model.getValue();
        const dotMatch = lineUntilPosition.match(/([a-zA-Z_][a-zA-Z0-9_]*)\.\s*$/);

        if (dotMatch) {
          const objName = dotMatch[1].toLowerCase();
          let methods = [
            { label: 'map', insertText: 'map((${1:x}) => ${2:x})', doc: 'Creates a new array with mapped elements.' },
            { label: 'filter', insertText: 'filter((${1:x}) => ${2:true})', doc: 'Filters array.' },
            { label: 'push', insertText: 'push(${1:item})', doc: 'Appends element.' },
            { label: 'slice', insertText: 'slice(${1:start}, ${2:end})', doc: 'Returns section of array.' },
            { label: 'length', insertText: 'length', doc: 'Gets length.' },
            { label: 'get', insertText: 'get(${1:key})', doc: 'Gets Map element.' },
            { label: 'set', insertText: 'set(${1:key}, ${2:val})', doc: 'Sets Map element.' },
          ];
          if (objName === 'console') {
            methods = [
              { label: 'log', insertText: 'log(${1:msg});', doc: 'Outputs message.' },
              { label: 'error', insertText: 'error(${1:err});', doc: 'Outputs error.' },
              { label: 'warn', insertText: 'warn(${1:msg});', doc: 'Outputs warning.' },
            ];
          }

          return {
            suggestions: methods.map(m => ({
              label: m.label,
              kind: monaco.languages.CompletionItemKind.Method,
              insertText: m.insertText,
              insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
              documentation: m.doc,
              range,
            })),
          };
        }

        const symbols = extractDocumentSymbols(code);
        return {
          suggestions: [
            { label: 'console.log', kind: monaco.languages.CompletionItemKind.Snippet, insertText: 'console.log(${1:val});', range },
            ...symbols.map(s => ({ label: s, kind: monaco.languages.CompletionItemKind.Variable, insertText: s, range })),
          ],
        };
      },
    });
  });

  // ── RUST COMPLETER ──────────────────────────────────────────
  monaco.languages.registerCompletionItemProvider('rust', {
    triggerCharacters: ['.', ':'],
    provideCompletionItems: (model, position) => {
      const lineUntilPosition = model.getValueInRange({
        startLineNumber: position.lineNumber,
        startColumn: 1,
        endLineNumber: position.lineNumber,
        endColumn: position.column,
      });

      const word = model.getWordUntilPosition(position);
      const range = {
        startLineNumber: position.lineNumber,
        endLineNumber: position.lineNumber,
        startColumn: word.startColumn,
        endColumn: word.endColumn,
      };

      const code = model.getValue();
      const dotMatch = lineUntilPosition.match(/([a-zA-Z_][a-zA-Z0-9_]*|\bVec|\bHashMap)(\.|\:\:)\s*$/);

      if (dotMatch) {
        let methods = [
          { label: 'push', insertText: 'push(${1:val});', doc: 'Appends element.' },
          { label: 'insert', insertText: 'insert(${1:key}, ${2:val});', doc: 'Inserts key-value pair.' },
          { label: 'get', insertText: 'get(&${1:key})', doc: 'Returns reference to value.' },
          { label: 'len', insertText: 'len()', doc: 'Returns length.' },
          { label: 'is_empty', insertText: 'is_empty()', doc: 'Checks if empty.' },
          { label: 'iter', insertText: 'iter()', doc: 'Returns iterator.' },
        ];

        return {
          suggestions: methods.map(m => ({
            label: m.label,
            kind: monaco.languages.CompletionItemKind.Method,
            insertText: m.insertText,
            insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
            documentation: m.doc,
            range,
          })),
        };
      }

      const symbols = extractDocumentSymbols(code);
      return {
        suggestions: [
          { label: 'println!', kind: monaco.languages.CompletionItemKind.Snippet, insertText: 'println!("${1:{}}", ${2:val});', range },
          { label: 'Vec::new', kind: monaco.languages.CompletionItemKind.Function, insertText: 'Vec::new()', range },
          ...symbols.map(s => ({ label: s, kind: monaco.languages.CompletionItemKind.Variable, insertText: s, range })),
        ],
      };
    },
  });

  // ── GO COMPLETER ────────────────────────────────────────────
  monaco.languages.registerCompletionItemProvider('go', {
    triggerCharacters: ['.'],
    provideCompletionItems: (model, position) => {
      const lineUntilPosition = model.getValueInRange({
        startLineNumber: position.lineNumber,
        startColumn: 1,
        endLineNumber: position.lineNumber,
        endColumn: position.column,
      });

      const word = model.getWordUntilPosition(position);
      const range = {
        startLineNumber: position.lineNumber,
        endLineNumber: position.lineNumber,
        startColumn: word.startColumn,
        endColumn: word.endColumn,
      };

      const code = model.getValue();
      const dotMatch = lineUntilPosition.match(/([a-zA-Z_][a-zA-Z0-9_]*)\.\s*$/);

      if (dotMatch) {
        let methods = [
          { label: 'Println', insertText: 'Println(${1:v})', doc: 'Writes formatted line.' },
          { label: 'Printf', insertText: 'Printf("${1:%v}\\n", ${2:v})', doc: 'Writes formatted string.' },
          { label: 'Split', insertText: 'Split(${1:s}, "${2:sep}")', doc: 'Splits string.' },
        ];

        return {
          suggestions: methods.map(m => ({
            label: m.label,
            kind: monaco.languages.CompletionItemKind.Method,
            insertText: m.insertText,
            insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
            documentation: m.doc,
            range,
          })),
        };
      }

      const symbols = extractDocumentSymbols(code);
      return {
        suggestions: [
          { label: 'fmt.Println', kind: monaco.languages.CompletionItemKind.Snippet, insertText: 'fmt.Println(${1:v})', range },
          { label: 'make', kind: monaco.languages.CompletionItemKind.Function, insertText: 'make(${1:type}, ${2:len})', range },
          ...symbols.map(s => ({ label: s, kind: monaco.languages.CompletionItemKind.Variable, insertText: s, range })),
        ],
      };
    },
  });

  // ── LUA COMPLETER ───────────────────────────────────────────
  monaco.languages.registerCompletionItemProvider('lua', {
    triggerCharacters: ['.'],
    provideCompletionItems: (model, position) => {
      const lineUntilPosition = model.getValueInRange({
        startLineNumber: position.lineNumber,
        startColumn: 1,
        endLineNumber: position.lineNumber,
        endColumn: position.column,
      });

      const word = model.getWordUntilPosition(position);
      const range = {
        startLineNumber: position.lineNumber,
        endLineNumber: position.lineNumber,
        startColumn: word.startColumn,
        endColumn: word.endColumn,
      };

      const code = model.getValue();
      const dotMatch = lineUntilPosition.match(/([a-zA-Z_][a-zA-Z0-9_]*)\.\s*$/);

      if (dotMatch) {
        let methods = [
          { label: 'insert', insertText: 'insert(${1:t}, ${2:val})', doc: 'Inserts element.' },
          { label: 'remove', insertText: 'remove(${1:t}, ${2:pos})', doc: 'Removes element.' },
          { label: 'sub', insertText: 'sub(${1:s}, ${2:i}, ${3:j})', doc: 'Returns substring.' },
        ];

        return {
          suggestions: methods.map(m => ({
            label: m.label,
            kind: monaco.languages.CompletionItemKind.Method,
            insertText: m.insertText,
            insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
            documentation: m.doc,
            range,
          })),
        };
      }

      const symbols = extractDocumentSymbols(code);
      return {
        suggestions: [
          { label: 'print', kind: monaco.languages.CompletionItemKind.Function, insertText: 'print(${1:value})', range },
          ...symbols.map(s => ({ label: s, kind: monaco.languages.CompletionItemKind.Variable, insertText: s, range })),
        ],
      };
    },
  });

  // ── HTML COMPLETER ──────────────────────────────────────────
  monaco.languages.registerCompletionItemProvider('html', {
    triggerCharacters: ['<'],
    provideCompletionItems: (model, position) => {
      const word = model.getWordUntilPosition(position);
      const range = {
        startLineNumber: position.lineNumber,
        endLineNumber: position.lineNumber,
        startColumn: word.startColumn,
        endColumn: word.endColumn,
      };

      return {
        suggestions: [
          { label: 'div', kind: monaco.languages.CompletionItemKind.Snippet, insertText: '<div>${1}</div>', range },
          { label: 'span', kind: monaco.languages.CompletionItemKind.Snippet, insertText: '<span>${1}</span>', range },
          { label: 'p', kind: monaco.languages.CompletionItemKind.Snippet, insertText: '<p>${1}</p>', range },
          { label: 'h1', kind: monaco.languages.CompletionItemKind.Snippet, insertText: '<h1>${1}</h1>', range },
          { label: 'button', kind: monaco.languages.CompletionItemKind.Snippet, insertText: '<button>${1:Click}</button>', range },
        ],
      };
    },
  });
}


