"use client";

import * as React from "react";
import { motion, useInView, useReducedMotion } from "framer-motion";
import { cn } from "@/lib/utils";

export function Reveal({
  children,
  className,
  delay = 0,
  y = 24,
  as = "div",
}: {
  children: React.ReactNode;
  className?: string;
  delay?: number;
  y?: number;
  as?: "div" | "section" | "li" | "span";
}) {
  const ref = React.useRef<HTMLDivElement>(null);
  const inView = useInView(ref, { once: true, margin: "-80px" });
  const reduce = useReducedMotion();
  const MotionTag = motion[as] as typeof motion.div;

  return (
    <MotionTag
      ref={ref}
      initial={{ opacity: 0, y: reduce ? 0 : y }}
      animate={inView ? { opacity: 1, y: 0 } : { opacity: 0, y: reduce ? 0 : y }}
      transition={{ duration: 0.7, delay, ease: [0.16, 1, 0.3, 1] }}
      className={className}
    >
      {children}
    </MotionTag>
  );
}

export function SectionHeading({
  eyebrow,
  title,
  description,
  align = "left",
  className,
}: {
  eyebrow?: string;
  title: React.ReactNode;
  description?: React.ReactNode;
  align?: "left" | "center";
  className?: string;
}) {
  return (
    <div
      className={cn(
        "flex flex-col gap-4",
        align === "center" && "items-center text-center",
        className,
      )}
    >
      {eyebrow && (
        <Reveal>
          <div
            className={cn(
              "flex items-center gap-2.5",
              align === "center" && "justify-center",
            )}
          >
            {/* Small hexagonal crystal mark — echoes the StratOps logo */}
            <svg
              viewBox="0 0 24 24"
              className="h-3.5 w-3.5 text-brand"
              fill="none"
              aria-hidden="true"
            >
              <path
                d="M12 2L21 7V17L12 22L3 17V7L12 2Z"
                stroke="currentColor"
                strokeWidth="1.5"
                strokeLinejoin="round"
              />
              <path
                d="M12 2V22M3 7L21 17M21 7L3 17"
                stroke="currentColor"
                strokeWidth="0.75"
                strokeLinejoin="round"
                opacity="0.4"
              />
            </svg>
            <span className="font-mono-num text-[11px] uppercase tracking-[0.28em] text-brand">
              {eyebrow}
            </span>
          </div>
        </Reveal>
      )}
      <Reveal delay={0.06}>
        <h2 className="font-display text-[clamp(1.9rem,4vw,3.4rem)] font-semibold leading-[1.05] tracking-tight text-foreground">
          {title}
        </h2>
      </Reveal>
      {description && (
        <Reveal delay={0.12}>
          <p
            className={cn(
              "max-w-2xl text-base leading-relaxed text-muted-foreground sm:text-lg",
              align === "center" && "mx-auto",
            )}
          >
            {description}
          </p>
        </Reveal>
      )}
    </div>
  );
}

export function CountUp({
  value,
  suffix = "",
  prefix = "",
  duration = 1.6,
  className,
}: {
  value: string | number;
  suffix?: string;
  prefix?: string;
  duration?: number;
  className?: string;
}) {
  const ref = React.useRef<HTMLSpanElement>(null);
  const inView = useInView(ref, { once: true, margin: "-50px" });

  // Compute a smart initial display: the full value with the number zeroed
  const str = String(value);
  const match = str.match(/^([^\d]*)(\d+(?:\.\d+)?)(.*)$/);
  const before = match?.[1] ?? "";
  const after = match?.[3] ?? "";
  const initialValue = match ? `${before}0${after}` : str;

  const [display, setDisplay] = React.useState(initialValue);

  React.useEffect(() => {
    if (!inView) return;
    if (!match) {
      setDisplay(str);
      return;
    }
    const target = parseFloat(match[2]);
    if (isNaN(target)) {
      setDisplay(str);
      return;
    }
    const isInt = !match[2].includes(".");
    const start = performance.now();
    const animate = (t: number) => {
      const p = Math.min((t - start) / (duration * 1000), 1);
      const eased = 1 - Math.pow(1 - p, 3);
      const current = target * eased;
      const formatted = isInt
        ? Math.round(current).toString()
        : current.toFixed(1);
      setDisplay(`${before}${formatted}${after}`);
      if (p < 1) requestAnimationFrame(animate);
    };
    requestAnimationFrame(animate);
  }, [inView, value, duration]);

  // Safety fallback: if inView never triggers (e.g. IntersectionObserver issue),
  // show the real value after 2 seconds
  React.useEffect(() => {
    if (inView) return;
    const t = setTimeout(() => {
      setDisplay(str);
    }, 2000);
    return () => clearTimeout(t);
  }, [inView, str]);

  return (
    <span ref={ref} className={className}>
      {prefix}
      {display}
      {suffix}
    </span>
  );
}
