/**
 * Single-pass PowerShell syntax highlighter.
 *
 * Uses a combined alternation regex so tokens matched earlier in the list
 * cannot be re-coloured by later rules (e.g. a variable inside a string
 * is captured by the string rule and won't be re-matched by the variable rule).
 *
 * Priority order:
 *  1. Comments       /#[^\r\n]star/
 *  2. String literals /"[^"]*"|'[^']*'/
 *  3. Unfilled placeholders /\{\{[^}]+\}\}/
 *  4. Variables      /\$\w+/
 *  5. Cmdlets        /[A-Z][a-z]+-[A-Z][a-zA-Z]+/
 *  6. Parameters     /-[A-Za-z]+/
 *  7. Keywords       /\b(if|else|...)\b/
 *
 * Note: variables (priority 4) consume $foreach before keywords (priority 7)
 * can match — this is intentional PowerShell behaviour.
 */

import React from 'react'

const TOKEN_REGEX = new RegExp(
  [
    /#[^\r\n]*/,                                                              // 1. comments
    /"[^"]*"|'[^']*'/,                                                        // 2. string literals
    /\{\{[^}]+\}\}/,                                                          // 3. unfilled placeholders
    /\$\w+/,                                                                  // 4. variables
    /[A-Z][a-z]+-[A-Z][a-zA-Z]+/,                                            // 5. cmdlets (Verb-Noun)
    /-[A-Za-z]+/,                                                             // 6. parameters
    /\b(?:if|else|elseif|foreach|for|while|function|return|try|catch|finally|param|switch)\b/, // 7. keywords
  ]
    .map(r => r.source)
    .join('|'),
  'g'
)

const TOKEN_CLASSES: Record<string, string> = {
  comment: 'text-[#8b949e]',
  string: 'text-[#a5d6ff]',
  placeholder: 'text-amber-400 underline decoration-dashed',
  variable: 'text-[#79c0ff]',
  cmdlet: 'text-primary',
  parameter: 'text-[#d2a8ff]',
  keyword: 'text-[#ff7b72]',
}

const KEYWORDS = new Set([
  'if', 'else', 'elseif', 'foreach', 'for', 'while',
  'function', 'return', 'try', 'catch', 'finally', 'param', 'switch',
])

function classify(token: string): string {
  if (token.startsWith('#')) return 'comment'
  if (token.startsWith('"') || token.startsWith("'")) return 'string'
  if (token.startsWith('{{')) return 'placeholder'
  if (token.startsWith('$')) return 'variable'
  if (/^-[A-Za-z]+$/.test(token)) return 'parameter'
  if (KEYWORDS.has(token)) return 'keyword'
  return 'cmdlet'
}

interface Props {
  script: string
  className?: string
}

export function PowerShellHighlighter({ script, className }: Props) {
  const parts: React.ReactNode[] = []
  let lastIndex = 0
  const tokenRegex = new RegExp(TOKEN_REGEX.source, TOKEN_REGEX.flags)

  let match: RegExpExecArray | null

  while ((match = tokenRegex.exec(script)) !== null) {
    if (match.index > lastIndex) {
      parts.push(script.slice(lastIndex, match.index))
    }
    const token = match[0]
    const kind = classify(token)
    parts.push(
      <span key={match.index} className={TOKEN_CLASSES[kind]}>
        {token}
      </span>
    )
    lastIndex = match.index + token.length
  }

  if (lastIndex < script.length) {
    parts.push(script.slice(lastIndex))
  }

  return (
    <pre className={className ?? "font-mono text-sm bg-card rounded-xl p-4 overflow-x-auto"}>
      <code>{parts}</code>
    </pre>
  )
}
