// Tapestry "wall" text. The weave's letters are rendered as one
// continuous monospace block — class-based color, not whitespace, gives
// the wall its woven texture. Each maximal same-class run becomes one
// inner `<Text>` span so RN's text-flow merges all spans into a single
// wrapping paragraph; consecutive same-class letters share a span so a
// typical wall renders as a handful of coloured runs instead of N
// independent glyphs.
//
// Pending letters from the local emit queue render as a trailing
// `accentTint` span so they read as a separate species and collapse
// into the wall without a visual seam when the flush fires.

import { memo, type ReactNode } from 'react'
import type { Letter } from 'src/lib/tapestry/grammar'
import { Text } from 'tamagui'

type WeaveClass =
  | 'authored'
  | 'social'
  | 'communication'
  | 'consumption'
  | 'corrective'
  | 'unknown'

// Letter → class. Mirrors the grammar in `src/lib/tapestry/grammar.ts`
// without re-importing each meaning string. The five classes map to
// Tamagui colour tokens via `CLASS_TOKEN`. Mirrored on the watch by
// `targets/_scripts/gen-tapestry-letters.mjs` — keep both tables in
// step when the grammar grows.
//
// The grammar's "Admin" group (`E` edit profile, `T` theme change) folds
// into `authored` here — they're uppercase active user gestures, and the
// implementation plan §4.2 colour table only enumerates five classes. A
// dedicated sixth class would add a sixth palette without enriching the
// woven texture.
const LETTER_CLASS: Record<string, WeaveClass> = {
  P: 'authored',
  C: 'authored',
  M: 'authored',
  V: 'authored',
  E: 'authored',
  T: 'authored',
  L: 'social',
  R: 'social',
  B: 'social',
  F: 'social',
  D: 'communication',
  N: 'communication',
  s: 'consumption',
  v: 'consumption',
  e: 'consumption',
  u: 'corrective',
  d: 'corrective',
  x: 'corrective',
}

const CLASS_TOKEN: Record<WeaveClass, string> = {
  authored: '$accent',
  social: '$accentMuted',
  communication: '$accentTint',
  consumption: '$colorTertiary',
  corrective: '$weaveCorrective',
  unknown: '$color',
}

// Group consecutive same-class letters into one span each so a typical
// wall becomes a handful of coloured runs instead of N coloured glyphs.
// The JetBrains Mono column grid stays intact across span boundaries.
function classRuns(body: string): Array<{ cls: WeaveClass; text: string }> {
  if (body.length === 0) return []
  const runs: Array<{ cls: WeaveClass; text: string }> = []
  let i = 0
  while (i < body.length) {
    const cls = LETTER_CLASS[body[i]!] ?? 'unknown'
    let j = i + 1
    while (j < body.length && (LETTER_CLASS[body[j]!] ?? 'unknown') === cls) j++
    runs.push({ cls, text: body.slice(i, j) })
    i = j
  }
  return runs
}

function renderRuns(body: string): ReactNode {
  const runs = classRuns(body)
  return runs.map((run, idx) => (
    <Text key={`${idx}:${run.cls}`} color={CLASS_TOKEN[run.cls]}>
      {run.text}
    </Text>
  ))
}

export type WeaveTextProps = {
  // The full weave body: live letters + history letters concatenated
  // newest-first into one string with no per-minute separators.
  body: string
  // Optional locally-queued pending tail, rendered in `accentTint` so
  // it reads as a separate species. Joins the body without a line break.
  pending?: string
}

export const WeaveText = memo(function WeaveText({ body, pending }: WeaveTextProps) {
  const showPending = pending && pending.length > 0
  return (
    <Text fontFamily="$weave" fontSize="$5" color="$color">
      {renderRuns(body)}
      {showPending ? <Text color="$accentTint">{renderRuns(pending!)}</Text> : null}
    </Text>
  )
})

export type { WeaveClass }
// Exported for unit tests and any future consumer that wants the same
// class-by-class colouring outside this row component.
export { CLASS_TOKEN, classRuns, LETTER_CLASS }

// Compile-time assertion that every grammar letter has a class. The
// `LETTER_CLASS` keys are the exact set of `Letter`s; if a future grammar
// addition slips by, this line stops type-checking.
type _AllLettersClassed = Letter extends keyof typeof LETTER_CLASS ? true : never
const _allLettersClassed: _AllLettersClassed = true
void _allLettersClassed
