"use client";

import { useEffect, useRef, useState } from "react";
import { CgLock, CgShoppingCart } from "react-icons/cg";
import { BiMessageSquare } from "react-icons/bi";
import { BsTag } from "react-icons/bs";
import { useAppSelector } from "@/app/store/hooks";
import {
  fetchNotifications,
  markAllNotificationsAsRead,
  markNotificationAsRead,
  markNotificationAsUnread,
} from "@/lib/actions/notificationActions";
import { checkAuthErrorGet } from "@/lib/checkAuthError";
import { useRouter } from "next/navigation";
import { useDispatch } from "react-redux";
import { useTranslations } from "next-intl";
import { useLocale } from "next-intl";
import { toast } from "react-toastify";

function timeAgo(dateString: string) {
  if (!dateString) return "";
  const now = new Date();
  const date = new Date(dateString);
  const diffMs = now.getTime() - date.getTime();
  const seconds = Math.floor(diffMs / 1000);
  const minutes = Math.floor(seconds / 60);
  const hours = Math.floor(minutes / 60);
  const days = Math.floor(hours / 24);

  if (seconds < 60) return "just now";
  if (minutes < 60) return `${minutes} minute${minutes !== 1 ? "s" : ""} ago`;
  if (hours < 24) return `${hours} hour${hours !== 1 ? "s" : ""} ago`;
  if (days < 7) return `${days} day${days !== 1 ? "s" : ""} ago`;
  return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(
    2,
    "0"
  )}-${String(date.getDate()).padStart(2, "0")} ${String(
    date.getHours()
  ).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}`;
}

export default function NotificationDropdown() {
  const t = useTranslations();
  const locale = useLocale();
  const [isOpen, setIsOpen] = useState(false);
  const [notifications, setNotifications] = useState<any[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [page, setPage] = useState(1);
  const [limit] = useState(10);
  const [totalPages, setTotalPages] = useState(1);
  const [hasMore, setHasMore] = useState(true);
  const notificationsContainerRef = useRef<HTMLDivElement>(null);
  const dropdownRef = useRef(null);
  const { user } = useAppSelector((state) => state.auth);
  const token = user?.token;
  const router = useRouter();
  const dispatch = useDispatch();
  const [isUnreadNotification, setIsUnreadNotification] =
    useState<boolean>(false);

  const toggleDropdown = () => setIsOpen((prev) => !prev);

  useEffect(() => {
    // if (!isOpen || !token) return;
    if (!token) return;
    const fetchData = async () => {
      setLoading(true);
      setError(null);
      try {
        const res = await fetchNotifications(token, page, limit);
        const notificationsArr = Array.isArray(res.data?.data)
          ? res.data.data
          : [];
        notificationsArr.forEach((notification: any) => {
          if (!notification?.isRead) {
            setIsUnreadNotification(true);
          }
        });

        setNotifications((prev) =>
          page === 1 ? notificationsArr : [...prev, ...notificationsArr]
        );
        const totalPagesVal =
          typeof res.data?.totalPages === "number"
            ? res.data.totalPages
            : res.data?.pagination?.totalPages || 1;
        setTotalPages(totalPagesVal);
        setHasMore(page < totalPagesVal);
      } catch (error) {
        if (checkAuthErrorGet(error, dispatch, router)) return;
        setError(t("notification_dropdown.error"));
      } finally {
        setLoading(false);
      }
    };
    fetchData();
  }, [isOpen, token, page, limit, locale]);

  useEffect(() => {
    const handleClickOutside = (event: MouseEvent) => {
      if (
        dropdownRef.current &&
        !(dropdownRef.current as any).contains(event.target)
      ) {
        setIsOpen(false);
      }
    };
    document.addEventListener("mousedown", handleClickOutside);
    return () => document.removeEventListener("mousedown", handleClickOutside);
  }, []);

  const handleMarkAsRead = async (id: string) => {
    if (!token) return;
    try {
      await markNotificationAsRead(id, token);
      setNotifications((prev) => {
        let hasUnread = false;

        const updated = prev.map((n) => {
          if (n.id === id) {
            return { ...n, isRead: true };
          }

          if (!n.isRead) {
            hasUnread = true;
          }

          return n;
        });

        setIsUnreadNotification(hasUnread);

        return updated;
      });
    } catch (err: any) {
      if (checkAuthErrorGet(err, dispatch, router)) return;
    }
  };

  const handleMarkAsUnread = async (id: string) => {
    if (!token) return;
    try {
      await markNotificationAsUnread(id, token);
      setNotifications((prev) =>
        prev.map((n) => (n.id === id ? { ...n, isRead: false } : n))
      );
      setIsUnreadNotification(true);
    } catch (err: any) {
      if (checkAuthErrorGet(err, dispatch, router)) return;
    }
  };

  const handleMarkAllAsRead = async () => {
    if (!token) return;
    if(!isUnreadNotification) return;
    try {
      const res = await markAllNotificationsAsRead(token);
      toast.success(res?.data?.message || "All notifications marked as read");
      setNotifications((prev) => prev.map((n) => ({ ...n, isRead: true })));
      setIsUnreadNotification(false);
    } catch (err: any) {
      if (checkAuthErrorGet(err, dispatch, router)) return;
      toast.error(err?.response?.data?.message || "Failed to mark all as read");
    }
  };

  const getIcon = (type: string) => {
    switch (type) {
      case "help_center_request":
        return <CgShoppingCart className="w-5 h-5" />;
      case "message":
        return <BiMessageSquare className="w-5 h-5" />;
      case "tag":
        return <BsTag className="w-5 h-5" />;
      case "lock":
        return <CgLock className="w-5 h-5" />;
      default:
        return <BiMessageSquare className="w-5 h-5" />;
    }
  };

  const handleScroll = (e: React.UIEvent<HTMLDivElement>) => {
    const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
    if (scrollHeight - scrollTop <= clientHeight + 10 && hasMore && !loading) {
      setPage((prev) => prev + 1);
    }
  };

  return (
    <div className="relative" ref={dropdownRef}>
      <div
        onClick={toggleDropdown}
        className={`overflow-hidden cursor-pointer ${isOpen ? "active" : ""}`}
      >
        <svg
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          xmlns="http://www.w3.org/2000/svg"
        >
          <path
            d="M12 22C13.1 22 14 21.1 14 20H10C10 21.1 10.9 22 12 22ZM18 16V11C18 7.93 16.37 5.36 13.5 4.68V4C13.5 3.17 12.83 2.5 12 2.5C11.17 2.5 10.5 3.17 10.5 4V4.68C7.64 5.36 6 7.92 6 11V16L4 18V19H20V18L18 16ZM16 17H8V11C8 8.52 9.51 6.5 12 6.5C14.49 6.5 16 8.52 16 11V17Z"
            fill="#1E293B"
            className="dark:fill-white"
          />
        </svg>
        {notifications.some((n) => !n.isRead) && (
          <span
            className="
        absolute -top-1.5 -right-1
        bg-red-500 text-white
        text-[10px] font-semibold
        px-[6px] py-[2px]
        rounded-full shadow-sm
        leading-none
        min-w-[16px] min-h-[16px] flex items-center justify-center
      "
          >
            {notifications.filter((n) => !n.isRead).length > 99
              ? "99+"
              : notifications.filter((n) => !n.isRead).length}
          </span>
        )}
      </div>
      {isOpen && (
        <div className="absolute left-1/2 transform -translate-x-1/2 mt-2 w-96 bg-white border border-neutrals200 shadow-Shadow1 rounded-lg z-40 overflow-hidden dark:bg-background dark:border-darkborder">
          <div className="flex items-center justify-between p-5 border-b border-neutrals200 dark:bg-darkbg dark:border-darkborder">
            <div className="text-xl font-bold dark:text-white">
              {t("notification_dropdown.title")}
            </div>
            <button
              onClick={handleMarkAllAsRead}
              className="text-sm font-medium text-primary500 underline underline-offset-2 hover:text-primary600 dark:text-primary400"
            >
              {isUnreadNotification
                ? t("notification_dropdown.mark_all_as_read")
                : t("notification_dropdown.no_notifications")}
            </button>
          </div>
          <div
            ref={notificationsContainerRef}
            onScroll={handleScroll}
            className="bg-white p-2.5 flex flex-col gap-2.5 max-h-96 overflow-y-auto dark:bg-background"
          >
            {loading && (
              <div className="text-center text-neutrals500 py-8">
                {t("notification_dropdown.loading")}
              </div>
            )}
            {error && (
              <div className="text-center text-red-500 py-8">
                {t("notification_dropdown.error")}
              </div>
            )}
            {!loading && !error && notifications.length === 0 && (
              <div className="text-center text-neutrals500 py-8">
                {t("notification_dropdown.no_notifications")}
              </div>
            )}
            {notifications.map((note, index) => (
              <div
                key={note.id || index}
                className={`relative flex p-2.5 rounded-lg gap-2.5 cursor-pointer hover:bg-neutrals50 dark:hover:bg-darkbg ${
                  !note.isRead
                    ? "bg-neutrals50 dark:bg-darkbg"
                    : "bg-white dark:bg-background"
                }`}
                onClick={() =>
                  note.isRead
                    ? handleMarkAsUnread(note.id)
                    : handleMarkAsRead(note.id)
                }
              >
                {!note.isRead && (
                  <span className="absolute top-2 right-2 w-2 h-2 rounded-full bg-primary500 dark:bg-primary400" />
                )}
                <div
                  className={`shrink-0 w-11 h-11 rounded-full flex items-center justify-center ${
                    !note.isRead ? "bg-neutrals50" : "bg-neutrals50"
                  }`}
                >
                  {getIcon(note.type)}
                </div>
                <div className="text-sm">
                  <div className="text-sm font-bold text-neutrals800 mb-1 dark:text-white">
                    {note.title}
                  </div>
                  <div className="text-neutrals500 text-sm dark:text-neutrals400">
                    {note.description}
                  </div>
                  <div className="text-xs text-gray-400 mt-1">
                    {timeAgo(note.createdAt)}
                  </div>
                </div>
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}
