"use client";

import { useCallback, useEffect, useRef, useState } from "react";
import { useRouter } from "next/navigation";
import { useLang } from "@/context/LanguageContext";
import { api } from "@/lib/client";
import { formatDate } from "@/lib/utils";
import { IconBell } from "@/components/icons";

interface NotificationItem {
  id: number;
  kind: string;
  title: string;
  body: string | null;
  link: string | null;
  createdAt: string;
  read: boolean;
}

const POLL_MS = 45_000;

/** Topbar push-notification bell — unread badge, dropdown feed with
    mark-as-read, and opt-in desktop alerts for newly arrived pushes. */
export default function NotificationBell() {
  const { t, locale } = useLang();
  const N = t.notifications;
  const router = useRouter();
  const [unread, setUnread] = useState(0);
  const [open, setOpen] = useState(false);
  const [items, setItems] = useState<NotificationItem[] | null>(null);
  const [loading, setLoading] = useState(false);
  const [alertsOn, setAlertsOn] = useState(false);
  const lastSeenIdRef = useRef<number | null>(null);
  const rootRef = useRef<HTMLLIElement>(null);

  /** unread count — also fires desktop alerts for new arrivals */
  const poll = useCallback(async () => {
    try {
      const res = await api<{ unread: number; notifications: NotificationItem[] }>("/api/me/notifications?limit=5");
      setUnread(res.unread);
      const newest = res.notifications[0];
      if (newest) {
        if (lastSeenIdRef.current != null && newest.id > lastSeenIdRef.current && res.unread > 0) {
          // a push arrived while the user is logged in — desktop alert if allowed
          try {
            if (typeof window !== "undefined" && "Notification" in window && Notification.permission === "granted") {
              const n = new Notification(newest.title, { body: newest.body ?? undefined });
              n.onclick = () => {
                window.focus();
                if (newest.link) router.push(newest.link);
              };
            }
          } catch {
            /* alerts are best-effort */
          }
        }
        lastSeenIdRef.current = Math.max(lastSeenIdRef.current ?? 0, newest.id);
      }
    } catch {
      /* offline / unauthenticated — ignore */
    }
  }, [router]);

  useEffect(() => {
    poll();
    const timer = setInterval(poll, POLL_MS);
    return () => clearInterval(timer);
  }, [poll]);

  useEffect(() => {
    if (typeof window !== "undefined" && "Notification" in window && Notification.permission === "granted") {
      setAlertsOn(true);
    }
  }, []);

  // close on outside click
  useEffect(() => {
    if (!open) return;
    const onDoc = (e: MouseEvent) => {
      if (rootRef.current && !rootRef.current.contains(e.target as Node)) setOpen(false);
    };
    document.addEventListener("mousedown", onDoc);
    return () => document.removeEventListener("mousedown", onDoc);
  }, [open]);

  async function openPanel() {
    const next = !open;
    setOpen(next);
    if (next && !items) {
      setLoading(true);
      try {
        const res = await api<{ notifications: NotificationItem[] }>("/api/me/notifications?limit=25");
        setItems(res.notifications);
      } catch {
        setItems([]);
      } finally {
        setLoading(false);
      }
    }
  }

  async function markRead(item: NotificationItem) {
    if (!item.read) {
      setItems((prev) => (prev ?? []).map((x) => (x.id === item.id ? { ...x, read: true } : x)));
      setUnread((u) => Math.max(0, u - 1));
      try {
        await api("/api/me/notifications", { method: "POST", body: JSON.stringify({ ids: [item.id] }) });
      } catch {
        /* best-effort */
      }
    }
    setOpen(false);
    if (item.link) router.push(item.link);
  }

  async function markAllRead() {
    try {
      await api("/api/me/notifications", { method: "POST", body: JSON.stringify({ all: true }) });
    } catch {
      /* best-effort */
    }
    setItems((prev) => (prev ?? []).map((x) => ({ ...x, read: true })));
    setUnread(0);
  }

  async function enableAlerts() {
    try {
      if (typeof window === "undefined" || !("Notification" in window)) return;
      const perm = await Notification.requestPermission();
      if (perm === "granted") {
        setAlertsOn(true);
        new Notification(N.title, { body: N.alertsEnabled });
      }
    } catch {
      /* permission prompt dismissed */
    }
  }

  const kindLabel = (kind: string) =>
    kind === "EVENT" ? N.kindEvent : kind === "RESULT" ? N.kindResult : kind === "SYSTEM" ? N.kindSystem : N.kindNotice;
  const kindBadge = (kind: string) =>
    kind === "EVENT" ? "badge-primary" : kind === "RESULT" ? "badge-success" : kind === "SYSTEM" ? "badge-warning" : "badge-secondary";

  return (
    <li className="position-relative" ref={rootRef}>
      <button
        type="button"
        className="btn p-0 position-relative"
        onClick={openPanel}
        title={N.title}
        style={{ lineHeight: 0 }}
      >
        <IconBell className="svg-20" />
        {unread > 0 && (
          <span
            className="position-absolute badge rounded-pill badge-danger"
            style={{ top: -6, right: -8, fontSize: 10 }}
          >
            {unread > 99 ? "99+" : unread}
          </span>
        )}
      </button>

      {open && (
        <div
          className="position-absolute bg-white rounded shadow"
          style={{ top: "100%", right: 0, width: 360, maxWidth: "90vw", zIndex: 1050, marginTop: 8 }}
        >
          <div className="d-flex justify-content-between align-items-center px-3 py-2 border-bottom">
            <h6 className="mb-0 f-w-700">{N.title}</h6>
            <div className="d-flex gap-2 align-items-center">
              {!alertsOn && (
                <button type="button" className="btn btn-sm btn-soft-secondary ems-fs-11" onClick={enableAlerts}>
                  {N.enableAlerts}
                </button>
              )}
              <button type="button" className="btn btn-sm btn-soft-primary ems-fs-11" onClick={markAllRead} disabled={unread === 0}>
                {N.markAllRead}
              </button>
            </div>
          </div>
          <div style={{ maxHeight: 380, overflowY: "auto" }}>
            {loading ? (
              <p className="text-center text-muted ems-fs-13 py-4 mb-0">…</p>
            ) : (items ?? []).length === 0 ? (
              <p className="text-center text-muted ems-fs-13 py-4 mb-0">{N.empty}</p>
            ) : (
              (items ?? []).map((item) => (
                <button
                  key={item.id}
                  type="button"
                  className="d-block w-100 text-start px-3 py-2 border-bottom bg-transparent"
                  style={{ border: "none", borderBottom: "1px solid #eef2f7" }}
                  onClick={() => markRead(item)}
                >
                  <div className="d-flex justify-content-between align-items-center gap-2">
                    <span className={`badge ${kindBadge(item.kind)}`}>{kindLabel(item.kind)}</span>
                    <span className="ems-fs-11 text-muted">{formatDate(item.createdAt, locale)}</span>
                    {!item.read && <span className="badge rounded-pill badge-danger" style={{ fontSize: 8, padding: "2px 6px" }}>&nbsp;</span>}
                  </div>
                  <div className={`ems-fs-13 ${item.read ? "" : "f-w-700"}`}>{item.title}</div>
                  {item.body && <div className="ems-fs-11 text-muted text-truncate">{item.body}</div>}
                </button>
              ))
            )}
          </div>
        </div>
      )}
    </li>
  );
}
