"use client";

import { useCallback, useEffect, useRef, useState } from "react";
import Link from "next/link";
import { Bell } from "lucide-react";

interface NotificationItem {
  id: string;
  body: string;
  link: string | null;
  isRead: boolean;
  sentAt: string;
  poId: string | null;
}

interface Props {
  initialUnreadCount: number;
  initialNotifications: NotificationItem[];
}

function timeAgo(dateStr: string): string {
  const diff = Date.now() - new Date(dateStr).getTime();
  const mins = Math.floor(diff / 60_000);
  if (mins < 1) return "just now";
  if (mins < 60) return `${mins}m ago`;
  const hrs = Math.floor(mins / 60);
  if (hrs < 24) return `${hrs}h ago`;
  return `${Math.floor(hrs / 24)}d ago`;
}

export function NotificationBell({ initialUnreadCount, initialNotifications }: Props) {
  const [open, setOpen] = useState(false);
  const [unreadCount, setUnreadCount] = useState(initialUnreadCount);
  const [notifications, setNotifications] = useState<NotificationItem[]>(initialNotifications);
  const [newArrival, setNewArrival] = useState(false);
  const prevCountRef = useRef(initialUnreadCount);
  const panelRef = useRef<HTMLDivElement>(null);

  // ── Poll for new notifications every 30 s ───────────────────────────────────
  const fetchNotifications = useCallback(async () => {
    try {
      const res = await fetch("/api/notifications", { cache: "no-store" });
      if (!res.ok) return;
      const data: { unreadCount: number; notifications: NotificationItem[] } = await res.json();

      setNotifications(data.notifications);

      if (data.unreadCount > prevCountRef.current) {
        // New notification arrived — flash the bell
        setNewArrival(true);
        setTimeout(() => setNewArrival(false), 3000);
      }
      prevCountRef.current = data.unreadCount;
      setUnreadCount(data.unreadCount);
    } catch {
      // network error — silently ignore
    }
  }, []);

  useEffect(() => {
    const id = setInterval(fetchNotifications, 30_000);
    return () => clearInterval(id);
  }, [fetchNotifications]);

  // ── Close on outside click ──────────────────────────────────────────────────
  useEffect(() => {
    function handleClick(e: MouseEvent) {
      if (panelRef.current && !panelRef.current.contains(e.target as Node)) {
        setOpen(false);
      }
    }
    document.addEventListener("mousedown", handleClick);
    return () => document.removeEventListener("mousedown", handleClick);
  }, []);

  // ── Mark all read when panel opens ─────────────────────────────────────────
  async function handleOpen() {
    const next = !open;
    setOpen(next);
    if (next && unreadCount > 0) {
      setUnreadCount(0);
      prevCountRef.current = 0;
      setNotifications((prev) => prev.map((n) => ({ ...n, isRead: true })));
      await fetch("/api/notifications/read", { method: "PATCH" });
    }
  }

  return (
    <div ref={panelRef} className="relative">
      {/* Bell button */}
      <button
        onClick={handleOpen}
        className={`relative flex items-center justify-center rounded-lg p-2 transition-colors ${
          open
            ? "bg-neutral-100 text-neutral-700"
            : "text-neutral-500 hover:bg-neutral-100 hover:text-neutral-700"
        }`}
        title="Notifications"
        aria-label={`Notifications${unreadCount > 0 ? ` (${unreadCount} unread)` : ""}`}
      >
        <Bell
          className={`h-5 w-5 transition-transform ${newArrival ? "animate-bounce" : ""}`}
        />
        {unreadCount > 0 && (
          <span
            className={`absolute -top-0.5 -right-0.5 flex h-4.5 min-w-[18px] items-center justify-center rounded-full bg-danger px-1 text-[10px] font-bold leading-none text-white ${
              newArrival ? "animate-pulse" : ""
            }`}
          >
            {unreadCount > 99 ? "99+" : unreadCount}
          </span>
        )}
      </button>

      {/* Dropdown panel */}
      {open && (
        <div className="absolute right-0 top-full mt-2 w-80 sm:w-96 max-w-[calc(100vw-1rem)] rounded-xl border border-neutral-200 bg-white shadow-xl z-50 overflow-hidden">
          {/* Header */}
          <div className="flex items-center justify-between border-b border-neutral-100 px-4 py-3">
            <h3 className="text-sm font-semibold text-neutral-900">Notifications</h3>
            {notifications.length > 0 && (
              <button
                onClick={async () => {
                  setNotifications((prev) => prev.map((n) => ({ ...n, isRead: true })));
                  setUnreadCount(0);
                  prevCountRef.current = 0;
                  await fetch("/api/notifications/read", { method: "PATCH" });
                }}
                className="text-xs text-primary-600 hover:text-primary-700 font-medium"
              >
                Mark all read
              </button>
            )}
          </div>

          {/* List */}
          <div className="max-h-[480px] overflow-y-auto divide-y divide-neutral-50">
            {notifications.length === 0 ? (
              <div className="px-4 py-10 text-center text-sm text-neutral-400">
                No notifications yet
              </div>
            ) : (
              notifications.map((n) => {
                const content = (
                  <div
                    className={`flex items-start gap-3 px-4 py-3.5 transition-colors hover:bg-neutral-50 ${
                      !n.isRead ? "bg-primary-50/40" : ""
                    }`}
                  >
                    {/* Unread dot */}
                    <span
                      className={`mt-1.5 h-2 w-2 shrink-0 rounded-full transition-colors ${
                        !n.isRead ? "bg-primary-500" : "bg-transparent"
                      }`}
                    />
                    <div className="flex-1 min-w-0">
                      <p className={`text-sm leading-snug ${!n.isRead ? "font-medium text-neutral-900" : "text-neutral-700"}`}>
                        {n.body}
                      </p>
                      <p className="text-xs text-neutral-400 mt-0.5">{timeAgo(n.sentAt)}</p>
                    </div>
                  </div>
                );

                return n.link ? (
                  <Link
                    key={n.id}
                    href={n.link}
                    onClick={() => setOpen(false)}
                    className="block"
                  >
                    {content}
                  </Link>
                ) : (
                  <div key={n.id}>{content}</div>
                );
              })
            )}
          </div>

          {/* Footer */}
          {notifications.length === 20 && (
            <div className="border-t border-neutral-100 px-4 py-2 text-center">
              <span className="text-xs text-neutral-400">Showing 20 most recent</span>
            </div>
          )}
        </div>
      )}
    </div>
  );
}
