import { useState, useCallback, useMemo } from 'react';
import { MoreHorizontal } from 'lucide-react';
import { useQueryClient } from '@tanstack/react-query';

import { EmojiPicker, type EmojiSelection } from '@/components/EmojiPicker';
import { isCustomEmoji } from '@/lib/customEmoji';
import { useNostrPublish } from '@/hooks/useNostrPublish';
import { useCurrentUser } from '@/hooks/useCurrentUser';
import { useEmojiUsage } from '@/hooks/useEmojiUsage';
import { useCustomEmojis } from '@/hooks/useCustomEmojis';
import { useFeedSettings } from '@/hooks/useFeedSettings';
import { cn } from '@/lib/utils';
import type { EventStats } from '@/hooks/useTrending';
import type { ResolvedEmoji } from '@/lib/customEmoji';

interface QuickReactMenuProps {
  /** The event ID being reacted to. */
  eventId: string;
  /** The pubkey of the event author. */
  eventPubkey: string;
  /** The kind number of the event being reacted to. */
  eventKind: number;
  /** Called after an emoji is selected so the parent can close the popover. */
  onClose?: () => void;
  /** Called when the full picker is opened/closed so the parent can lock the popover open. */
  onExpandChange?: (expanded: boolean) => void;
  /**
   * Optional custom handler called when an emoji is selected.
   * When provided, this replaces the default kind 7 publish behavior.
   * The optional second argument is an emoji tag `['emoji', shortcode, url]` for custom emojis.
   */
  onReact?: (emoji: string, emojiTag?: string[]) => void;
  /** Optional extra class names. */
  className?: string;
}

export function QuickReactMenu({
  eventId,
  eventPubkey,
  eventKind,
  onClose,
  onExpandChange,
  onReact,
  className,
}: QuickReactMenuProps) {
  const { user } = useCurrentUser();
  const { mutate: publishEvent } = useNostrPublish();
  const queryClient = useQueryClient();
  const { trackEmojiUsage, getTopEmojis } = useEmojiUsage();
  const { feedSettings } = useFeedSettings();
  const { emojis: allCustomEmojis } = useCustomEmojis();
  const customEmojisEnabled = feedSettings.showCustomEmojis !== false;
  const customEmojis = useMemo(() => customEmojisEnabled ? allCustomEmojis : [], [customEmojisEnabled, allCustomEmojis]);

  const [showFullPicker, setShowFullPicker] = useState(false);
  const [selectedEmoji, setSelectedEmoji] = useState<string | null>(null);

  // Build a lookup map from shortcode -> url for custom emojis
  const customEmojiMap = useMemo(() => {
    const map = new Map<string, string>();
    for (const e of customEmojis) {
      map.set(e.shortcode, e.url);
    }
    return map;
  }, [customEmojis]);

  // Get user's most-used emojis (or defaults), filtering out
  // custom emoji shortcodes that are no longer in the user's collection
  const quickEmojis = useMemo(() => {
    const top = getTopEmojis(8);
    return top
      .filter((emoji) => {
        if (!isCustomEmoji(emoji)) return true;
        const shortcode = emoji.slice(1, -1);
        return customEmojiMap.has(shortcode);
      })
      .slice(0, 6);
  }, [getTopEmojis, customEmojiMap]);

  /** Publish a reaction with a native Unicode emoji string. */
  const publishReaction = useCallback((emoji: string, emojiTag?: [string, string, string]) => {
    if (!user) return;

    // Close the entire popover
    onClose?.();

    // Set selected emoji for optimistic update
    setSelectedEmoji(emoji);

    // Track emoji usage (only for native emojis)
    if (!emojiTag) trackEmojiUsage(emoji);

    // If a custom handler is provided, delegate to it
    if (onReact) {
      onReact(emoji, emojiTag);
      return;
    }

    // Optimistic update
    const displayEmoji = (emoji === '+' || emoji === '') ? '👍' : emoji;
    const resolvedEmoji: ResolvedEmoji = emojiTag
      ? { content: displayEmoji, url: emojiTag[2], name: emojiTag[1] }
      : { content: displayEmoji };
    const prevStats = queryClient.getQueryData<EventStats>(['event-stats', eventId]);
    if (prevStats) {
      queryClient.setQueryData<EventStats>(['event-stats', eventId], {
        ...prevStats,
        reactions: prevStats.reactions + 1,
        reactionEmojis: prevStats.reactionEmojis.some((e) => e.content === displayEmoji)
          ? prevStats.reactionEmojis
          : [...prevStats.reactionEmojis, resolvedEmoji],
      });
    }

    queryClient.setQueryData<ResolvedEmoji>(['user-reaction', eventId], resolvedEmoji);

    // Build tags
    const tags: string[][] = [
      ['e', eventId],
      ['p', eventPubkey],
      ['k', String(eventKind)],
    ];
    if (emojiTag) tags.push(emojiTag);

    // Publish kind 7 reaction
    publishEvent(
      {
        kind: 7,
        content: emoji,
        created_at: Math.floor(Date.now() / 1000),
        tags,
      },
      {
        onSuccess: () => {
          setTimeout(() => {
            queryClient.invalidateQueries({ queryKey: ['event-stats', eventId] });
            queryClient.invalidateQueries({ queryKey: ['event-interactions', eventId] });
          }, 3000);
        },
        onError: () => {
          setSelectedEmoji(null);
          if (prevStats) {
            queryClient.setQueryData<EventStats>(['event-stats', eventId], prevStats);
          }
          queryClient.removeQueries({ queryKey: ['user-reaction', eventId] });
        },
      },
    );
  }, [user, eventId, eventPubkey, eventKind, onReact, publishEvent, queryClient, trackEmojiUsage, onClose]);

  /** Handle selection from the quick buttons (native or custom emoji). */
  const handleQuickSelect = useCallback((emoji: string) => {
    if (isCustomEmoji(emoji)) {
      const shortcode = emoji.slice(1, -1);
      const url = customEmojiMap.get(shortcode);
      if (url) {
        publishReaction(emoji, ['emoji', shortcode, url]);
        return;
      }
    }
    publishReaction(emoji);
  }, [publishReaction, customEmojiMap]);

  /** Handle selection from the full EmojiPicker (native or custom). */
  const handlePickerSelect = useCallback((selection: EmojiSelection) => {
    if (selection.type === 'native') {
      publishReaction(selection.emoji);
    } else {
      // Custom NIP-30 emoji — content is :shortcode:, with emoji tag
      publishReaction(
        `:${selection.shortcode}:`,
        ['emoji', selection.shortcode, selection.url],
      );
    }
  }, [publishReaction]);

  if (!user) return null;

  if (showFullPicker) {
    return (
      <div
        className={cn('rounded-xl shadow-xl overflow-hidden', className)}
        onClick={(e) => e.stopPropagation()}
      >
        <EmojiPicker customEmojis={customEmojis} onSelect={handlePickerSelect} />
      </div>
    );
  }

  return (
    <div
      className={cn(
        'inline-flex items-center gap-1 p-1.5 rounded-full bg-popover border border-border shadow-lg',
        className,
      )}
      onClick={(e) => e.stopPropagation()}
    >
      {/* Quick emoji buttons */}
      {quickEmojis.map((emoji) => {
        const isCustom = isCustomEmoji(emoji);
        const shortcode = isCustom ? emoji.slice(1, -1) : undefined;
        const customUrl = shortcode ? customEmojiMap.get(shortcode) : undefined;

        return (
          <button
            key={emoji}
            onClick={() => handleQuickSelect(emoji)}
            className={cn(
              'flex items-center justify-center size-9 rounded-full text-xl transition-all focus:outline-none hover:bg-secondary hover:scale-110 active:scale-95',
              selectedEmoji === emoji && 'bg-secondary scale-110',
            )}
            title={`React with ${isCustom ? shortcode : emoji}`}
          >
            {customUrl ? (
              <img
                src={customUrl}
                alt={emoji}
                className="size-6 object-contain"
                loading="lazy"
                decoding="async"
              />
            ) : (
              emoji
            )}
          </button>
        );
      })}

      {/* More button to show full picker */}
      <button
        onClick={() => {
          setShowFullPicker(true);
          onExpandChange?.(true);
        }}
        className="flex items-center justify-center size-9 rounded-full text-muted-foreground transition-all focus:outline-none hover:bg-secondary hover:text-foreground hover:scale-110 active:scale-95"
        title="More reactions"
      >
        <MoreHorizontal className="size-5" />
      </button>
    </div>
  );
}
