'use client';

import { MotionConfig, motion, useInView, useReducedMotion } from 'framer-motion';
import { ArrowRight } from 'lucide-react';
import { useEffect, useRef, useState } from 'react';
import { cn } from '@/lib/utils';

const EASE = [0.16, 1, 0.3, 1] as const;

/* ---------------- WordsPullUp ---------------- */
interface WordsPullUpProps {
  text: string;
  className?: string;
  showAsterisk?: boolean;
  /** Seconds before the first word starts, for chaining several lines. */
  delay?: number;
  style?: React.CSSProperties;
}

export const WordsPullUp = ({ text, className = '', showAsterisk = false, delay = 0, style }: WordsPullUpProps) => {
  const ref = useRef<HTMLDivElement>(null);
  const isInView = useInView(ref, { once: true });
  const words = text.split(' ');

  return (
    <div ref={ref} className={cn('inline-flex flex-wrap', className)} style={style}>
      {words.map((word, i) => {
        const isLast = i === words.length - 1;
        return (
          <motion.span
            key={i}
            initial={{ y: 20, opacity: 0 }}
            animate={isInView ? { y: 0, opacity: 1 } : {}}
            transition={{ duration: 0.6, delay: delay + i * 0.08, ease: EASE }}
            className="relative inline-block"
            style={{ marginRight: isLast ? 0 : '0.25em' }}
          >
            {word}
            {showAsterisk && isLast && (
              <span aria-hidden="true" className="absolute -right-[0.3em] top-[0.65em] text-[0.31em]">
                *
              </span>
            )}
          </motion.span>
        );
      })}
    </div>
  );
};

/* ---------------- WordsPullUpMultiStyle ---------------- */
interface Segment {
  text: string;
  className?: string;
}

interface WordsPullUpMultiStyleProps {
  segments: Segment[];
  className?: string;
  style?: React.CSSProperties;
}

export const WordsPullUpMultiStyle = ({ segments, className = '', style }: WordsPullUpMultiStyleProps) => {
  const ref = useRef<HTMLDivElement>(null);
  const isInView = useInView(ref, { once: true });

  const words: { word: string; className?: string }[] = [];
  segments.forEach((seg) => {
    seg.text.split(' ').forEach((w) => {
      if (w) words.push({ word: w, className: seg.className });
    });
  });

  return (
    <div ref={ref} className={cn('inline-flex flex-wrap justify-center', className)} style={style}>
      {words.map((w, i) => (
        <motion.span
          key={i}
          initial={{ y: 20, opacity: 0 }}
          animate={isInView ? { y: 0, opacity: 1 } : {}}
          transition={{ duration: 0.6, delay: i * 0.08, ease: EASE }}
          className={cn('inline-block', w.className)}
          style={{ marginRight: '0.25em' }}
        >
          {w.word}
        </motion.span>
      ))}
    </div>
  );
};

/* ---------------- Hero ---------------- */
export interface PrismaHeroNavItem {
  label: string;
  href: string;
}

export interface PrismaHeroProps {
  /** The oversized animated word(s). Pass an array to put each entry on its own line. */
  title?: string | string[];
  /** Full headline for screen readers and search engines, when `title` alone is too terse. */
  srTitle?: string;
  showAsterisk?: boolean;
  /** Overrides for the title's size, leading or font, e.g. for longer words. */
  titleClassName?: string;
  description?: React.ReactNode;
  /** Call-to-action area. Defaults to a single "Join the lab" button. */
  actions?: React.ReactNode;
  /** Small print under the actions. */
  meta?: React.ReactNode;
  navItems?: PrismaHeroNavItem[];
  navLabel?: string;
  /** Extra classes for the nav tab, e.g. its colour or height. */
  navClassName?: string;
  /**
   * Extra classes for each nav link, e.g. text colours that suit `navClassName`.
   * The last-clicked link has `data-active="true"`, so `data-[active=true]:` styles it.
   */
  navLinkClassName?: string;
  videoSrc?: string;
  /** Still image shown while the video loads, and instead of it for reduced-motion users. */
  posterSrc?: string;
  /** Put the description and actions under the title instead of beside it. */
  stacked?: boolean;
  /** Extra classes for the content block, e.g. bottom padding to lift it up. */
  contentClassName?: string;
  /** Extra classes for the title-and-copy block only (not the aside). */
  textClassName?: string;
  /** Visual shown to the right of the text (use with `stacked`). */
  aside?: React.ReactNode;
  asideClassName?: string;
  /** Extra classes for the rounded video frame, e.g. `rounded-none` for a full-bleed hero. */
  frameClassName?: string;
  className?: string;
}

const defaultNavItems: PrismaHeroNavItem[] = ['Our story', 'Collective', 'Workshops', 'Programs', 'Inquiries'].map(
  (label) => ({ label, href: '#' }),
);

const DEFAULT_VIDEO =
  'https://d8j0ntlcm91z4.cloudfront.net/user_38xzZboKViGWJOttwIXH07lWA1P/hf_20260405_170732_8a9ccda6-5cff-4628-b164-059c500a2b41.mp4';

/** The round black arrow badge used inside the hero's primary button. */
export const PrismaHeroArrow = () => (
  <span className="flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-black transition-transform group-hover:scale-110 sm:h-10 sm:w-10">
    <ArrowRight className="h-4 w-4 text-cream" aria-hidden="true" />
  </span>
);

const PrismaHero = ({
  title = 'Prisma',
  srTitle,
  showAsterisk = true,
  titleClassName,
  description = 'Prisma is a worldwide network of visual artists, filmmakers and storytellers bound not by place, status or labels but by passion and hunger to unlock potential through our unique perspectives.',
  actions,
  meta,
  navItems = defaultNavItems,
  navLabel = 'Hero',
  navClassName,
  navLinkClassName,
  videoSrc = DEFAULT_VIDEO,
  posterSrc,
  stacked = false,
  contentClassName,
  textClassName,
  aside,
  asideClassName,
  frameClassName,
  className,
}: PrismaHeroProps) => {
  const videoRef = useRef<HTMLVideoElement>(null);
  const reduceMotion = useReducedMotion();
  const [activeNav, setActiveNav] = useState<string | null>(null);
  const titleLines = Array.isArray(title) ? title : [title];
  // Each line starts pulling up once the previous line's words have started.
  const lineDelays = titleLines.map((_, i) =>
    titleLines.slice(0, i).reduce((sum, line) => sum + line.split(' ').length * 0.08, 0),
  );

  useEffect(() => {
    if (reduceMotion) videoRef.current?.pause();
  }, [reduceMotion]);

  return (
    <MotionConfig reducedMotion="user">
      <section className={cn('h-screen w-full', className)}>
        <div
          className={cn('relative h-full w-full overflow-hidden rounded-2xl bg-black md:rounded-[2rem]', frameClassName)}
        >
          {/* Background video */}
          <video
            ref={videoRef}
            autoPlay
            loop
            muted
            playsInline
            preload="metadata"
            poster={posterSrc}
            aria-hidden="true"
            className="absolute inset-0 h-full w-full object-cover"
            src={videoSrc}
          />

          {/* Noise overlay */}
          <div className="noise-overlay pointer-events-none absolute inset-0 opacity-[0.7] mix-blend-overlay" />

          {/* Gradient overlay */}
          <div className="pointer-events-none absolute inset-0 bg-gradient-to-b from-black/30 via-transparent to-black/70" />

          {/* Navbar */}
          {navItems.length > 0 && (
            <nav aria-label={navLabel} className="absolute left-1/2 top-0 z-20 max-w-full -translate-x-1/2">
              <div
                className={cn(
                  'flex items-center gap-3 whitespace-nowrap rounded-b-2xl bg-black px-4 py-2 sm:gap-6 md:gap-12 md:rounded-b-3xl md:px-8 lg:gap-14',
                  navClassName,
                )}
              >
                {navItems.map((item) => (
                  <a
                    key={item.label}
                    href={item.href}
                    onClick={() => setActiveNav(item.href)}
                    data-active={activeNav === item.href}
                    aria-current={activeNav === item.href ? 'location' : undefined}
                    className={cn(
                      'text-[10px] text-cream/80 no-underline transition-colors hover:text-cream sm:text-xs md:text-sm',
                      navLinkClassName,
                    )}
                  >
                    {item.label}
                  </a>
                ))}
              </div>
            </nav>
          )}

          {/* Hero content */}
          <div className={cn('absolute bottom-0 left-0 right-0 px-4 pb-2 sm:px-6 md:px-10', contentClassName)}>
            <div className="grid grid-cols-12 items-end gap-4">
              <div
                className={cn(
                  'col-span-12',
                  stacked ? 'flex flex-col gap-4' : 'contents',
                  stacked && aside && 'lg:col-span-7',
                  textClassName,
                )}
              >
                <div className={cn('col-span-12', !stacked && 'lg:col-span-8')}>
                  <h1
                    className={cn(
                      'm-0 font-medium leading-[0.85] tracking-[-0.07em] text-cream text-[26vw] sm:text-[24vw] md:text-[22vw] lg:text-[20vw] xl:text-[19vw] 2xl:text-[20vw]',
                      titleClassName,
                    )}
                  >
                    {srTitle && <span className="sr-only">{srTitle}</span>}
                    <span aria-hidden={srTitle ? true : undefined}>
                      {titleLines.map((line, i) => (
                        <WordsPullUp
                          key={i}
                          text={line}
                          delay={lineDelays[i]}
                          showAsterisk={showAsterisk && i === titleLines.length - 1}
                          className={titleLines.length > 1 ? 'flex' : undefined}
                        />
                      ))}
                    </span>
                  </h1>
                </div>
  
                <div
                  className={cn(
                    'flex flex-col gap-5',
                    stacked ? 'max-w-2xl pb-6' : 'col-span-12 pb-6 lg:col-span-4 lg:pb-10',
                  )}
                >
                  <motion.p
                    initial={{ y: 20, opacity: 0 }}
                    animate={{ y: 0, opacity: 1 }}
                    transition={{ duration: 0.8, delay: 0.5, ease: EASE }}
                    className="m-0 text-xs text-cream/80 sm:text-sm md:text-base"
                    style={{ lineHeight: 1.2 }}
                  >
                    {description}
                  </motion.p>
  
                  <motion.div
                    initial={{ y: 20, opacity: 0 }}
                    animate={{ y: 0, opacity: 1 }}
                    transition={{ duration: 0.8, delay: 0.7, ease: EASE }}
                    className="flex flex-wrap items-center gap-x-5 gap-y-3"
                  >
                    {actions ?? (
                      <button className="group inline-flex items-center gap-2 self-start rounded-full border-0 bg-primary py-1 pl-5 pr-1 text-sm font-medium text-black transition-all hover:gap-3 sm:text-base">
                        Join the lab
                        <PrismaHeroArrow />
                      </button>
                    )}
                  </motion.div>
  
                  {meta && (
                    <motion.p
                      initial={{ opacity: 0 }}
                      animate={{ opacity: 1 }}
                      transition={{ duration: 0.8, delay: 0.9, ease: EASE }}
                      className="m-0 text-[11px] text-cream/60 sm:text-xs"
                    >
                      {meta}
                    </motion.p>
                  )}
                </div>
              </div>

              {aside && (
                <motion.div
                  initial={{ opacity: 0, scale: 0.96 }}
                  animate={{ opacity: 1, scale: 1 }}
                  transition={{ duration: 1, delay: 0.6, ease: EASE }}
                  className={cn('col-span-12 self-center pb-6 lg:col-span-5', asideClassName)}
                >
                  {aside}
                </motion.div>
              )}
            </div>
          </div>
        </div>
      </section>
    </MotionConfig>
  );
};

export { PrismaHero };
