"use client";

import { useRef } from "react";
import {
  motion,
  useMotionValue,
  useTransform,
  animate,
  PanInfo,
  MotionValue,
} from "framer-motion";
import RestaurantCard from "./RestaurantCard";
import { Restaurant, SwipeDirection } from "@/types";

const SWIPE_THRESHOLD = 120;
const getExitX = () =>
  typeof window !== "undefined" ? window.innerWidth * 1.5 : 600;
const ROTATION_RANGE = 18;

interface SwipeableCardProps {
  restaurant: Restaurant;
  isTop: boolean;
  onSwipe: (direction: SwipeDirection) => void;
  registerSwipe?: (fn: (direction: SwipeDirection) => void) => void;
  likeCount: number;
}

function SwipeOverlay({ x }: { x: MotionValue<number> }) {
  const likeOpacity = useTransform(x, [0, SWIPE_THRESHOLD], [0, 1]);
  const nopeOpacity = useTransform(x, [-SWIPE_THRESHOLD, 0], [1, 0]);

  return (
    <>
      <motion.div
        className="pointer-events-none absolute inset-0 z-10 flex items-start justify-start rounded-2xl border-4 border-emerald-400 p-6"
        style={{ opacity: likeOpacity }}
      >
        <span className="rounded-lg border-3 border-emerald-400 px-3 py-1 text-2xl font-extrabold tracking-wide text-emerald-400">
          LIKE
        </span>
      </motion.div>
      <motion.div
        className="pointer-events-none absolute inset-0 z-10 flex items-start justify-end rounded-2xl border-4 border-rose-400 p-6"
        style={{ opacity: nopeOpacity }}
      >
        <span className="rounded-lg border-3 border-rose-400 px-3 py-1 text-2xl font-extrabold tracking-wide text-rose-400">
          NOPE
        </span>
      </motion.div>
    </>
  );
}

export default function SwipeableCard({
  restaurant,
  isTop,
  onSwipe,
  registerSwipe,
  likeCount,
}: SwipeableCardProps) {
  const x = useMotionValue(0);
  const rotate = useTransform(x, [-300, 300], [-ROTATION_RANGE, ROTATION_RANGE]);
  const opacity = useTransform(x, [-300, -100, 0, 100, 300], [0.5, 1, 1, 1, 0.5]);

  const isSwiping = useRef(false);

  const flyOut = (direction: SwipeDirection) => {
    if (isSwiping.current) return;
    isSwiping.current = true;
    const exit = getExitX();
    const exitX = direction === "right" ? exit : -exit;
    animate(x, exitX, {
      type: "spring",
      stiffness: 600,
      damping: 40,
      onComplete: () => onSwipe(direction),
    });
  };

  if (registerSwipe) {
    registerSwipe(flyOut);
  }

  const handleDragEnd = (_: unknown, info: PanInfo) => {
    const offsetX = info.offset.x;
    if (offsetX > SWIPE_THRESHOLD) {
      flyOut("right");
    } else if (offsetX < -SWIPE_THRESHOLD) {
      flyOut("left");
    } else {
      animate(x, 0, { type: "spring", stiffness: 500, damping: 30 });
    }
  };

  return (
    <motion.div
      className="absolute inset-0"
      style={{
        x,
        rotate,
        opacity,
        zIndex: isTop ? 10 : 0,
        cursor: isTop ? "grab" : "default",
      }}
      drag={isTop ? "x" : false}
      dragConstraints={{ left: 0, right: 0 }}
      dragElastic={0.9}
      onDragEnd={handleDragEnd}
      whileDrag={{ cursor: "grabbing" }}
      initial={isTop ? { scale: 1 } : { scale: 0.95, y: 16 }}
      animate={isTop ? { scale: 1, y: 0 } : { scale: 0.95, y: 16 }}
      transition={{ type: "spring", stiffness: 300, damping: 25 }}
    >
      <SwipeOverlay x={x} />
      <RestaurantCard restaurant={restaurant} likeCount={likeCount} />
    </motion.div>
  );
}
