import { useMemo, useRef, useState } from "react";
import type { CSSProperties } from "react";
import { useNavigate } from "react-router-dom";
import { useKeenSlider } from "keen-slider/react";
import type { KeenSliderInstance, KeenSliderPlugin } from "keen-slider/react";
import "keen-slider/keen-slider.min.css";
import "./HomePageCarousel.css";
import { usePageTracking } from "../../hooks/usePageTracking";
import { topicFeedConfig } from "../../config/topicFeedConfig";
import {
  BookOpen,
  NotebookPen,
  Users,
  Palette,
  Droplets,
  Dumbbell,
  Sun,
  Newspaper,
  PartyPopper,
} from "lucide-react";
import type { LucideIcon } from "lucide-react";
import takhtesiyahImage from "../../assets/card-images/takhtesiyah.jpg";
import nimkatImage from "../../assets/card-images/nimkat.jpg";
import daftarcheyadashtImage from "../../assets/card-images/daftarcheyadasht.jpg";
import divarehayatImage from "../../assets/card-images/divarehayat.jpg";
import abkhoriImage from "../../assets/card-images/abkhori.jpg";
import zangvarzshImage from "../../assets/card-images/zangvarzsh.jpg";
import semahtatiliImage from "../../assets/card-images/semahtatili.jpg";
import roznamedivariImage from "../../assets/card-images/roznamedivari.jpg";
import zangtafrihJpgImage from "../../assets/card-images/zangtafrih.jpg";
import takhtesiyahOverlayImage from "../../assets/card-overlays/takhtesiyah-overlay.png";
import nimkatOverlayImage from "../../assets/card-overlays/nimkat-overlay.png";
import daftarcheyadashtOverlayImage from "../../assets/card-overlays/daftarcheyadasht-overlay.png";
import divarehayatOverlayImage from "../../assets/card-overlays/divarehayat-overlay.png";
import abkhoriOverlayImage from "../../assets/card-overlays/abkhori-overlay.png";
import zangvarzshOverlayImage from "../../assets/card-overlays/zangvarzsh-overlay.png";
import semahtatiliOverlayImage from "../../assets/card-overlays/semahtatili-overlay.png";
import roznamedivariOverlayImage from "../../assets/card-overlays/roznamedivari-overlay.png";
import zangtafrihOverlayImage from "../../assets/card-overlays/zangtafrih-overlay.png";
import sampleOverlayImage from "../../assets/card-overlays/sample-overlay.png";

const lockedTopics = new Set(["7"]);

const topicImages: Record<string, string> = {
  "1": takhtesiyahImage,
  "2": nimkatImage,
  "3": daftarcheyadashtImage,
  "4": divarehayatImage,
  "5": abkhoriImage,
  "6": zangvarzshImage,
  "7": semahtatiliImage,
  "8": roznamedivariImage,
  "9": zangtafrihJpgImage,
};

const topicIcons: Record<string, LucideIcon> = {
  "1": BookOpen,
  "2": Users,
  "3": NotebookPen,
  "4": Palette,
  "5": Droplets,
  "6": Dumbbell,
  "7": Sun,
  "8": Newspaper,
  "9": PartyPopper,
};

const topicOverlayImages: Record<string, string> = {
  "1": takhtesiyahOverlayImage,
  "2": nimkatOverlayImage,
  "3": daftarcheyadashtOverlayImage,
  "4": divarehayatOverlayImage,
  "5": abkhoriOverlayImage,
  "6": zangvarzshOverlayImage,
  "7": semahtatiliOverlayImage,
  "8": roznamedivariOverlayImage,
  "9": zangtafrihOverlayImage,
};

const carousel: KeenSliderPlugin = (slider: KeenSliderInstance) => {
  const z = 240;
  const visibleAngle = 80;
  const centerBandDeg = 12;
  const smoothFactor = 0.22;
  const slideAnimState = new WeakMap<HTMLElement, { scale: number; tilt: number }>();
  let previousDeg = 0;
  let hasPreviousDeg = false;
  let rotationDirection = 1;

  function normalizeAngle(angle: number) {
    return ((angle + 180) % 360 + 360) % 360 - 180;
  }

  function updateSlideVisibility() {
    const details = slider.track.details;
    if (!details) return;

    const currentDeg = 360 * details.progress;
    const stepDeg = 360 / slider.slides.length;
    if (hasPreviousDeg) {
      const deltaDeg = normalizeAngle(currentDeg - previousDeg);
      if (Math.abs(deltaDeg) > 0.02) {
        rotationDirection = deltaDeg > 0 ? 1 : -1;
      }
    }
    previousDeg = currentDeg;
    hasPreviousDeg = true;

    const predictedDeg = currentDeg + rotationDirection * (stepDeg * 0.5);
    let activeIndex = 0;
    let activeDistance = Number.POSITIVE_INFINITY;

    slider.slides.forEach((element, idx) => {
      const baseDeg = stepDeg * idx;
      const relativeDeg = normalizeAngle(baseDeg - currentDeg);
      const absRelativeDeg = Math.abs(relativeDeg);
      const isVisible = absRelativeDeg <= visibleAngle;
      const slide = element as HTMLElement;
      const sideTiltMaxDeg = -22;

      const focus =
        absRelativeDeg <= centerBandDeg
          ? 1
          : Math.max(0, 1 - (absRelativeDeg - centerBandDeg) / (visibleAngle - centerBandDeg));
      const easedFocus = focus * focus * (3 - 2 * focus);
      const predictedRelativeDeg = normalizeAngle(baseDeg - predictedDeg);
      const predictedDistance = Math.abs(predictedRelativeDeg);
      if (predictedDistance < activeDistance) {
        activeDistance = predictedDistance;
        activeIndex = idx;
      }
      const targetScale = 1 + easedFocus * 0.3;
      const targetTilt = 23 + sideTiltMaxDeg;
      const overlayRaw = Math.max(0, (easedFocus - 0.35) / 0.65);
      const overlayProgress = overlayRaw * overlayRaw * (3 - 2 * overlayRaw);

      const prev = slideAnimState.get(slide) ?? { scale: targetScale, tilt: targetTilt };
      const nextScale = prev.scale + (targetScale - prev.scale) * smoothFactor;
      const nextTilt = prev.tilt + (targetTilt - prev.tilt) * smoothFactor;
      slideAnimState.set(slide, { scale: nextScale, tilt: nextTilt });

      slide.style.transform = `rotateY(${baseDeg}deg) translateZ(${z}px) rotateX(${nextTilt.toFixed(2)}deg) scale(${nextScale.toFixed(3)})`;
      slide.style.setProperty("--ui-counter-tilt", `${(-nextTilt).toFixed(2)}deg`);
      slide.style.opacity = isVisible ? "1" : "0";
      slide.style.pointerEvents = isVisible ? "auto" : "none";
    });

    const activeBaseDeg = stepDeg * activeIndex;
    const activeRelativeDeg = normalizeAngle(activeBaseDeg - currentDeg);
    const activeFocusRaw = Math.max(0, 1 - Math.abs(activeRelativeDeg) / (visibleAngle * 0.7));
    const activeFocusEased = activeFocusRaw * activeFocusRaw * (3 - 2 * activeFocusRaw);

    const container = slider.container as HTMLElement;
    container.style.setProperty("--active-overlay-index", `${activeIndex}`);
    container.style.setProperty("--active-overlay-progress", `${activeFocusEased.toFixed(3)}`);
  }

  function rotate() {
    const deg = 360 * slider.track.details.progress;
    slider.container.style.transform = `translateZ(-${z}px) rotateX(-23deg) rotateY(${-deg}deg)`;
    updateSlideVisibility();
  }

  slider.on("created", rotate);
  slider.on("detailsChanged", rotate);
};

export function HomePage() {
  const navigate = useNavigate();
  usePageTracking("صفحه اصلی");
  const [overlayFromIndex, setOverlayFromIndex] = useState(0);
  const [overlayToIndex, setOverlayToIndex] = useState(0);
  const [overlayProgress, setOverlayProgress] = useState(0);
  const displayedOverlayIndexRef = useRef(0);
  const overlayFromIndexRef = useRef(0);
  const overlayToIndexRef = useRef(0);
  const overlayProgressRef = useRef(0);
  const transitionAnchorVirtualRef = useRef(0);
  const virtualPositionRef = useRef(0);
  const previousProgressRef = useRef(0);
  const transitionDirectionRef = useRef(1);

  const clamp01 = (value: number) => Math.max(0, Math.min(1, value));
  const wrapIndex = (index: number, total: number) => {
    if (total <= 0) return 0;
    return ((index % total) + total) % total;
  };
  const normalizeProgressDelta = (value: number) => {
    if (value > 0.5) return value - 1;
    if (value < -0.5) return value + 1;
    return value;
  };
  const smoothstep = (value: number) => value * value * (3 - 2 * value);

  const activityCards = Object.entries(topicFeedConfig)
    .sort(([a], [b]) => Number(a) - Number(b))
    .map(([id, topic]) => ({
      id: Number(id),
      topicId: id,
      title: topic.title,
      subtitle: topic.description,
      Icon: topicIcons[id] || Users,
      image: topicImages[id],
      overlayImage: topicOverlayImages[id] || sampleOverlayImage,
      disabled: lockedTopics.has(id),
      targetPath: topic.hasFeed ? `/feed/${id}` : `/challenges/${id}`,
    }));

  const [sliderRef] = useKeenSlider<HTMLDivElement>(
    {
      loop: true,
      selector: ".carousel__item",
      renderMode: "custom",
      mode: "free-snap",
      created(slider) {
        const details = slider.track.details;
        if (!details) return;
        const total = slider.slides.length;
        const current = wrapIndex(details.rel, total);
        displayedOverlayIndexRef.current = current;
        overlayFromIndexRef.current = current;
        overlayToIndexRef.current = current;
        overlayProgressRef.current = 0;
        virtualPositionRef.current = details.progress * total;
        transitionAnchorVirtualRef.current = virtualPositionRef.current;
        previousProgressRef.current = details.progress;
      },
      dragStarted(slider) {
        const details = slider.track.details;
        if (!details) return;
        const total = slider.slides.length || 1;
        virtualPositionRef.current = details.progress * total;
        transitionAnchorVirtualRef.current = virtualPositionRef.current;
        previousProgressRef.current = details.progress;
        slider.container.setAttribute("data-drag-start-abs", String(details.abs));
      },
      dragEnded(slider) {
        const details = slider.track.details;
        if (!details) return;
        const startAbs = Number.parseFloat(
          slider.container.getAttribute("data-drag-start-abs") || `${details.abs}`,
        );
        const delta = details.abs - startAbs;
        if (Math.abs(delta) <= 1.05) return;

        const baseIndex = Math.round(startAbs);
        const targetIndex = baseIndex + (delta > 0 ? 1 : -1);
        slider.moveToIdx(targetIndex, true, {
          duration: 360,
          easing: (t) => 1 - Math.pow(1 - t, 3),
        });
      },
      animationStarted(slider) {
        const details = slider.track.details;
        if (!details) return;
        const total = slider.slides.length || 1;
        virtualPositionRef.current = details.progress * total;
      },
      detailsChanged(slider) {
        const details = slider.track.details;
        if (!details) return;
        const total = slider.slides.length;
        if (!total) return;

        const deltaFromPrev = normalizeProgressDelta(details.progress - previousProgressRef.current);
        virtualPositionRef.current += deltaFromPrev * total;
        const moving = Math.abs(deltaFromPrev) > 0.00035;
        previousProgressRef.current = details.progress;

        if (moving) transitionDirectionRef.current = deltaFromPrev > 0 ? 1 : -1;
        if (!moving && !slider.animator.active) {
          const snappedIndex = wrapIndex(details.rel, total);
          displayedOverlayIndexRef.current = snappedIndex;
          overlayFromIndexRef.current = snappedIndex;
          overlayToIndexRef.current = snappedIndex;
          overlayProgressRef.current = 0;
          transitionAnchorVirtualRef.current = virtualPositionRef.current;
        } else {
          const phaseRaw = virtualPositionRef.current - Math.floor(virtualPositionRef.current);
          const phaseForward = phaseRaw < 0 ? phaseRaw + 1 : phaseRaw;
          const phase =
            transitionDirectionRef.current > 0 ? phaseForward : (1 - phaseForward) % 1;

          const transitionStart = 0;
          const phaseProgress = clamp01((phase - transitionStart) / (1 - transitionStart));
          const syncedProgress =
            phaseProgress <= 0.001 ? 0 : phaseProgress >= 0.999 ? 1 : smoothstep(phaseProgress);

          const fromIndex =
            transitionDirectionRef.current > 0
              ? wrapIndex(Math.floor(virtualPositionRef.current), total)
              : wrapIndex(Math.ceil(virtualPositionRef.current), total);
          const toIndex = wrapIndex(fromIndex + transitionDirectionRef.current, total);

          overlayFromIndexRef.current = fromIndex;
          overlayToIndexRef.current = toIndex;
          overlayProgressRef.current = syncedProgress;
          displayedOverlayIndexRef.current = syncedProgress >= 0.999 ? toIndex : fromIndex;
        }

        const container = slider.container as HTMLElement;
        container.style.setProperty("--active-overlay-index", String(overlayToIndexRef.current));
        container.style.setProperty(
          "--active-overlay-progress",
          overlayProgressRef.current.toFixed(3),
        );

        setOverlayFromIndex(overlayFromIndexRef.current);
        setOverlayToIndex(overlayToIndexRef.current);
        setOverlayProgress(overlayProgressRef.current);
      },
    },
    [carousel],
  );

  const overlayFromImage = useMemo(
    () => activityCards[overlayFromIndex]?.overlayImage || sampleOverlayImage,
    [activityCards, overlayFromIndex],
  );

  const overlayToImage = useMemo(
    () => activityCards[overlayToIndex]?.overlayImage || sampleOverlayImage,
    [activityCards, overlayToIndex],
  );

  return (
    <div
      className="home-page"
      dir="rtl"
    >
      <div className="home-carousel-wrapper">
        <div className="home-carousel-scene">
          <div
            className="home-carousel-floating-overlay"
            style={
              {
                "--floating-progress": overlayProgress.toFixed(3),
              } as CSSProperties
            }
            aria-hidden="true"
          >
            <img src={overlayFromImage} alt="" className="home-carousel-floating-overlay-image home-carousel-floating-overlay-image--out" />
            <img src={overlayToImage} alt="" className="home-carousel-floating-overlay-image home-carousel-floating-overlay-image--in" />
          </div>
          <div className="home-carousel keen-slider" ref={sliderRef} dir="ltr">
            {activityCards.map((card, idx) => (
              <div key={card.id} className={`carousel__item number-slide${(idx % 6) + 1}`}>
                <button
                  type="button"
                  onClick={() => !card.disabled && navigate(card.targetPath)}
                  disabled={card.disabled}
                  className="carousel__cell"
                  style={{ cursor: card.disabled ? "not-allowed" : "pointer" }}
                  dir="rtl"
                >
                  <span className="home-carousel-icon-badge" aria-hidden="true">
                    <card.Icon size={20} strokeWidth={2} />
                  </span>
                  <div className="home-carousel-text">
                    <span className="home-carousel-label">
                      {card.disabled ? `🔒 ${card.title}` : card.title}
                    </span>
                    <span className="home-carousel-subtitle">{card.subtitle}</span>
                  </div>
                  <img src={card.image} alt={card.title} className="home-carousel-image" loading="eager" />
                </button>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}
