import * as React from 'react'
import { motion, useScroll, useTransform, type MotionValue } from 'framer-motion'
import { useRef } from 'react'

export interface MagicTextProps {
  text: string
  /** dir of the text — affects word flow */
  dir?: 'rtl' | 'ltr'
  /** inline style applied to the paragraph (font-size, color, line-height…) */
  style?: React.CSSProperties
  className?: string
}

interface WordProps {
  children: string
  progress: MotionValue<number>
  range: [number, number]
}

const Word: React.FC<WordProps> = ({ children, progress, range }) => {
  const opacity = useTransform(progress, range, [0, 1])
  return (
    <span style={{ position: 'relative', marginInlineEnd: '0.28em' }}>
      <span style={{ position: 'absolute', inset: 0, opacity: 0.18 }}>{children}</span>
      <motion.span style={{ opacity }}>{children}</motion.span>
    </span>
  )
}

/**
 * Scroll-driven per-word reveal. Each word fades from faint → solid as the
 * paragraph scrolls through the viewport. Adapted from the HextaUI MagicText
 * recipe to framer-motion + RTL body text.
 */
export const MagicText: React.FC<MagicTextProps> = ({ text, dir = 'rtl', style, className }) => {
  const container = useRef<HTMLParagraphElement>(null)
  const { scrollYProgress } = useScroll({
    target: container,
    offset: ['start 0.9', 'start 0.35'],
  })
  const words = text.split(' ')

  return (
    <p
      ref={container}
      dir={dir}
      className={className}
      style={{ display: 'flex', flexWrap: 'wrap', textAlign: 'justify', ...style }}
    >
      {words.map((word, i) => {
        const start = i / words.length
        const end = start + 1 / words.length
        return (
          <Word key={i} progress={scrollYProgress} range={[start, end]}>
            {word}
          </Word>
        )
      })}
    </p>
  )
}

export interface MagicTextGroupProps {
  /** ordered list of paragraphs — revealed sequentially, one finishing before the next starts */
  paragraphs: string[]
  dir?: 'rtl' | 'ltr'
  style?: React.CSSProperties
  className?: string
}

/**
 * Reveals several paragraphs with a SINGLE shared scroll progress. Every word
 * across all paragraphs gets a global range, so paragraph 1 fully reveals
 * before paragraph 2 begins (instead of all paragraphs animating at once).
 */
export const MagicTextGroup: React.FC<MagicTextGroupProps> = ({ paragraphs, dir = 'rtl', style, className }) => {
  const container = useRef<HTMLDivElement>(null)
  const { scrollYProgress } = useScroll({
    target: container,
    offset: ['start 0.9', 'end 0.4'],
  })

  // tokenize once and assign a continuous global index to every word
  const wordsPerPara = paragraphs.map((p) => p.split(' '))
  const totalWords = wordsPerPara.reduce((n, w) => n + w.length, 0)
  let globalIndex = 0

  return (
    <div ref={container}>
      {wordsPerPara.map((words, pi) => (
        <p
          key={pi}
          dir={dir}
          className={className}
          style={{ display: 'flex', flexWrap: 'wrap', textAlign: 'justify', ...style }}
        >
          {words.map((word, wi) => {
            const start = globalIndex / totalWords
            const end = (globalIndex + 1) / totalWords
            globalIndex += 1
            return (
              <Word key={wi} progress={scrollYProgress} range={[start, end]}>
                {word}
              </Word>
            )
          })}
        </p>
      ))}
    </div>
  )
}
