"use client";
import React, { useState, useEffect, useRef, useCallback } from "react";
import Link from "next/link";
import { createClient } from "@/lib/supabase/client";

interface Notification {
  id: string;
  type: "thread_reply" | "mention" | "upvote" | "follow";
  title: string;
  body: string | null;
  link: string | null;
  actor_name: string | null;
  is_read: boolean;
  created_at: string;
}

const TYPE_CONFIG: Record<string, { icon: React.ReactNode; label: string; color: string }> = {
  thread_reply: {
    icon: (
      <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" aria-hidden="true">
        <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
      </svg>
    ),
    label: "Reply",
    color: "text-blue-400",
  },
  mention: {
    icon: (
      <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" aria-hidden="true">
        <circle cx="12" cy="12" r="4" /><path d="M16 8v5a3 3 0 0 0 6 0v-1a10 10 0 1 0-3.92 7.94" />
      </svg>
    ),
    label: "Mention",
    color: "text-purple-400",
  },
  upvote: {
    icon: (
      <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" aria-hidden="true">
        <path d="M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3H14z" />
        <path d="M7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3" />
      </svg>
    ),
    label: "Upvote",
    color: "text-green-400",
  },
  follow: {
    icon: (
      <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" aria-hidden="true">
        <path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" /><circle cx="9" cy="7" r="4" />
        <line x1="19" y1="8" x2="19" y2="14" /><line x1="22" y1="11" x2="16" y2="11" />
      </svg>
    ),
    label: "Follow",
    color: "text-yellow-400",
  },
};

function timeAgo(dateStr: string): string {
  const diff = Date.now() - new Date(dateStr).getTime();
  const mins = Math.floor(diff / 60000);
  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`;
  const days = Math.floor(hrs / 24);
  if (days < 7) return `${days}d ago`;
  return new Date(dateStr).toLocaleDateString();
}

export default function NotificationCenter() {
  const [open, setOpen] = useState(false);
  const [notifications, setNotifications] = useState<Notification[]>([]);
  const [unreadCount, setUnreadCount] = useState(0);
  const [loading, setLoading] = useState(false);
  const [loggedIn, setLoggedIn] = useState(false);
  const panelRef = useRef<HTMLDivElement>(null);
  const bellRef = useRef<HTMLButtonElement>(null);

  // Check auth
  useEffect(() => {
    const supabase = createClient();
    supabase.auth.getUser().then(({ data: { user } }) => {
      setLoggedIn(!!user);
    });
    const { data: { subscription } } = supabase.auth.onAuthStateChange((_e, session) => {
      setLoggedIn(!!session?.user);
    });
    return () => subscription.unsubscribe();
  }, []);

  const fetchNotifications = useCallback(async () => {
    if (!loggedIn) return;
    setLoading(true);
    try {
      const res = await fetch("/api/notifications?limit=30");
      if (res.ok) {
        const data = await res.json();
        setNotifications(data.notifications ?? []);
        setUnreadCount(data.unreadCount ?? 0);
      }
    } catch {
      // silent
    } finally {
      setLoading(false);
    }
  }, [loggedIn]);

  // Poll for unread count every 60s
  useEffect(() => {
    if (!loggedIn) return;
    fetchNotifications();
    const interval = setInterval(fetchNotifications, 60000);
    return () => clearInterval(interval);
  }, [loggedIn, fetchNotifications]);

  // Open panel and mark visible as read
  const handleOpen = async () => {
    setOpen((prev) => !prev);
    if (!open && unreadCount > 0) {
      const unreadIds = notifications.filter((n) => !n.is_read).map((n) => n.id);
      if (unreadIds.length > 0) {
        await fetch("/api/notifications", {
          method: "PATCH",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ ids: unreadIds }),
        });
        setNotifications((prev) => prev.map((n) => ({ ...n, is_read: true })));
        setUnreadCount(0);
      }
    }
  };

  // Dismiss single
  const dismissOne = async (id: string, e: React.MouseEvent) => {
    e.preventDefault();
    e.stopPropagation();
    await fetch("/api/notifications", {
      method: "DELETE",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ ids: [id] }),
    });
    setNotifications((prev) => prev.filter((n) => n.id !== id));
  };

  // Dismiss all
  const dismissAll = async () => {
    await fetch("/api/notifications", {
      method: "DELETE",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ dismissAll: true }),
    });
    setNotifications([]);
    setUnreadCount(0);
  };

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

  // Close on Escape
  useEffect(() => {
    const handler = (e: KeyboardEvent) => {
      if (e.key === "Escape" && open) {
        setOpen(false);
        bellRef.current?.focus();
      }
    };
    document.addEventListener("keydown", handler);
    return () => document.removeEventListener("keydown", handler);
  }, [open]);

  if (!loggedIn) return null;

  return (
    <div className="relative">
      {/* Bell Button */}
      <button
        ref={bellRef}
        onClick={handleOpen}
        aria-label={`Notifications${unreadCount > 0 ? `, ${unreadCount} unread` : ""}`}
        aria-expanded={open}
        aria-haspopup="true"
        className="relative flex items-center justify-center w-7 h-7 text-[#888] hover:text-[#1D4ED8] transition-colors focus:outline-none focus-visible:ring-1 focus-visible:ring-[#1D4ED8] focus-visible:ring-offset-1 focus-visible:ring-offset-[#111]"
      >
        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" aria-hidden="true">
          <path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9" />
          <path d="M13.73 21a2 2 0 0 1-3.46 0" />
        </svg>
        {unreadCount > 0 && (
          <span
            aria-hidden="true"
            className="absolute -top-1 -right-1 min-w-[16px] h-4 px-0.5 flex items-center justify-center rounded-full bg-[#1D4ED8] text-white text-[9px] font-bold leading-none"
          >
            {unreadCount > 99 ? "99+" : unreadCount}
          </span>
        )}
      </button>

      {/* Dropdown Panel */}
      {open && (
        <div
          ref={panelRef}
          role="dialog"
          aria-label="Notification center"
          className="absolute right-0 top-full mt-2 w-80 bg-[#FFFFFF] border border-[#DCE6F2] rounded-lg shadow-2xl z-50 overflow-hidden"
          style={{ maxHeight: "480px" }}
        >
          {/* Header */}
          <div className="flex items-center justify-between px-4 py-3 border-b border-[#DCE6F2]">
            <h2 className="text-sm font-bold text-[#e0e0e0] uppercase tracking-wide">Notifications</h2>
            <div className="flex items-center gap-2">
              {notifications.length > 0 && (
                <button
                  onClick={dismissAll}
                  className="text-[10px] text-[#666] hover:text-[#1D4ED8] transition-colors uppercase tracking-wide font-bold focus:outline-none focus-visible:ring-1 focus-visible:ring-[#1D4ED8]"
                >
                  Clear all
                </button>
              )}
              <button
                onClick={() => setOpen(false)}
                aria-label="Close notifications"
                className="text-[#555] hover:text-[#ccc] transition-colors focus:outline-none focus-visible:ring-1 focus-visible:ring-[#1D4ED8]"
              >
                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" aria-hidden="true">
                  <line x1="18" y1="6" x2="6" y2="18" /><line x1="6" y1="6" x2="18" y2="18" />
                </svg>
              </button>
            </div>
          </div>

          {/* Filter tabs */}
          <FilterTabs notifications={notifications} />
        </div>
      )}
    </div>
  );
}

function FilterTabs({ notifications }: { notifications: Notification[] }) {
  const [activeTab, setActiveTab] = useState<"all" | "replies" | "upvotes" | "mentions" | "follows">("all");

  const tabs: { key: typeof activeTab; label: string }[] = [
    { key: "all", label: "All" },
    { key: "replies", label: "Replies" },
    { key: "upvotes", label: "Upvotes" },
    { key: "mentions", label: "Mentions" },
    { key: "follows", label: "Follows" },
  ];

  const filtered = notifications.filter((n) => {
    if (activeTab === "all") return true;
    if (activeTab === "replies") return n.type === "thread_reply";
    if (activeTab === "upvotes") return n.type === "upvote";
    if (activeTab === "mentions") return n.type === "mention";
    if (activeTab === "follows") return n.type === "follow";
    return true;
  });

  return (
    <>
      {/* Tabs */}
      <div className="flex border-b border-[#DCE6F2] overflow-x-auto scrollbar-none">
        {tabs.map((tab) => {
          const count = tab.key === "all"
            ? notifications.length
            : notifications.filter((n) =>
                tab.key === "replies" ? n.type === "thread_reply" :
                tab.key === "upvotes" ? n.type === "upvote" :
                tab.key === "mentions" ? n.type === "mention" :
                n.type === "follow"
              ).length;
          return (
            <button
              key={tab.key}
              onClick={() => setActiveTab(tab.key)}
              className={`flex-shrink-0 px-3 py-2 text-[10px] font-bold uppercase tracking-wide transition-colors focus:outline-none focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-[#1D4ED8] ${
                activeTab === tab.key
                  ? "text-[#1D4ED8] border-b-2 border-[#1D4ED8]"
                  : "text-[#666] hover:text-[#aaa]"
              }`}
            >
              {tab.label}
              {count > 0 && (
                <span className="ml-1 text-[9px] text-[#555]">({count})</span>
              )}
            </button>
          );
        })}
      </div>

      {/* List */}
      <div className="overflow-y-auto" style={{ maxHeight: "340px" }}>
        {filtered.length === 0 ? (
          <div className="flex flex-col items-center justify-center py-10 text-center px-4">
            <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" className="text-[#333] mb-2" aria-hidden="true">
              <path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9" />
              <path d="M13.73 21a2 2 0 0 1-3.46 0" />
            </svg>
            <p className="text-[#555] text-xs">No notifications yet</p>
          </div>
        ) : (
          filtered.map((n) => <NotificationItem key={n.id} notification={n} />)
        )}
      </div>
    </>
  );
}

function NotificationItem({ notification: n }: { notification: Notification }) {
  const cfg = TYPE_CONFIG[n.type] ?? TYPE_CONFIG.thread_reply;
  const [dismissed, setDismissed] = useState(false);

  const handleDismiss = async (e: React.MouseEvent) => {
    e.preventDefault();
    e.stopPropagation();
    setDismissed(true);
    await fetch("/api/notifications", {
      method: "DELETE",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ ids: [n.id] }),
    });
  };

  if (dismissed) return null;

  const content = (
    <div className={`group flex items-start gap-3 px-4 py-3 border-b border-[#DCE6F2] hover:bg-[#e2e8f0] transition-colors ${!n.is_read ? "bg-[#EFF6FF]" : ""}`}>
      {/* Type icon */}
      <div className={`flex-shrink-0 mt-0.5 ${cfg.color}`}>{cfg.icon}</div>

      {/* Content */}
      <div className="flex-1 min-w-0">
        <div className="flex items-start justify-between gap-2">
          <div className="min-w-0">
            <p className="text-[11px] text-[#ccc] leading-snug">
              {n.actor_name && (
                <span className="font-semibold text-[#e0e0e0]">{n.actor_name} </span>
              )}
              {n.title}
            </p>
            {n.body && (
              <p className="text-[10px] text-[#666] mt-0.5 truncate">{n.body}</p>
            )}
          </div>
          <button
            onClick={handleDismiss}
            aria-label="Dismiss notification"
            className="flex-shrink-0 opacity-0 group-hover:opacity-100 text-[#444] hover:text-[#888] transition-all focus:outline-none focus:opacity-100 focus-visible:ring-1 focus-visible:ring-[#1D4ED8]"
          >
            <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" aria-hidden="true">
              <line x1="18" y1="6" x2="6" y2="18" /><line x1="6" y1="6" x2="18" y2="18" />
            </svg>
          </button>
        </div>
        <div className="flex items-center gap-2 mt-1">
          <span className={`text-[9px] font-bold uppercase tracking-wide ${cfg.color}`}>{cfg.label}</span>
          <span className="text-[9px] text-[#444]">{timeAgo(n.created_at)}</span>
          {!n.is_read && (
            <span className="w-1.5 h-1.5 rounded-full bg-[#1D4ED8] flex-shrink-0" aria-label="Unread" />
          )}
        </div>
      </div>
    </div>
  );

  if (n.link) {
    return (
      <Link href={n.link} className="block focus:outline-none focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-[#1D4ED8]">
        {content}
      </Link>
    );
  }
  return <div>{content}</div>;
}
