// One minute-bucket of weave letters, rendered in the monospace `weave`
// font so consecutive rows align on a column grid.
//
// The letter body is rendered as class-coloured spans grouped by run
// (Authored/Social affirm/Communication/Consumption/Corrective). A typical
// row renders as 3–6 contiguous coloured spans, not N independent glyphs,
// which is what gives the ribbon its woven look. Pending letters from the
// local queue are appended in `accentTint` so they read as a separate
// species and collapse upward into the live row when the flush fires.
//
// The day's first row (HHMM === '0000', UTC) prepends a low-opacity
// weekday glyph to the left as the calendrical warp behind the weft.

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

export type TapestryRowProps = {
  bucket?: string
  letters: string
  // Pending letters from the local queue (live row only). Rendered in
  // `accentTint` so the eye reads them as a separate species — they
  // collapse into the live row without a visual seam when the flush fires.
  pendingLetters?: string
  // When true the row is the live (current-minute) tail. Drives whether
  // the pending tail is rendered.
  isLive?: boolean
}

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`.
//
// 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 row
// 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 const TapestryRow = memo(function TapestryRow({
  bucket,
  letters,
  pendingLetters,
  isLive,
}: TapestryRowProps) {
  const showPending = isLive && pendingLetters && pendingLetters.length > 0
  const weekdayGlyph = bucket ? dayStartWeekdayGlyph(bucket) : null

  return (
    <XStack alignItems="baseline" paddingHorizontal="$4" paddingVertical="$1">
      <Text fontFamily="$weave" fontSize="$5" color="$color" opacity={0.12} width={16}>
        {weekdayGlyph ?? ' '}
      </Text>
      <Text fontFamily="$weave" fontSize="$5" color="$color">
        {renderRuns(letters)}
        {showPending ? (
          <Text color="$accentTint">{renderRuns(pendingLetters!)}</Text>
        ) : null}
      </Text>
    </XStack>
  )
})

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
