/**
 * FluxL language support for CodeMirror 6
 * Extracted from countermeasure-web query.ts
 */

import { StreamLanguage, LanguageSupport } from '@codemirror/language'
import { type Completion } from '@codemirror/autocomplete'

const KEYWORDS = [
  'from',
  'where',
  'select',
  'group',
  'by',
  'limit',
  'order',
  'desc',
  'asc',
  'join',
  'left',
  'right',
  'inner',
  'outer',
  'on',
  'as',
  'having',
  'distinct',
  'top',
  'and',
  'or',
  'not',
]

const OPERATORS = ['contains', 'starts_with', 'ends_with', 'matches', 'in', 'between', 'like']

const FUNCTIONS = [
  'count',
  'sum',
  'avg',
  'min',
  'max',
  'yara_x_match',
  'yara_match',
  'regex',
  'now',
  'bucket',
]

const fluxlLanguage = StreamLanguage.define({
  token(stream): string | null {
    if (stream.eatSpace()) {
      return null
    }

    if (stream.match('--') !== null) {
      stream.skipToEnd()
      return 'comment'
    }

    if (stream.match(/\/\*.*?\*\//) !== null) {
      return 'comment'
    }

    if (stream.match(/"(?:[^"\\]|\\.)*"/) !== null) {
      return 'string'
    }

    if (stream.match(/'(?:[^'\\]|\\.)*'/) !== null) {
      return 'string'
    }

    if (stream.match(/\d+(\.\d+)?/) !== null) {
      return 'number'
    }

    if (stream.match(/[A-Za-z_][\w.]*/) !== null) {
      const word = stream.current().toLowerCase()
      if (KEYWORDS.includes(word)) {
        return 'keyword'
      }
      if (OPERATORS.includes(word)) {
        return 'operator'
      }
      if (FUNCTIONS.includes(word)) {
        return 'variableName'
      }
      return 'variableName'
    }

    if (stream.match(/==|!=|<=|>=|[<>|=]/) !== null) {
      return 'operator'
    }

    stream.next()
    return null
  },
})

/** FluxL language support for CodeMirror */
export function fluxl(): LanguageSupport {
  return new LanguageSupport(fluxlLanguage)
}

/** Static completions for FluxL keywords, operators, and functions */
export const fluxlCompletions: Completion[] = [
  ...KEYWORDS.map(label => ({ label, type: 'keyword' as const })),
  ...OPERATORS.map(label => ({ label, type: 'keyword' as const })),
  ...FUNCTIONS.map(label => ({
    label: `${label}()`,
    type: 'function' as const,
  })),
]

export { fluxlLanguage }
