/**
 * ParameterizationPreview — read-only script display with placeholders /
 * AI-proposed parameter values highlighted.
 *
 * Used inside both NoTemplateDialog (showing the AI-drafted script with
 * proposed parameter values flagged in amber) and TemplatizePrompt (Phase 6,
 * showing the templated body with `{{ key }}` placeholders).
 *
 * Highlight rules:
 * - `{{ key }}` placeholders → cyan accent (template view)
 * - Substrings matching an entry in `highlightValues` → amber pill
 *   (proposed-parameterization view)
 *
 * Not a syntax-aware highlighter — accuracy of the underlying script is the
 * AI's responsibility.
 */
import { Fragment, useMemo } from 'react'

interface ParameterizationPreviewProps {
  body: string
  // Map of {paramKey: paramValue} to highlight as proposed values inline.
  // Longer values match first to avoid partial-overlap surprises.
  highlightValues?: Record<string, string>
}

type Token =
  | { kind: 'text'; text: string }
  | { kind: 'placeholder'; text: string; key: string }
  | { kind: 'value'; text: string; key: string }

function tokenize(body: string, highlightValues: Record<string, string> | undefined): Token[] {
  // Pass 1: split on {{ key }} placeholders so we never highlight inside one.
  const placeholderRe = /\{\{\s*(\w+)\s*\}\}/g
  const segments: Array<{ text: string; placeholderKey?: string }> = []
  let lastIndex = 0
  let m: RegExpExecArray | null
  while ((m = placeholderRe.exec(body)) !== null) {
    if (m.index > lastIndex) {
      segments.push({ text: body.slice(lastIndex, m.index) })
    }
    segments.push({ text: m[0], placeholderKey: m[1] })
    lastIndex = m.index + m[0].length
  }
  if (lastIndex < body.length) {
    segments.push({ text: body.slice(lastIndex) })
  }
  if (segments.length === 0) {
    segments.push({ text: body })
  }

  // Pass 2: in each non-placeholder segment, tokenize highlight values.
  const valueEntries = highlightValues
    ? Object.entries(highlightValues)
        .filter(([, v]) => typeof v === 'string' && v.length > 0)
        .sort((a, b) => b[1].length - a[1].length)  // longest match wins
    : []

  const tokens: Token[] = []
  for (const seg of segments) {
    if (seg.placeholderKey !== undefined) {
      tokens.push({ kind: 'placeholder', text: seg.text, key: seg.placeholderKey })
      continue
    }
    if (valueEntries.length === 0) {
      tokens.push({ kind: 'text', text: seg.text })
      continue
    }

    // Walk the segment one char at a time; at each position, try the longest
    // matching value. This is O(n * m) where m is the number of values —
    // fine for the small param sets we see in MSP scripts.
    let cursor = 0
    let pending = ''
    const flushPending = () => {
      if (pending) {
        tokens.push({ kind: 'text', text: pending })
        pending = ''
      }
    }
    while (cursor < seg.text.length) {
      let matched: { key: string; value: string } | null = null
      for (const [key, value] of valueEntries) {
        if (seg.text.startsWith(value, cursor)) {
          matched = { key, value }
          break
        }
      }
      if (matched) {
        flushPending()
        tokens.push({ kind: 'value', text: matched.value, key: matched.key })
        cursor += matched.value.length
      } else {
        pending += seg.text[cursor]
        cursor++
      }
    }
    flushPending()
  }
  return tokens
}

export function ParameterizationPreview({ body, highlightValues }: ParameterizationPreviewProps) {
  const tokens = useMemo(() => tokenize(body, highlightValues), [body, highlightValues])

  return (
    <pre className="text-[0.75rem] font-mono text-heading whitespace-pre-wrap overflow-x-auto rounded-lg border border-default bg-code px-3 py-2.5 max-h-[40vh] leading-relaxed">
      {tokens.map((t, i) => {
        if (t.kind === 'placeholder') {
          return (
            <span
              key={i}
              className="rounded px-1 bg-accent-dim text-accent-text font-semibold"
              title={`Parameter: ${t.key}`}
            >
              {t.text}
            </span>
          )
        }
        if (t.kind === 'value') {
          return (
            <span
              key={i}
              className="rounded px-1 bg-warning-dim text-warning font-semibold"
              title={`Proposed parameter ${t.key}`}
            >
              {t.text}
            </span>
          )
        }
        return <Fragment key={i}>{t.text}</Fragment>
      })}
    </pre>
  )
}

export default ParameterizationPreview
