import { useCallback, useEffect, useState } from "react";
import { Link, useNavigate } from "@tanstack/react-router";
import {
  AlertTriangle,
  Bell,
  CheckCircle2,
  CircleDot,
  FileStack,
  HelpCircle,
  MessageSquareReply,
  Upload,
} from "lucide-react";
import type { AuthPlatform } from "@/lib/auth";
import { useAuthSession } from "@/hooks/useAuthSession";
import {
  fetchNotifications,
  markAllNotificationsRead,
  markNotificationRead,
  notificationNavigation,
  notificationRelativeTime,
  type AppNotification,
} from "@/lib/notifications-api";
import { Button } from "@/components/ui/button";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { cn } from "@/lib/utils";

const POLL_MS = 20_000;

function iconFor(type: string) {
  switch (type) {
    case "DOCUMENT_UPLOADED":
      return { Icon: Upload, className: "bg-muted text-muted-foreground" };
    case "DOCUMENT_NEEDS_REVIEW":
    case "AI_ADVICE_REQUIRES_APPROVAL":
      return { Icon: AlertTriangle, className: "bg-attention-soft text-attention" };
    case "ACCOUNTANT_QUESTION":
      return { Icon: HelpCircle, className: "bg-attention-soft text-attention" };
    case "QUESTION_ANSWERED":
      return { Icon: MessageSquareReply, className: "bg-primary-soft text-primary" };
    case "INVOICE_APPROVED":
    case "DOCUMENT_READY":
    case "SNLSTART_SYNC_SUCCESS":
      return { Icon: CheckCircle2, className: "bg-success-soft text-success" };
    case "INVOICE_REJECTED":
    case "SNLSTART_SYNC_FAILED":
      return { Icon: AlertTriangle, className: "bg-destructive-soft text-destructive" };
    case "CLIENT_REMINDER":
      return { Icon: CircleDot, className: "bg-brand-soft text-brand" };
    default:
      return { Icon: FileStack, className: "bg-muted text-muted-foreground" };
  }
}

export function NotificationBell({ platform }: { platform: AuthPlatform }) {
  const navigate = useNavigate();
  const session = useAuthSession(platform);
  const [open, setOpen] = useState(false);
  const [items, setItems] = useState<AppNotification[]>([]);
  const [unread, setUnread] = useState(0);
  const [loading, setLoading] = useState(false);

  const refresh = useCallback(async () => {
    if (!session?.email) return;
    try {
      const data = await fetchNotifications(platform, session.email, {
        clientId: session.clientId,
        limit: 8,
      });
      setItems(data.items);
      setUnread(data.unread_count);
    } catch {
      // Keep last known state; bell must not break the shell
    }
  }, [platform, session?.email, session?.clientId]);

  useEffect(() => {
    void refresh();
    const id = window.setInterval(() => void refresh(), POLL_MS);
    const onFocus = () => void refresh();
    window.addEventListener("focus", onFocus);
    return () => {
      window.clearInterval(id);
      window.removeEventListener("focus", onFocus);
    };
  }, [refresh]);

  useEffect(() => {
    if (open) void refresh();
  }, [open, refresh]);

  const onOpenItem = async (n: AppNotification) => {
    if (!session?.email) return;
    setOpen(false);
    if (!n.is_read) {
      try {
        await markNotificationRead(platform, session.email, n.id, session.clientId);
        setUnread((c) => Math.max(0, c - 1));
        setItems((prev) => prev.map((x) => (x.id === n.id ? { ...x, is_read: true } : x)));
      } catch {
        // navigation still proceeds
      }
    }
    const nav = notificationNavigation(platform, n);
    void navigate({ to: nav.to as never, params: nav.params as never });
  };

  const onMarkAll = async () => {
    if (!session?.email || unread === 0) return;
    setLoading(true);
    try {
      await markAllNotificationsRead(platform, session.email, session.clientId);
      setUnread(0);
      setItems((prev) => prev.map((x) => ({ ...x, is_read: true })));
    } catch {
      // ignore
    } finally {
      setLoading(false);
    }
  };

  return (
    <Popover open={open} onOpenChange={setOpen}>
      <PopoverTrigger asChild>
        <Button
          variant="ghost"
          size="icon"
          aria-label={
            unread > 0
              ? `Notifications, ${unread > 99 ? "99+" : unread} unread`
              : "Notifications"
          }
          className="relative shrink-0 overflow-visible"
        >
          <span className="relative inline-flex">
            <Bell size={18} />
            {unread > 0 ? (
              <span
                aria-hidden="true"
                className="absolute -top-1.5 -right-1.5 flex h-[16px] min-w-[16px] items-center justify-center rounded-full bg-[#E11D48] px-[4px] text-[9px] leading-none font-bold text-white shadow-[0_0_0_2px_var(--background)]"
              >
                {unread > 99 ? "99+" : unread}
              </span>
            ) : null}
          </span>
        </Button>
      </PopoverTrigger>
      <PopoverContent align="end" className="w-[360px] p-0 shadow-[var(--shadow-panel)]">
        <div className="flex items-center justify-between border-b border-border px-4 py-3">
          <p className="text-[14px] font-semibold text-foreground">Notifications</p>
          <button
            type="button"
            disabled={unread === 0 || loading}
            onClick={() => void onMarkAll()}
            className="text-[12px] font-medium text-primary disabled:opacity-40 hover:underline"
          >
            Mark all read
          </button>
        </div>

        {items.length === 0 ? (
          <div className="px-4 py-10 text-center">
            <Bell size={22} className="mx-auto text-muted-foreground" aria-hidden="true" />
            <p className="mt-2 text-[13.5px] font-medium text-foreground">You’re all caught up</p>
            <p className="mt-1 text-[12.5px] text-muted-foreground">No notifications yet.</p>
          </div>
        ) : (
          <ul className="max-h-[380px] overflow-y-auto divide-y divide-border">
            {items.map((n) => {
              const { Icon, className } = iconFor(n.type);
              return (
                <li key={n.id}>
                  <button
                    type="button"
                    onClick={() => void onOpenItem(n)}
                    className={cn(
                      "flex w-full gap-3 px-4 py-3 text-left transition-colors hover:bg-muted/50",
                      !n.is_read ? "bg-[#E11D48]/6" : "opacity-80",
                    )}
                  >
                    <span
                      className={cn(
                        "mt-0.5 flex size-8 shrink-0 items-center justify-center rounded-full",
                        className,
                      )}
                    >
                      <Icon size={14} aria-hidden="true" />
                    </span>
                    <div className="min-w-0 flex-1">
                      <div className="flex items-start gap-2">
                        <p
                          className={cn(
                            "truncate text-[13.5px] text-foreground",
                            !n.is_read ? "font-semibold" : "font-medium",
                          )}
                        >
                          {n.title}
                        </p>
                        {!n.is_read ? (
                          <span className="mt-1.5 size-1.5 shrink-0 rounded-full bg-[#E11D48]" aria-hidden="true" />
                        ) : null}
                      </div>
                      <p className="mt-0.5 line-clamp-2 text-[12.5px] leading-5 text-muted-foreground">
                        {n.message}
                      </p>
                      <p className="mt-1 text-[11.5px] text-muted-foreground">
                        {notificationRelativeTime(n.created_at)}
                      </p>
                    </div>
                  </button>
                </li>
              );
            })}
          </ul>
        )}

        <div className="border-t border-border px-4 py-2.5">
          <Link
            to="/notifications"
            onClick={() => setOpen(false)}
            className="block text-center text-[13px] font-semibold text-brand-foreground hover:text-brand"
          >
            View all notifications →
          </Link>
        </div>
      </PopoverContent>
    </Popover>
  );
}
