"use client";

import { useState, useEffect } from "react";
import { toast } from "sonner";
import { useTranslations } from "next-intl";

const REACTIONS: Record<string, string> = {
  like: "👍",
  love: "❤️",
  laugh: "😂",
  wow: "😮",
  sad: "😢",
  fire: "🔥",
};

type Props = {
  recipeId: string;
  commentId: string;
  initialCounts?: Record<string, number>;
  initialUserReactions?: string[];
};

export function CommentReactions({ recipeId, commentId, initialCounts = {}, initialUserReactions = [] }: Props) {
  const t = useTranslations("social");
  const [counts, setCounts] = useState<Record<string, number>>(initialCounts);
  const [userReactions, setUserReactions] = useState<string[]>(initialUserReactions);
  const [pending, setPending] = useState<string | null>(null);

  useEffect(() => {
    let cancelled = false;
    fetch(`/api/v1/recipes/${recipeId}/comments/${commentId}/reactions`)
      .then((res) => (res.ok ? res.json() : null))
      .then((data: { counts: Record<string, number>; userReactions: string[] } | null) => {
        if (!data || cancelled) return;
        setCounts(data.counts);
        setUserReactions(data.userReactions);
      })
      .catch(() => {});
    return () => { cancelled = true; };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [recipeId, commentId]);

  async function toggle(type: string) {
    if (pending) return;
    setPending(type);

    // Optimistic update
    const hasReacted = userReactions.includes(type);
    setUserReactions((prev) =>
      hasReacted ? prev.filter((r) => r !== type) : [...prev, type],
    );
    setCounts((prev) => ({
      ...prev,
      [type]: Math.max(0, (prev[type] ?? 0) + (hasReacted ? -1 : 1)),
    }));

    try {
      const res = await fetch(`/api/v1/recipes/${recipeId}/comments/${commentId}/reactions`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ type }),
      });

      if (!res.ok) {
        // Revert optimistic update
        setUserReactions((prev) =>
          hasReacted ? [...prev, type] : prev.filter((r) => r !== type),
        );
        setCounts((prev) => ({
          ...prev,
          [type]: Math.max(0, (prev[type] ?? 0) + (hasReacted ? 1 : -1)),
        }));
        if (res.status === 401) {
          toast.error(t("signInToReact"));
        } else {
          toast.error(t("reactionFailed"));
        }
        return;
      }

      const data = await res.json() as { counts: Record<string, number>; added: boolean };
      setCounts(data.counts);
      setUserReactions((prev) => {
        if (data.added && !prev.includes(type)) return [...prev, type];
        if (!data.added && prev.includes(type)) return prev.filter((r) => r !== type);
        return prev;
      });
    } catch {
      // Revert on network error
      setUserReactions((prev) =>
        hasReacted ? [...prev, type] : prev.filter((r) => r !== type),
      );
      setCounts((prev) => ({
        ...prev,
        [type]: Math.max(0, (prev[type] ?? 0) + (hasReacted ? 1 : -1)),
      }));
      toast.error(t("reactionFailed"));
    } finally {
      setPending(null);
    }
  }

  return (
    <div className="flex flex-wrap gap-1">
      {Object.entries(REACTIONS).map(([type, emoji]) => {
        const reacted = userReactions.includes(type);
        const cnt = counts[type] ?? 0;
        return (
          <button
            key={type}
            onClick={() => void toggle(type)}
            disabled={pending === type}
            className={[
              "inline-flex items-center gap-0.5 rounded-full border px-2 py-0.5 text-xs transition-colors",
              reacted
                ? "border-primary bg-primary/10 text-primary"
                : "border-border bg-transparent text-muted-foreground hover:border-primary/50 hover:text-foreground",
              pending === type ? "opacity-60 cursor-not-allowed" : "cursor-pointer",
            ].join(" ")}
            aria-label={reacted ? t("removeReaction", { type }) : t("addReaction", { type })}
            aria-pressed={reacted}
          >
            <span>{emoji}</span>
            {cnt > 0 && <span>{cnt}</span>}
          </button>
        );
      })}
    </div>
  );
}
