import React, { useRef, useCallback, useState, useEffect } from "react";
import NotificationCard from "../common/NotificationCard";
import { useNotifications } from "@/shared/hooks/useNotification";
import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
import { Bell, BellOff, CheckCheck, Loader2 } from "lucide-react";
import { useNavigate } from "react-router-dom";
import type { Notification } from "@/shared/hooks/useNotification";
import { toast } from "sonner";
import { useSocketNotification } from "./hooks/useSocket";
import { useTranslation } from "react-i18next";

dayjs.extend(relativeTime);

const NotificationList = () => {
  const { t } = useTranslation();
  const [activeTab, setActiveTab] = useState<"all" | "unread">("unread");
  const loaderRef = useRef<HTMLDivElement>(null);
  const [visibleCount, setVisibleCount] = useState(3);
  const [unseenCount, setUnseenCount] = useState(0);
  const navigate = useNavigate();
  const { notifications, loading, error, markAsRead, refresh, setParams } =
    useNotifications(
      { take: 100, skip: 0, orderBy: "createdAt:DESC" },
      setUnseenCount,
    );
  const { scheduleReminder } = useSocketNotification();

  const filteredNotifications = notifications
    .filter((n) => (activeTab === "unread" ? !n.isSeen : true))
    .sort(
      (a, b) =>
        new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(),
    );

  const visibleNotifications = filteredNotifications.slice(0, visibleCount);
  const hasUnread = unseenCount > 0;

  const handleObserver = useCallback(
    (entries: IntersectionObserverEntry[]) => {
      const [entry] = entries;
      if (entry.isIntersecting && !loading) {
        setVisibleCount((prev) => prev + 3);
        if (visibleCount + 3 > notifications.length) {
          setParams((prev) => ({
            ...prev,
            skip: prev.skip + prev.take,
          }));
        }
      }
    },
    [loading, notifications.length, setParams, visibleCount],
  );

  useEffect(() => {
    const observer = new IntersectionObserver(handleObserver, {
      root: null,
      rootMargin: "20px",
      threshold: 0.1,
    });

    const currentLoader = loaderRef.current;
    if (currentLoader) observer.observe(currentLoader);

    return () => {
      if (currentLoader) observer.unobserve(currentLoader);
    };
  }, [handleObserver]);

  const markAllAsRead = useCallback(() => {
    filteredNotifications
      .filter((n) => !n.isSeen)
      .forEach((n) => markAsRead(n.id));
  }, [filteredNotifications, markAsRead]);

  const resolveNavigationPath = useCallback(
    (notification: Notification): string | null => {
      const itemId = notification.itemId || notification.id;
      const routeRaw = `${notification.metadata?.route || ""}`
        .toLowerCase()
        .replace(/[\s_-]/g, "");
      const recordTypeRaw = `${notification.metadata?.recordType || ""}`
        .toLowerCase()
        .replace(/[\s_-]/g, "");

      // 1. If the backend gave us a ready-made route, use it (replace {id} / :id placeholders)
      if (
        notification.metadata?.route &&
        notification.metadata.route.startsWith("/")
      ) {
        return notification.metadata.route
          .replace(/\{id\}/gi, itemId)
          .replace(/:id\b/gi, itemId);
      }

      // 2. DMS / Document routes
      if (
        routeRaw.includes("dms") ||
        routeRaw.includes("document") ||
        recordTypeRaw.includes("document") ||
        recordTypeRaw.includes("file")
      ) {
        return `/dms/documents/${itemId}`;
      }

      // 3. Record-management — outgoing / approval
      if (
        routeRaw.includes("outgoing") ||
        routeRaw.includes("approval") ||
        routeRaw.includes("approve")
      ) {
        return `/record-management/viewApproval/${itemId}`;
      }

      // 4. Record-management — incoming
      if (
        routeRaw.includes("incoming") ||
        ["external", "internal", "cc", "nonsmartuser", "internalmemo"].includes(
          recordTypeRaw,
        )
      ) {
        if (recordTypeRaw === "internal" || recordTypeRaw === "internalmemo") {
          return `/record-management/viewIncoming/internal/${itemId}`;
        }
        if (recordTypeRaw === "cc") {
          return `/record-management/viewIncoming/cc/${itemId}`;
        }
        return `/record-management/viewIncoming/incoming/${itemId}`;
      }

      return null;
    },
    [],
  );

  const handleNotificationOnClick = useCallback(
    (notification: Notification) => {
      if (!notification.isSeen) markAsRead(notification.id);

      const itemId = notification.itemId || notification.id;
      if (!itemId) {
        toast.info(
          t("notifications.noTarget", {
            defaultValue: "Notification does not contain a target record",
          }),
        );
        return;
      }

      const path = resolveNavigationPath(notification);
      if (path) {
        navigate(path);
      } else {
        toast.info(
          t("notifications.noRoute", {
            defaultValue:
              "No specific route defined for this notification type",
          }),
        );
      }
    },
    [navigate, markAsRead, resolveNavigationPath, t],
  );

  const handleRemind = useCallback(
    (notificationId: string, minutes: number) => {
      const notification = notifications.find((n) => n.id === notificationId);
      if (notification) {
        scheduleReminder(notification, minutes);
      }
    },
    [notifications, scheduleReminder],
  );

  if (loading && notifications.length === 0) {
    return (
      <div className="flex h-90 items-center justify-center">
        <Loader2 className="h-6 w-6 animate-spin text-green-500" />
      </div>
    );
  }

  if (error) {
    return (
      <div className="mx-4 my-5 rounded-xl border border-red-200 bg-red-50 p-4 text-center dark:border-red-900/60 dark:bg-red-950/30">
        <p className="text-sm text-red-600 dark:text-red-300">{error}</p>
        <button
          onClick={refresh}
          className="mt-2 rounded-md px-3 py-1 text-sm font-medium text-primary-700 hover:bg-primary-100 dark:text-primary-300 dark:hover:bg-primary-900/30">
          {t("profile.tryAgain")}
        </button>
      </div>
    );
  }

  return (
    <div className="flex h-full max-h-[calc(100dvh-5rem)] flex-col overflow-hidden rounded-2xl bg-white dark:bg-gray-900 sm:max-h-[430px]">
      <div className="border-b border-gray-100 bg-gradient-to-r from-primary-50 to-primary-50 px-3 py-3 dark:border-gray-800 dark:from-primary-950/40 dark:to-primary-950/30 sm:px-4">
        <div className="flex items-start justify-between gap-2">
          <div className="flex items-center gap-2">
            <div className="flex h-8 w-8 shrink-0 items-center justify-center rounded-xl bg-primary-500/10 text-primary-600 dark:bg-primary-900/30 dark:text-primary-300">
              <Bell className="h-4 w-4" />
            </div>
            <div className="min-w-0">
              <h3 className="text-sm font-semibold text-gray-900 dark:text-gray-100">
                {t("header.notifications")}
              </h3>
              <p className="text-xs text-gray-500 dark:text-gray-400">
                {hasUnread ? `${unseenCount} unread` : "You're all caught up"}
              </p>
            </div>
          </div>

          {hasUnread && (
            <button
              onClick={markAllAsRead}
              className="inline-flex shrink-0 items-center gap-1 rounded-lg bg-primary-500 px-2.5 py-1.5 text-xs font-medium text-white transition-colors hover:bg-primary-600">
              <CheckCheck className="h-3.5 w-3.5" />
              Mark all
            </button>
          )}
        </div>

        <div className="mt-3 inline-flex rounded-xl bg-white p-1 shadow-sm ring-1 ring-black/5 dark:bg-gray-800 dark:ring-white/10">
          <button
            className={`rounded-lg px-3 py-1.5 text-xs font-semibold transition-colors ${
              activeTab === "unread"
                ? "bg-primary-500 text-white shadow-sm"
                : "text-gray-600 hover:bg-primary-50 dark:text-gray-300 dark:hover:bg-primary-900/20"
            }`}
            onClick={() => {
              setActiveTab("unread");
              setVisibleCount(3);
            }}>
            Unread
            {unseenCount > 0 && (
              <span
                className={`ml-1.5 rounded-full px-1.5 py-0.5 text-[10px] ${
                  activeTab === "unread"
                    ? "bg-white/25 text-white"
                    : "bg-primary-100 text-primary-700 dark:bg-primary-900/40 dark:text-primary-300"
                }`}>
                {unseenCount}
              </span>
            )}
          </button>

          <button
            className={`rounded-lg px-3 py-1.5 text-xs font-semibold transition-colors ${
              activeTab === "all"
                ? "bg-primary-500 text-white shadow-sm"
                : "text-gray-600 hover:bg-primary-50 dark:text-gray-300 dark:hover:bg-primary-900/20"
            }`}
            onClick={() => {
              setActiveTab("all");
              setVisibleCount(3);
            }}>
            All
          </button>
        </div>
      </div>

      <div className="space-y-2.5 overflow-y-auto px-3 py-3 sm:space-y-3 sm:px-4">
        {visibleNotifications.length === 0 ? (
          <div className="py-10 text-center">
            <div className="mx-auto flex h-14 w-14 items-center justify-center rounded-2xl bg-gray-100 dark:bg-gray-800">
              {activeTab === "unread" ? (
                <BellOff className="h-6 w-6 text-gray-400 dark:text-gray-500" />
              ) : (
                <Bell className="h-6 w-6 text-gray-400 dark:text-gray-500" />
              )}
            </div>
            <h3 className="mt-3 text-sm font-semibold text-gray-900 dark:text-gray-100">
              No {activeTab === "unread" ? "unread " : ""}notifications
            </h3>
            <p className="mt-1 text-xs text-gray-500 dark:text-gray-400">
              New activity will appear here
            </p>
          </div>
        ) : (
          visibleNotifications.map((n) => (
            <NotificationCard
              key={n.id}
              id={n.id}
              subject={n.subject}
              time={dayjs(n.createdAt).fromNow()}
              isUnread={!n.isSeen}
              onClick={() => handleNotificationOnClick(n)}
              onRemind={handleRemind}
            />
          ))
        )}

        <div ref={loaderRef} className="flex justify-center py-4">
          {loading && (
            <Loader2 className="h-5 w-5 animate-spin text-primary-500" />
          )}
        </div>
      </div>
    </div>
  );
};

export default NotificationList;
