// src/components/frontend/MenuRenderer/index.tsx

'use client';

import { useState, useRef, useCallback, memo } from 'react';
import Link from 'next/link';
import * as motion from 'framer-motion/m';
import { AnimatePresence } from 'framer-motion';
import { ChevronDown, ArrowRight } from 'lucide-react';
import { getMenuItemUrl } from '@/lib/menu/getMenuItemUrl';

// ─── Types ────────────────────────────────────────────────────────────────────

export interface MenuItem {
  id: string;
  parent_id: string | null;
  type: 'page' | 'category' | 'product' | 'custom' | 'post';
  reference_id: string | null;
  url: string | null;
  target: '_self' | '_blank';
  icon: string | null;
  css_class: string | null;
  display_type: 'default' | 'dropdown' | 'mega';
  mega_columns: number | null;
  mega_style: 'default' | 'cards' | 'grid' | 'list';
  label: string;
  title_attr: string | null;
  description: string | null;
  children: MenuItem[];
  sort_order?: number;
}

interface MenuRendererProps {
  items: MenuItem[];
  className?: string;
}

// ─── Constants ────────────────────────────────────────────────────────────────

// ⚠️ Tailwind JIT can't see dynamically-built class strings like `grid-cols-${n}`.
// Must use a static lookup map so the classes actually exist in the compiled CSS.
const GRID_COLS: Record<number, string> = {
  1: 'grid-cols-1',
  2: 'grid-cols-2',
  3: 'grid-cols-3',
  4: 'grid-cols-4',
};

const CLOSE_DELAY = 150; // ms — small delay so moving mouse from button -> panel doesn't flicker-close

const dropdownAnim = {
  initial: { opacity: 0, y: 8, scale: 0.98 },
  animate: { opacity: 1, y: 0, scale: 1 },
  exit: { opacity: 0, y: 8, scale: 0.98 },
  transition: { duration: 0.16, ease: 'easeOut' as const },
};

// ─── Helpers ──────────────────────────────────────────────────────────────────

function getItemUrl(item: MenuItem): string {
  return getMenuItemUrl(item);
}

/**
 * Controlled hover-open state with a small close delay.
 * Replaces pure CSS `group-hover`, which is what caused the
 * unpredictable "opens without hovering / stuck open" bug.
 */
function useHoverOpen() {
  const [isOpen, setIsOpen] = useState(false);
  const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  const open = useCallback(() => {
    if (timeoutRef.current) clearTimeout(timeoutRef.current);
    setIsOpen(true);
  }, []);

  const close = useCallback(() => {
    if (timeoutRef.current) clearTimeout(timeoutRef.current);
    timeoutRef.current = setTimeout(() => setIsOpen(false), CLOSE_DELAY);
  }, []);

  return { isOpen, open, close };
}

// ─── Mega Menu Grid ──────────────────────────────────────────────────────────

const MegaMenuGrid = memo(function MegaMenuGrid({
  items,
  columns = 3,
  style = 'default',
  parentUrl,
  parentLabel,
}: {
  items: MenuItem[];
  columns?: number;
  style?: string;
  parentUrl: string;
  parentLabel: string;
}) {
  const colClass = GRID_COLS[Math.min(Math.max(columns, 1), 4)] ?? GRID_COLS[3];
  const width = style === 'list' ? 'w-[640px]' : 'w-[860px]';

  return (
    <motion.div
      {...dropdownAnim}
      className={`absolute top-full left-1/2 -translate-x-1/2 mt-3 ${width} max-w-[92vw] rounded-2xl border border-black/5 bg-white/95 backdrop-blur-xl shadow-2xl ring-1 ring-black/5 z-50 overflow-hidden`}
    >
      {/* accent top bar */}
      <div className="h-1 w-full bg-gradient-primary" />

      <div className="p-6">
        <div className={`grid ${colClass} gap-5`}>
          {items.map((item) => (
            <div
              key={item.id}
              className="group/card rounded-xl p-4 -m-1 hover:bg-gray-50 transition-colors duration-200"
            >
              <Link href={getItemUrl(item)} target={item.target || '_self'} className="block">
                <span className="block font-semibold text-gray-800 group-hover/card:text-primary transition-colors">
                  {item.label}
                </span>
                {item.description && (
                  <span className="block text-xs text-gray-500 mt-0.5 leading-snug">{item.description}</span>
                )}
              </Link>

              {item.children && item.children.length > 0 && (
                <ul className="mt-3 space-y-1.5">
                  {item.children.map((child) => (
                    <li key={child.id}>
                      <Link
                        href={getItemUrl(child)}
                        target={child.target || '_self'}
                        className="text-sm text-gray-500 hover:text-primary hover:translate-x-0.5 transition-all duration-150 inline-block"
                      >
                        {child.label}
                      </Link>
                    </li>
                  ))}
                </ul>
              )}
            </div>
          ))}
        </div>
      </div>

      {/* footer CTA */}
      <div className="border-t border-gray-100 bg-gray-50/60 px-6 py-3">
        <Link
          href={parentUrl}
          className="inline-flex items-center gap-1.5 text-sm font-semibold text-primary hover:gap-2.5 transition-all duration-200"
        >
          Explore all {parentLabel}
          <ArrowRight size={14} />
        </Link>
      </div>
    </motion.div>
  );
});

// ─── Dropdown Menu (simple, with nested support) ─────────────────────────────

const DropdownMenu = memo(function DropdownMenu({ items }: { items: MenuItem[] }) {
  return (
    <motion.div
      {...dropdownAnim}
      className="absolute top-full left-0 mt-3 min-w-55 max-w-75 rounded-xl border border-black/5 bg-white/95 backdrop-blur-xl shadow-2xl ring-1 ring-black/5 z-50 py-2 overflow-hidden"
    >
      {items.map((item) => (
        <DropdownRow key={item.id} item={item} />
      ))}
    </motion.div>
  );
});

const DropdownRow = memo(function DropdownRow({ item }: { item: MenuItem }) {
  const hasChildren = item.children && item.children.length > 0;
  const { isOpen, open, close } = useHoverOpen();

  return (
    <div className="relative" onMouseEnter={open} onMouseLeave={close}>
      <Link
        href={getItemUrl(item)}
        target={item.target || '_self'}
        className="flex items-center justify-between gap-3 px-4 py-2.5 text-sm font-medium text-gray-700 hover:bg-primary/5 hover:text-primary transition-colors duration-150 whitespace-nowrap"
      >
        <span>{item.label}</span>
        {hasChildren && <ChevronDown size={13} className="-rotate-90 text-gray-400 shrink-0" />}
      </Link>

      <AnimatePresence>
        {hasChildren && isOpen && (
          <motion.div
            {...dropdownAnim}
            className="absolute left-full top-0 ml-1 min-w-50 max-w-70 rounded-xl border border-black/5 bg-white/95 backdrop-blur-xl shadow-2xl ring-1 ring-black/5 z-50 py-2"
          >
            {item.children.map((child) => (
              <Link
                key={child.id}
                href={getItemUrl(child)}
                target={child.target || '_self'}
                className="block px-4 py-2 text-sm text-gray-600 hover:bg-primary/5 hover:text-primary transition-colors duration-150 whitespace-nowrap"
              >
                {child.label}
              </Link>
            ))}
          </motion.div>
        )}
      </AnimatePresence>
    </div>
  );
});

// ─── Top-level Menu Item ──────────────────────────────────────────────────────

const MenuItemRenderer = memo(function MenuItemRenderer({ item }: { item: MenuItem }) {
  const hasChildren = item.children && item.children.length > 0;
  const isMega = item.display_type === 'mega' || (item.children && item.children.length > 3);
  const url = getItemUrl(item);
  const { isOpen, open, close } = useHoverOpen();

  if (!hasChildren) {
    return (
      <Link
        href={url}
        target={item.target || '_self'}
        className="relative font-semibold text-gray-700 hover:text-primary transition-colors duration-200 py-2 after:content-[''] after:absolute after:left-0 after:-bottom-0.5 after:h-0.5 after:w-0 after:bg-primary hover:after:w-full after:transition-all after:duration-200"
      >
        {item.label}
      </Link>
    );
  }

  return (
    <div className="relative" onMouseEnter={open} onMouseLeave={close}>
      <button
        className={`flex items-center gap-1 font-semibold py-2 transition-colors duration-200 ${
          isOpen ? 'text-primary' : 'text-gray-700 hover:text-primary'
        }`}
        aria-expanded={isOpen}
      >
        {item.label}
        <ChevronDown
          size={14}
          className={`transition-transform duration-200 ${isOpen ? 'rotate-180' : ''}`}
        />
      </button>

      <AnimatePresence>
        {isOpen &&
          (isMega ? (
            <MegaMenuGrid
              items={item.children}
              columns={item.mega_columns || 3}
              style={item.mega_style || 'default'}
              parentUrl={url}
              parentLabel={item.label}
            />
          ) : (
            <DropdownMenu items={item.children} />
          ))}
      </AnimatePresence>
    </div>
  );
});

// ─── Main Renderer ───────────────────────────────────────────────────────────

export function MenuRenderer({ items, className = '' }: MenuRendererProps) {
  if (!items || items.length === 0) return null;

  return (
    <ul className={`flex items-center gap-7 list-none m-0 p-0 ${className}`}>
      {items.map((item) => (
        <li key={item.id} className="relative">
          <MenuItemRenderer item={item} />
        </li>
      ))}
    </ul>
  );
}