import React from 'react';
import { AnimatePresence, motion, useReducedMotion } from 'framer-motion';
import { Outlet, useLocation, useNavigationType } from 'react-router-dom';

const TAB_SECTIONS = new Set(['home', 'tasks', 'achievements', 'gallery']);

export function getTabKey(pathname: string): string | null {
  const match = pathname.match(/^\/e\/[^/]+(?:\/([^/]+))?$/);
  if (!match) {
    return null;
  }

  const section = match[1];
  if (!section) {
    return 'home';
  }

  return TAB_SECTIONS.has(section) ? section : null;
}

export function getTransitionKind(prevPath: string, nextPath: string): 'tab' | 'stack' {
  const prevTab = getTabKey(prevPath);
  const nextTab = getTabKey(nextPath);

  if (prevTab && nextTab && prevTab !== nextTab) {
    return 'tab';
  }

  return 'stack';
}

export function isTransitionDisabled(pathname: string): boolean {
  if (pathname.startsWith('/share/')) {
    return true;
  }

  return /^\/e\/[^/]+\/upload(?:\/|$)/.test(pathname);
}

export default function RouteTransition({ children }: { children?: React.ReactNode }) {
  const location = useLocation();
  const navigationType = useNavigationType();
  const prefersReducedMotion = useReducedMotion();
  const prevPathRef = React.useRef(location.pathname);
  const prevPath = prevPathRef.current;
  const direction = navigationType === 'POP' ? 'back' : 'forward';
  const kind = getTransitionKind(prevPath, location.pathname);
  const disableTransitions = prefersReducedMotion
    || isTransitionDisabled(prevPath)
    || isTransitionDisabled(location.pathname);

  React.useEffect(() => {
    prevPathRef.current = location.pathname;
  }, [location.pathname]);

  const content = children ?? <Outlet />;

  if (disableTransitions) {
    return <>{content}</>;
  }

  const stackVariants = {
    enter: ({ direction }: { direction: 'forward' | 'back' }) => ({
      x: direction === 'back' ? -28 : 28,
      opacity: 0,
    }),
    center: { x: 0, opacity: 1 },
    exit: ({ direction }: { direction: 'forward' | 'back' }) => ({
      x: direction === 'back' ? 28 : -28,
      opacity: 0,
    }),
  };

  const tabVariants = {
    enter: { opacity: 0, y: 8 },
    center: { opacity: 1, y: 0 },
    exit: { opacity: 0, y: -8 },
  };

  const transition = kind === 'tab'
    ? { duration: 0.22, ease: [0.22, 0.61, 0.36, 1] }
    : { duration: 0.28, ease: [0.25, 0.8, 0.25, 1] };

  return (
    <AnimatePresence initial={false} mode="wait">
      <motion.div
        key={location.pathname}
        custom={{ direction }}
        variants={kind === 'tab' ? tabVariants : stackVariants}
        initial="enter"
        animate="center"
        exit="exit"
        transition={transition as any}
        style={{ willChange: 'transform, opacity' }}
      >
        {content}
      </motion.div>
    </AnimatePresence>
  );
}
