"use client";

import { CheckIcon } from "@/assets/icons";
import gsap from "gsap";
import React, {
  ReactNode,
  useEffect,
  useLayoutEffect,
  useRef,
  useState,
} from "react";

export interface Step {
  title: string;
  description?: string;
  content: ReactNode;
}

interface StepperProps {
  steps: Step[];
  currentStep?: number;
  onStepChange?: (step: number) => void;
  onSubmit?: () => void;
  isSubmitting?: boolean;
  nextDisabled?: boolean;
}

const Stepper: React.FC<StepperProps> = ({
  steps,
  currentStep: controlledStep,
  onStepChange,
  onSubmit,
  isSubmitting = false,
  nextDisabled = false,
}) => {
  const [internalStep, setInternalStep] = useState(0);
  const currentStep =
    controlledStep !== undefined ? controlledStep : internalStep;

  const rootRef = useRef<HTMLDivElement>(null);
  const railRef = useRef<HTMLDivElement>(null);
  const railFillRef = useRef<HTMLDivElement>(null);
  const stepRefs = useRef<Array<HTMLButtonElement | null>>([]);
  const labelRefs = useRef<Array<HTMLDivElement | null>>([]);
  const checkRefs = useRef<Array<HTMLSpanElement | null>>([]);
  const numberRefs = useRef<Array<HTMLSpanElement | null>>([]);
  const contentRef = useRef<HTMLDivElement>(null);
  const prevBtnRef = useRef<HTMLButtonElement>(null);
  const nextBtnRef = useRef<HTMLButtonElement>(null);
  const submitGlowRef = useRef<HTMLSpanElement>(null);
  const prevStepRef = useRef<number>(currentStep);

  // Intro animation
  useLayoutEffect(() => {
    const reduced =
      typeof window !== "undefined" &&
      window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    if (reduced) return;

    const ctx = gsap.context(() => {
      gsap.from(stepRefs.current.filter(Boolean), {
        scale: 0,
        opacity: 0,
        rotate: -180,
        duration: 0.7,
        stagger: 0.08,
        ease: "back.out(2)",
      });
      gsap.from(labelRefs.current.filter(Boolean), {
        y: 12,
        opacity: 0,
        duration: 0.5,
        stagger: 0.08,
        delay: 0.15,
        ease: "power3.out",
      });
      if (contentRef.current) {
        gsap.from(contentRef.current, {
          y: 24,
          opacity: 0,
          duration: 0.6,
          delay: 0.3,
          ease: "power3.out",
        });
      }
    }, rootRef);

    return () => ctx.revert();
  }, []);

  // Animate rail fill + active circle pulse when current step changes
  useLayoutEffect(() => {
    const reduced =
      typeof window !== "undefined" &&
      window.matchMedia("(prefers-reduced-motion: reduce)").matches;

    const total = steps.length - 1;
    const target = total > 0 ? (currentStep / total) * 100 : 0;
    if (railFillRef.current) {
      gsap.to(railFillRef.current, {
        width: `${target}%`,
        duration: reduced ? 0 : 0.8,
        ease: "power3.inOut",
      });
    }

    // Pulse the active circle
    const active = stepRefs.current[currentStep];
    if (active && !reduced) {
      gsap.fromTo(
        active,
        { scale: 1 },
        {
          scale: 1.18,
          duration: 0.25,
          yoyo: true,
          repeat: 1,
          ease: "power2.inOut",
        },
      );
    }

    // Animate newly checked step
    const prev = prevStepRef.current;
    if (currentStep > prev && !reduced) {
      const justCompleted = checkRefs.current[prev];
      const oldNumber = numberRefs.current[prev];
      if (justCompleted) {
        gsap.fromTo(
          justCompleted,
          { scale: 0, rotate: -90, opacity: 0 },
          {
            scale: 1,
            rotate: 0,
            opacity: 1,
            duration: 0.5,
            ease: "back.out(2.4)",
          },
        );
      }
      if (oldNumber) {
        gsap.to(oldNumber, { opacity: 0, duration: 0.2 });
      }
    }
    prevStepRef.current = currentStep;
  }, [currentStep, steps.length]);

  // Animate content swap when step changes
  const isFirstContentRender = useRef(true);
  useLayoutEffect(() => {
    if (isFirstContentRender.current) {
      isFirstContentRender.current = false;
      return;
    }
    const reduced =
      typeof window !== "undefined" &&
      window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    if (reduced || !contentRef.current) return;

    gsap.fromTo(
      contentRef.current,
      { y: 18, opacity: 0, filter: "blur(6px)" },
      {
        y: 0,
        opacity: 1,
        filter: "blur(0px)",
        duration: 0.55,
        ease: "power3.out",
      },
    );
  }, [currentStep]);

  // Submit button glow loop on last step
  useEffect(() => {
    if (currentStep !== steps.length - 1 || !submitGlowRef.current) return;
    const reduced =
      typeof window !== "undefined" &&
      window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    if (reduced) return;

    const tween = gsap.to(submitGlowRef.current, {
      opacity: 0.85,
      scale: 1.08,
      duration: 1.2,
      yoyo: true,
      repeat: -1,
      ease: "sine.inOut",
    });
    return () => {
      tween.kill();
    };
  }, [currentStep, steps.length]);

  const handleStepClick = (index: number) => {
    if (index <= currentStep) {
      if (onStepChange) {
        onStepChange(index);
      } else {
        setInternalStep(index);
      }
    }
  };

  const handleButtonHover = (
    btn: HTMLButtonElement | null,
    enter: boolean,
  ) => {
    if (!btn) return;
    gsap.to(btn, {
      scale: enter ? 1.04 : 1,
      y: enter ? -2 : 0,
      duration: 0.25,
      ease: "power2.out",
    });
  };

  const nextStep = () => {
    if (nextDisabled) return;
    if (currentStep === steps.length - 1) {
      if (onSubmit) onSubmit();
    } else if (currentStep < steps.length - 1) {
      const newStep = currentStep + 1;
      if (onStepChange) {
        onStepChange(newStep);
      } else {
        setInternalStep(newStep);
      }
    }
    if (typeof window !== "undefined") {
      window.scroll({ top: 0, behavior: "smooth" });
    }
  };

  const prevStep = () => {
    if (currentStep > 0) {
      const newStep = currentStep - 1;
      if (onStepChange) {
        onStepChange(newStep);
      } else {
        setInternalStep(newStep);
      }
    }
    if (typeof window !== "undefined") {
      window.scroll({ top: 0, behavior: "smooth" });
    }
  };

  const isLastStep = currentStep === steps.length - 1;

  return (
    <div
      ref={rootRef}
      className="relative mx-auto w-full max-w-4xl overflow-hidden rounded-2xl p-8"
    >
      {/* Decorative background blobs */}
      <div
        aria-hidden
        className="pointer-events-none absolute -left-24 -top-24 h-64 w-64 rounded-full bg-primary/10 blur-3xl"
      />
      <div
        aria-hidden
        className="pointer-events-none absolute -bottom-32 -right-16 h-72 w-72 rounded-full bg-blue/10 blur-3xl"
      />

      {/* Step indicator row */}
      <div className="relative mb-10">
        {/* Rail (track) */}
        <div
          ref={railRef}
          className="absolute left-[6%] right-[6%] top-6 h-1.5 -translate-y-1/2 overflow-hidden rounded-full bg-stroke/70 dark:bg-dark-3"
        >
          {/* Animated fill */}
          <div
            ref={railFillRef}
            className="relative h-full w-0 rounded-full bg-gradient-to-r from-primary via-blue to-primary bg-[length:200%_100%]"
            style={{
              backgroundPosition: "0% 50%",
              animation: "stepperShimmer 3s linear infinite",
            }}
          >
            <span className="absolute right-0 top-1/2 h-3 w-3 -translate-y-1/2 translate-x-1/2 rounded-full bg-primary shadow-[0_0_12px_rgba(91,113,255,0.9)]" />
          </div>
        </div>

        <div className="relative flex items-start justify-between">
          {steps.map((step, index) => {
            const isCompleted = index < currentStep;
            const isActive = index === currentStep;
            const isLocked = index > currentStep;

            return (
              <div
                key={index}
                className="relative flex flex-1 flex-col items-center"
              >
                <button
                  ref={(el) => {
                    stepRefs.current[index] = el;
                  }}
                  onClick={() => handleStepClick(index)}
                  disabled={isLocked}
                  className={`group relative flex h-12 w-12 items-center justify-center rounded-full text-base font-semibold transition-colors duration-300 ${
                    isCompleted
                      ? "cursor-pointer bg-gradient-to-br from-primary to-blue text-white shadow-lg shadow-primary/30"
                      : isActive
                        ? "bg-gradient-to-br from-primary to-blue text-white shadow-lg shadow-primary/40"
                        : "cursor-not-allowed bg-gray-2 text-gray-5 dark:bg-dark-3 dark:text-gray-4"
                  }`}
                  aria-current={isActive ? "step" : undefined}
                  aria-label={`Step ${index + 1}: ${step.title}`}
                >
                  {/* Active ring */}
                  {isActive && (
                    <span
                      aria-hidden
                      className="absolute inset-0 -m-1.5 rounded-full ring-2 ring-primary/40"
                      style={{ animation: "stepperRing 2s ease-out infinite" }}
                    />
                  )}
                  {/* Inner shine */}
                  {(isCompleted || isActive) && (
                    <span
                      aria-hidden
                      className="absolute inset-0 overflow-hidden rounded-full"
                    >
                      <span className="absolute -inset-1 block bg-gradient-to-tr from-white/0 via-white/40 to-white/0 opacity-60 mix-blend-overlay" />
                    </span>
                  )}

                  {/* Number */}
                  <span
                    ref={(el) => {
                      numberRefs.current[index] = el;
                    }}
                    className={`relative z-10 ${isCompleted ? "hidden" : "block"}`}
                  >
                    {index + 1}
                  </span>

                  {/* Check */}
                  <span
                    ref={(el) => {
                      checkRefs.current[index] = el;
                    }}
                    className={`relative z-10 ${isCompleted ? "block" : "hidden"}`}
                  >
                    <CheckIcon className="h-6 w-6" />
                  </span>
                </button>

                <div
                  ref={(el) => {
                    labelRefs.current[index] = el;
                  }}
                  className="mt-4 text-center"
                >
                  <div
                    className={`text-sm font-semibold transition-colors duration-300 ${
                      isActive
                        ? "text-primary"
                        : index <= currentStep
                          ? "text-dark-2 dark:text-white"
                          : "text-gray-4"
                    }`}
                  >
                    {step.title}
                  </div>
                  {step.description && (
                    <div className="mt-1 max-w-[140px] text-xs text-gray-5">
                      {step.description}
                    </div>
                  )}
                </div>
              </div>
            );
          })}
        </div>
      </div>

      {/* Step content */}
      <div
        ref={contentRef}
        key={currentStep}
        className="relative rounded-xl"
      >
        {steps[currentStep].content}
      </div>

      {/* Nav buttons */}
      <div className="mt-8 flex items-center justify-between">
        <button
          ref={prevBtnRef}
          onClick={prevStep}
          onMouseEnter={() => handleButtonHover(prevBtnRef.current, true)}
          onMouseLeave={() => handleButtonHover(prevBtnRef.current, false)}
          disabled={currentStep === 0}
          className={`group relative inline-flex items-center gap-2 overflow-hidden rounded-xl px-6 py-2.5 text-sm font-semibold transition-all ${
            currentStep === 0
              ? "cursor-not-allowed bg-gray-1 text-gray-4 dark:bg-dark-3"
              : "bg-gray-2 text-dark-2 hover:bg-gray-3 dark:bg-dark-3 dark:text-white"
          }`}
        >
          <svg
            className="h-4 w-4 transition-transform group-hover:-translate-x-0.5"
            fill="none"
            viewBox="0 0 24 24"
            stroke="currentColor"
            strokeWidth={2.5}
          >
            <path
              strokeLinecap="round"
              strokeLinejoin="round"
              d="M15 19l-7-7 7-7"
            />
          </svg>
          Previous
        </button>

        {/* Step counter */}
        <div className="hidden text-xs font-medium text-gray-5 sm:block">
          <span className="text-primary">{currentStep + 1}</span>
          <span className="mx-1">/</span>
          <span>{steps.length}</span>
        </div>

        <button
          ref={nextBtnRef}
          onClick={nextStep}
          onMouseEnter={() => handleButtonHover(nextBtnRef.current, true)}
          onMouseLeave={() => handleButtonHover(nextBtnRef.current, false)}
          disabled={isSubmitting || nextDisabled}
          className={`group relative inline-flex items-center gap-2 overflow-hidden rounded-xl px-6 py-2.5 text-sm font-semibold text-white transition-all ${
            isSubmitting || nextDisabled
              ? "cursor-not-allowed bg-gray-4"
              : "bg-gradient-to-r from-primary via-blue to-primary bg-[length:200%_100%] shadow-lg shadow-primary/30 hover:shadow-primary/50"
          }`}
          style={
            !isSubmitting && !nextDisabled
              ? { animation: "stepperShimmer 3s linear infinite" }
              : undefined
          }
        >
          {/* Glow halo for submit */}
          {isLastStep && !isSubmitting && !nextDisabled && (
            <span
              ref={submitGlowRef}
              aria-hidden
              className="pointer-events-none absolute inset-0 -z-10 rounded-xl bg-primary/40 opacity-40 blur-xl"
            />
          )}

          {isSubmitting ? (
            <>
              <svg
                className="h-4 w-4 animate-spin"
                viewBox="0 0 24 24"
                fill="none"
              >
                <circle
                  cx="12"
                  cy="12"
                  r="10"
                  stroke="currentColor"
                  strokeOpacity="0.25"
                  strokeWidth="4"
                />
                <path
                  d="M22 12a10 10 0 0 1-10 10"
                  stroke="currentColor"
                  strokeWidth="4"
                  strokeLinecap="round"
                />
              </svg>
              Submitting...
            </>
          ) : (
            <>
              {isLastStep ? "Submit" : "Next"}
              <svg
                className="h-4 w-4 transition-transform group-hover:translate-x-1"
                fill="none"
                viewBox="0 0 24 24"
                stroke="currentColor"
                strokeWidth={2.5}
              >
                <path
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  d={isLastStep ? "M5 13l4 4L19 7" : "M9 5l7 7-7 7"}
                />
              </svg>
            </>
          )}
        </button>
      </div>

      {/* Local keyframes (background shimmer + ring pulse) */}
      <style jsx>{`
        @keyframes stepperShimmer {
          0% {
            background-position: 0% 50%;
          }
          100% {
            background-position: 200% 50%;
          }
        }
        @keyframes stepperRing {
          0% {
            transform: scale(1);
            opacity: 0.8;
          }
          70% {
            transform: scale(1.45);
            opacity: 0;
          }
          100% {
            transform: scale(1.45);
            opacity: 0;
          }
        }
      `}</style>
    </div>
  );
};

export default Stepper;
