import { useEffect, useRef, useState, useSyncExternalStore } from "react";
import { useQueryClient } from "@tanstack/react-query";
import { Bell, Eye, RotateCcw, Search, Trash2 } from "lucide-react";
import { api, type FeedFilters } from "../lib/api";
import {
  clearAll,
  dismiss,
  getNotifications,
  getUnreadCount,
  markAllRead,
  notify,
  subscribe,
  type VideoHiddenMeta,
  type VideoWatchedMeta,
} from "../lib/notifications";
import { LEVEL_STYLE } from "./Toaster";

function relTime(ts: number): string {
  const s = Math.round((Date.now() - ts) / 1000);
  if (s < 60) return "just now";
  const m = Math.round(s / 60);
  if (m < 60) return `${m}m ago`;
  const h = Math.round(m / 60);
  if (h < 24) return `${h}h ago`;
  const d = Math.round(h / 24);
  return `${d}d ago`;
}

export default function NotificationCenter({
  filters,
  setFilters,
}: {
  filters: FeedFilters;
  setFilters: (f: FeedFilters) => void;
}) {
  const notifications = useSyncExternalStore(subscribe, getNotifications, getNotifications);
  const unread = useSyncExternalStore(subscribe, getUnreadCount, getUnreadCount);
  const [open, setOpen] = useState(false);
  const wrap = useRef<HTMLDivElement>(null);
  const qc = useQueryClient();

  // Close when clicking anywhere outside the panel.
  useEffect(() => {
    if (!open) return;
    function onDown(e: MouseEvent) {
      if (wrap.current && !wrap.current.contains(e.target as Node)) setOpen(false);
    }
    document.addEventListener("mousedown", onDown);
    return () => document.removeEventListener("mousedown", onDown);
  }, [open]);

  // Opening the center marks everything read.
  useEffect(() => {
    if (open) markAllRead();
  }, [open, notifications.length]);

  function locateHidden(meta: VideoHiddenMeta) {
    setFilters({
      ...filters,
      show: "hidden",
      channelId: meta.channelId || undefined,
      channelName: meta.channelName || undefined,
    });
    setOpen(false);
  }

  function revertState(meta: VideoHiddenMeta | VideoWatchedMeta, verb: string) {
    api
      .setState(meta.videoId, "new")
      .then(() => {
        qc.invalidateQueries({ queryKey: ["feed"] });
        qc.invalidateQueries({ queryKey: ["feed-count"] });
        notify({ level: "success", message: `${verb} “${meta.title}”` });
      })
      .catch(() => {});
  }

  return (
    <div className="relative" ref={wrap}>
      <button
        onClick={() => setOpen((o) => !o)}
        title="Notifications"
        className="relative p-2 rounded-lg text-muted hover:text-fg hover:bg-card transition"
      >
        <Bell className="w-5 h-5" />
        {unread > 0 && (
          <span className="absolute -top-0.5 -right-0.5 min-w-[16px] h-4 px-1 rounded-full bg-accent text-accent-fg text-[10px] font-bold grid place-items-center">
            {unread > 9 ? "9+" : unread}
          </span>
        )}
      </button>

      {open && (
        <div className="glass absolute right-0 mt-2 w-80 max-w-[calc(100vw-2rem)] rounded-xl z-30 flex flex-col max-h-[70vh] animate-[popIn_0.16s_ease]">
          <div className="flex items-center justify-between px-3 py-2 border-b border-border">
            <div className="text-sm font-semibold">Notifications</div>
            {notifications.length > 0 && (
              <button
                onClick={clearAll}
                className="flex items-center gap-1 text-xs text-muted hover:text-accent transition"
                title="Clear all"
              >
                <Trash2 className="w-3.5 h-3.5" />
                Clear
              </button>
            )}
          </div>

          <div className="overflow-y-auto">
            {notifications.length === 0 ? (
              <div className="px-3 py-8 text-center text-sm text-muted">No notifications yet.</div>
            ) : (
              notifications.map((n) => {
                const { icon: Icon, color } = LEVEL_STYLE[n.level];
                const needsAction = n.requiresInteraction && !n.dismissed;
                const hidden = n.meta?.kind === "video-hidden" ? n.meta : null;
                const watched = n.meta?.kind === "video-watched" ? n.meta : null;
                return (
                  <div
                    key={n.id}
                    className={`flex items-start gap-2.5 px-3 py-2.5 border-b border-border/60 ${
                      needsAction ? "bg-accent/5" : ""
                    }`}
                  >
                    <Icon className={`w-4 h-4 shrink-0 mt-0.5 ${color}`} />
                    <div className="min-w-0 flex-1">
                      {n.title && <div className="text-sm font-semibold">{n.title}</div>}
                      <div className="text-sm break-words">{n.message}</div>
                      <div className="flex items-center gap-2 mt-0.5">
                        <span className="text-[11px] text-muted">{relTime(n.ts)}</span>
                        {needsAction && (
                          <span className="text-[10px] uppercase tracking-wide font-semibold text-accent">
                            Action needed
                          </span>
                        )}
                      </div>

                      {hidden ? (
                        <div className="flex items-center gap-3 mt-1">
                          <button
                            onClick={() => locateHidden(hidden)}
                            className="flex items-center gap-1 text-accent text-sm font-semibold hover:underline"
                          >
                            <Search className="w-3.5 h-3.5" />
                            Find in feed
                          </button>
                          <button
                            onClick={() => revertState(hidden, "Unhidden")}
                            className="flex items-center gap-1 text-accent text-sm font-semibold hover:underline"
                          >
                            <Eye className="w-3.5 h-3.5" />
                            Unhide
                          </button>
                        </div>
                      ) : watched ? (
                        <div className="flex items-center gap-3 mt-1">
                          <button
                            onClick={() => revertState(watched, "Unwatched")}
                            className="flex items-center gap-1 text-accent text-sm font-semibold hover:underline"
                          >
                            <RotateCcw className="w-3.5 h-3.5" />
                            Unwatch
                          </button>
                        </div>
                      ) : (
                        n.action &&
                        !n.dismissed && (
                          <button
                            onClick={() => {
                              n.action!.onClick();
                              dismiss(n.id);
                            }}
                            className="mt-1 text-accent text-sm font-semibold hover:underline"
                          >
                            {n.action.label}
                          </button>
                        )
                      )}
                    </div>
                  </div>
                );
              })
            )}
          </div>
        </div>
      )}
    </div>
  );
}
