"use client";

import { useEffect, useRef, useState } from "react";
import { useRouter } from "next/navigation";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { Bell, Check, Loader2 } from "lucide-react";
import { notificationApi } from "@/lib/api/client";
import { useAuthStore } from "@/lib/store/auth-store";
import { useTranslation } from "@/lib/hooks/use-translation";
import { cn } from "@/lib/utils/cn";

interface NotificationRow {
  id: string;
  titleHi: string;
  titleEn: string;
  messageHi: string | null;
  messageEn: string | null;
  link: string | null;
  read: boolean;
  createdAt: string;
}

/**
 * In-app notifications.
 *
 * <p>The backend has written notification rows since the first commit and
 * nothing ever displayed them — every review decision, status change and
 * payment claim landed in a table no screen read. Mail is the other half of the
 * same job, but it depends on SMTP being configured and on the recipient
 * reading their inbox; this works regardless, which matters most for the person
 * who has to act on something.
 */
export function NotificationBell() {
  const { isAuthenticated } = useAuthStore();
  const { language } = useTranslation("COMMON");
  const router = useRouter();
  const qc = useQueryClient();
  const [open, setOpen] = useState(false);
  const wrapRef = useRef<HTMLDivElement>(null);

  const countQuery = useQuery({
    queryKey: ["notifications", "unread-count"],
    queryFn: async () => (await notificationApi.unreadCount()).data as { count: number },
    enabled: isAuthenticated,
    // Polled rather than pushed: there is no websocket here, and a payment
    // waiting on an editor should not sit unseen until the next full reload.
    refetchInterval: 60_000,
    refetchOnWindowFocus: true,
  });

  const listQuery = useQuery({
    queryKey: ["notifications", "list"],
    queryFn: async () => (await notificationApi.list()).data as NotificationRow[],
    enabled: isAuthenticated && open,
  });

  const markRead = useMutation({
    mutationFn: (id: string) => notificationApi.markRead(id),
    onSuccess: () => qc.invalidateQueries({ queryKey: ["notifications"] }),
  });

  const markAllRead = useMutation({
    mutationFn: () => notificationApi.markAllRead(),
    onSuccess: () => qc.invalidateQueries({ queryKey: ["notifications"] }),
  });

  // Close on an outside click, so the panel does not sit over the page.
  useEffect(() => {
    if (!open) return;
    const onDown = (e: MouseEvent) => {
      if (wrapRef.current && !wrapRef.current.contains(e.target as Node)) setOpen(false);
    };
    document.addEventListener("mousedown", onDown);
    return () => document.removeEventListener("mousedown", onDown);
  }, [open]);

  if (!isAuthenticated) return null;

  const unread = countQuery.data?.count ?? 0;
  const rows = listQuery.data ?? [];
  const hi = language === "hi";

  return (
    <div className="relative" ref={wrapRef}>
      <button
        onClick={() => setOpen((v) => !v)}
        aria-label={hi ? "सूचनाएँ" : "Notifications"}
        className="relative rounded-md p-2 text-gray-500 transition-colors hover:bg-gray-50 hover:text-indigo-600"
      >
        <Bell className="h-5 w-5" />
        {unread > 0 && (
          <span className="absolute -right-0.5 -top-0.5 flex h-4 min-w-4 items-center justify-center rounded-full bg-red-600 px-1 text-[10px] font-bold text-white">
            {unread > 99 ? "99+" : unread}
          </span>
        )}
      </button>

      {open && (
        <div className="absolute right-0 z-50 mt-2 w-80 overflow-hidden rounded-lg border border-gray-200 bg-white shadow-xl sm:w-96">
          <div className="flex items-center justify-between border-b border-gray-100 px-4 py-2.5">
            <span className="text-sm font-semibold text-gray-900">
              {hi ? "सूचनाएँ" : "Notifications"}
            </span>
            {unread > 0 && (
              <button
                onClick={() => markAllRead.mutate()}
                disabled={markAllRead.isPending}
                className="inline-flex items-center gap-1 text-xs text-indigo-600 hover:underline disabled:opacity-50"
              >
                <Check className="h-3 w-3" />
                {hi ? "सब पढ़े हुए" : "Mark all read"}
              </button>
            )}
          </div>

          <div className="max-h-96 overflow-y-auto">
            {listQuery.isLoading && (
              <div className="py-8 text-center">
                <Loader2 className="mx-auto h-5 w-5 animate-spin text-gray-300" />
              </div>
            )}

            {!listQuery.isLoading && rows.length === 0 && (
              <p className="px-4 py-8 text-center text-sm text-gray-400">
                {hi ? "कोई सूचना नहीं" : "Nothing to show"}
              </p>
            )}

            {rows.map((n) => (
              <button
                key={n.id}
                onClick={() => {
                  if (!n.read) markRead.mutate(n.id);
                  setOpen(false);
                  if (n.link) router.push(n.link);
                }}
                className={cn(
                  "block w-full border-b border-gray-50 px-4 py-3 text-left transition-colors hover:bg-gray-50",
                  !n.read && "bg-indigo-50/40"
                )}
              >
                <div className="flex items-start gap-2">
                  {!n.read && (
                    <span className="mt-1.5 h-1.5 w-1.5 shrink-0 rounded-full bg-indigo-600" />
                  )}
                  <div className={cn("min-w-0", n.read && "pl-3.5")}>
                    <div className="truncate text-sm font-medium text-gray-900">
                      {hi ? n.titleHi : n.titleEn}
                    </div>
                    {(n.messageHi || n.messageEn) && (
                      <div className="mt-0.5 line-clamp-2 text-xs text-gray-500">
                        {hi ? n.messageHi : n.messageEn}
                      </div>
                    )}
                    <div className="mt-1 text-[11px] text-gray-400">
                      {new Date(n.createdAt).toLocaleString("en-IN", {
                        dateStyle: "medium",
                        timeStyle: "short",
                      })}
                    </div>
                  </div>
                </div>
              </button>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}
