"use client";

/**
 * Notification bell — shows unread count badge, dropdown with recent
 * notifications, mark-all-read, and link to /notifications.
 */

import { useCallback, useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { Bell, Check, CheckCheck } from "lucide-react";
import { useBrand } from "@/context/brand-context";

interface Notif {
  id: string;
  title: string;
  message: string;
  type: string;
  severity: string;
  isRead: boolean;
  createdAt: string;
  metadata?: { link?: string } | null;
  /** Normalised route set by /api/notifications — used when the item
   *  comes from a signal SiteEvent source that doesn't carry a
   *  metadata.link the old way. Prefer this over metadata.link when
   *  present so signals → /signals, rank changes → /rank-tracker. */
  sourceUrl?: string;
  /** Which source the row came from ("notification" | "signal" | "rank"). */
  source?: string;
}

export default function NotificationBell() {
  const { brand } = useBrand();
  const router = useRouter();
  const [count, setCount] = useState(0);
  const [open, setOpen] = useState(false);
  const [items, setItems] = useState<Notif[]>([]);

  const loadCount = useCallback(async () => {
    if (!brand.id) return;
    const res = await fetch(`/api/notifications/count?brandId=${brand.id}`);
    if (res.ok) { const d = await res.json(); setCount(d.count ?? 0); }
  }, [brand.id]);

  useEffect(() => { loadCount(); const id = setInterval(loadCount, 30000); return () => clearInterval(id); }, [loadCount]);

  async function toggle() {
    if (!open) {
      const res = await fetch(`/api/notifications?brandId=${brand.id}&unreadOnly=false&limit=15`);
      if (res.ok) { const d = await res.json(); setItems(d.notifications ?? []); }
    }
    setOpen(!open);
  }

  async function markAllRead() {
    await fetch("/api/notifications/read", { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ all: true, brandId: brand.id }) });
    setCount(0);
    setItems((prev) => prev.map((n) => ({ ...n, isRead: true })));
  }

  async function clickNotif(n: Notif) {
    if (!n.isRead) {
      await fetch("/api/notifications/read", { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ ids: [n.id] }) });
      setCount((c) => Math.max(0, c - 1));
      setItems((prev) => prev.map((x) => x.id === n.id ? { ...x, isRead: true } : x));
    }
    // Prefer the normalised sourceUrl from /api/notifications — it's set
    // correctly for signal/rank rows (which have no metadata.link) and
    // falls back to the legacy metadata.link for Notification-table rows
    // whose alert rules wrote a custom deep link.
    const target = n.sourceUrl || n.metadata?.link;
    if (target) router.push(target);
    setOpen(false);
  }

  const sevDot: Record<string, string> = { critical: "bg-red-500", high: "bg-orange-500", medium: "bg-blue-500", low: "bg-slate-400" };

  return (
    <div className="relative">
      <button onClick={toggle} className="relative p-2 rounded-lg hover:bg-slate-100 text-slate-500">
        <Bell className="w-5 h-5" />
        {count > 0 && <span className="absolute top-1 right-1 w-4 h-4 rounded-full bg-red-500 text-white text-[9px] font-bold flex items-center justify-center">{count > 9 ? "9+" : count}</span>}
      </button>

      {open && (
        <>
          <div className="fixed inset-0 z-40" onClick={() => setOpen(false)} />
          <div className="absolute right-0 top-full mt-2 w-80 bg-white border border-slate-200 rounded-xl shadow-xl z-50 overflow-hidden">
            <div className="flex items-center justify-between px-4 py-3 border-b border-slate-100">
              <h3 className="text-sm font-bold text-slate-900">Notifications</h3>
              {count > 0 && <button onClick={markAllRead} className="flex items-center gap-1 text-[11px] text-brand-600 font-semibold hover:text-brand-800"><CheckCheck className="w-3 h-3" /> Mark all read</button>}
            </div>
            <div className="max-h-80 overflow-auto divide-y divide-slate-100">
              {items.length === 0 ? (
                <div className="px-4 py-8 text-center text-xs text-slate-400">No notifications yet.</div>
              ) : items.map((n) => (
                <button key={n.id} onClick={() => clickNotif(n)} className={`w-full text-left px-4 py-3 hover:bg-slate-50 ${!n.isRead ? "bg-brand-50/30" : ""}`}>
                  <div className="flex items-start gap-2">
                    <span className={`w-2 h-2 rounded-full mt-1.5 shrink-0 ${sevDot[n.severity] || sevDot.medium}`} />
                    <div className="flex-1 min-w-0">
                      <p className={`text-xs ${n.isRead ? "text-slate-600" : "text-slate-900 font-semibold"} truncate`}>{n.title}</p>
                      <p className="text-[11px] text-slate-500 line-clamp-2 mt-0.5">{n.message}</p>
                      <p className="text-[10px] text-slate-400 mt-1">{timeAgo(n.createdAt)}</p>
                    </div>
                    {!n.isRead && <span className="w-2 h-2 rounded-full bg-brand-500 mt-1.5 shrink-0" />}
                  </div>
                </button>
              ))}
            </div>
            <div className="px-4 py-2 border-t border-slate-100">
              <button onClick={() => { router.push("/notifications"); setOpen(false); }} className="text-xs text-brand-600 font-semibold hover:text-brand-800">View All Notifications</button>
            </div>
          </div>
        </>
      )}
    </div>
  );
}

function timeAgo(dateStr: string): string {
  const seconds = Math.floor((Date.now() - new Date(dateStr).getTime()) / 1000);
  if (seconds < 60) return "Just now";
  if (seconds < 3600) return `${Math.floor(seconds / 60)}m ago`;
  if (seconds < 86400) return `${Math.floor(seconds / 3600)}h ago`;
  return `${Math.floor(seconds / 86400)}d ago`;
}
