// noinspection RegExpAnonymousGroup

import { BellFilled } from "@ant-design/icons";
import { useQuery } from "@apollo/client";
import { useSplitTreatments } from "@splitsoftware/splitio-react";
import { Badge, Layout, Menu, Spin, Tooltip } from "antd";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import { FaTasks } from "react-icons/fa";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { TASKS_CENTER_POLL_INTERVAL, useSocket } from "../../contexts/SocketIO/useSocket.js";
import { GET_UNREAD_COUNT } from "../../graphql/notifications.queries.js";
import { QUERY_MY_TASKS_COUNT } from "../../graphql/tasks.queries.js";
import { selectDarkMode, selectRecentItems, selectSelectedHeader } from "../../redux/application/application.selectors";
import { setModalContext } from "../../redux/modals/modals.actions";
import { signOutStart } from "../../redux/user/user.actions";
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
import day from "../../utils/day.js";
import { useIsEmployee } from "../../utils/useIsEmployee.js";
import NotificationCenterContainer from "../notification-center/notification-center.container.jsx";
import TaskCenterContainer from "../task-center/task-center.container.jsx";
import buildAccountingChildren from "./buildAccountingChildren.jsx";
import buildLeftMenuItems from "./buildLeftMenuItems.jsx";
import { toggleDarkMode } from "../../redux/application/application.actions";

// --- Redux mappings ---
const mapStateToProps = createStructuredSelector({
  currentUser: selectCurrentUser,
  recentItems: selectRecentItems,
  selectedHeader: selectSelectedHeader,
  bodyshop: selectBodyshop,
  darkMode: selectDarkMode
});

const mapDispatchToProps = (dispatch) => ({
  setBillEnterContext: (context) => dispatch(setModalContext({ context, modal: "billEnter" })),
  setTimeTicketContext: (context) => dispatch(setModalContext({ context, modal: "timeTicket" })),
  setPaymentContext: (context) => dispatch(setModalContext({ context, modal: "payment" })),
  setReportCenterContext: (context) => dispatch(setModalContext({ context, modal: "reportCenter" })),
  signOutStart: () => dispatch(signOutStart()),
  setCardPaymentContext: (context) => dispatch(setModalContext({ context, modal: "cardPayment" })),
  setTaskUpsertContext: (context) => dispatch(setModalContext({ context, modal: "taskUpsert" })),
  toggleDarkMode: () => dispatch(toggleDarkMode())
});

// --- Utility Hooks ---
function useUnreadNotifications(userAssociationId, isConnected, scenarioNotificationsOn) {
  const {
    data: unreadData,
    refetch: refetchUnread,
    loading: unreadLoading
  } = useQuery(GET_UNREAD_COUNT, {
    variables: { associationid: userAssociationId },
    fetchPolicy: "network-only",
    pollInterval: isConnected ? 0 : day.duration(60, "seconds").asMilliseconds(),
    skip: !userAssociationId || !scenarioNotificationsOn
  });

  const unreadCount = unreadData?.notifications_aggregate?.aggregate?.count ?? 0;

  useEffect(() => {
    if (userAssociationId) {
      refetchUnread().catch((e) => console.error(`Error fetching unread notifications: ${e?.message}`));
    }
  }, [refetchUnread, userAssociationId]);

  useEffect(() => {
    if (!isConnected && !unreadLoading && userAssociationId) {
      refetchUnread().catch((e) => console.error(`Error fetching unread notifications: ${e?.message}`));
    }
  }, [isConnected, unreadLoading, refetchUnread, userAssociationId]);

  return { unreadCount, unreadLoading };
}

function useIncompleteTaskCount(assignedToId, bodyshopId, isEmployee, isConnected) {
  const { data: taskCountData, loading: taskCountLoading } = useQuery(QUERY_MY_TASKS_COUNT, {
    variables: { assigned_to: assignedToId, bodyshopid: bodyshopId },
    skip: !assignedToId || !bodyshopId || !isEmployee,
    fetchPolicy: "network-only",
    pollInterval: isConnected ? 0 : TASKS_CENTER_POLL_INTERVAL
  });

  const incompleteTaskCount = taskCountData?.tasks_aggregate?.aggregate?.count ?? 0;
  return { incompleteTaskCount, taskCountLoading };
}

// --- Main Component ---
function Header({
  handleMenuClick,
  currentUser,
  bodyshop,
  selectedHeader,
  signOutStart,
  setBillEnterContext,
  setTimeTicketContext,
  setPaymentContext,
  setReportCenterContext,
  recentItems,
  setCardPaymentContext,
  setTaskUpsertContext,
  toggleDarkMode,
  darkMode
}) {
  // Feature flags
  const {
    treatments: { ImEXPay, DmsAp, Simple_Inventory }
  } = useSplitTreatments({
    attributes: {},
    names: ["ImEXPay", "DmsAp", "Simple_Inventory"],
    splitKey: bodyshop && bodyshop.imexshopid
  });

  // Contexts and hooks
  const { t } = useTranslation();
  const { isConnected, scenarioNotificationsOn } = useSocket();
  const [notificationVisible, setNotificationVisible] = useState(false);
  const [taskCenterVisible, setTaskCenterVisible] = useState(false);
  const baseTitleRef = useRef(document.title || "");
  const lastSetTitleRef = useRef("");
  const taskCenterRef = useRef(null);
  const notificationRef = useRef(null);
  const userAssociationId = bodyshop?.associations?.[0]?.id;
  const isEmployee = useIsEmployee(bodyshop, currentUser);

  // Data hooks
  const { unreadCount, unreadLoading } = useUnreadNotifications(
    userAssociationId,
    isConnected,
    scenarioNotificationsOn
  );
  const assignedToId = bodyshop?.employees?.find((e) => e.user_email === currentUser.email)?.id;
  const { incompleteTaskCount, taskCountLoading } = useIncompleteTaskCount(
    assignedToId,
    bodyshop?.id,
    isEmployee,
    isConnected
  );

  // --- Effects ---

  // Update document title with unread count
  useEffect(() => {
    const updateTitle = () => {
      const currentTitle = document.title;
      if (currentTitle !== lastSetTitleRef.current) {
        const baseTitleMatch = currentTitle.match(/^\(\d+\)\s*(.*)$/);
        baseTitleRef.current = baseTitleMatch ? baseTitleMatch[1] : currentTitle;
      }
      const newTitle = unreadCount > 0 ? `(${unreadCount}) ${baseTitleRef.current}` : baseTitleRef.current;
      if (document.title !== newTitle) {
        document.title = newTitle;
        lastSetTitleRef.current = newTitle;
      }
    };
    updateTitle();
    const interval = setInterval(updateTitle, 100);
    return () => {
      clearInterval(interval);
      document.title = baseTitleRef.current;
    };
  }, [unreadCount]);

  // Handle outside clicks for popovers
  useEffect(() => {
    const handleClickOutside = (event) => {
      const isNotificationClick = event.target.closest("#header-notifications");
      const isTaskCenterClick = event.target.closest("#header-taskcenter");

      if (isNotificationClick && scenarioNotificationsOn) {
        setTaskCenterVisible(false); // Close task center
        return;
      }

      if (isTaskCenterClick) {
        setNotificationVisible(scenarioNotificationsOn ? false : notificationVisible); // Close notification center if enabled
        return;
      }

      if (taskCenterVisible && taskCenterRef.current && !taskCenterRef.current.contains(event.target)) {
        setTaskCenterVisible(false);
      }

      if (
        scenarioNotificationsOn &&
        notificationVisible &&
        notificationRef.current &&
        !notificationRef.current.contains(event.target)
      ) {
        setNotificationVisible(false);
      }
    };

    document.addEventListener("mousedown", handleClickOutside);
    return () => document.removeEventListener("mousedown", handleClickOutside);
  }, [taskCenterVisible, notificationVisible, scenarioNotificationsOn]);

  // --- Event Handlers ---
  const handleTaskCenterClick = useCallback(
    (e) => {
      setTaskCenterVisible((prev) => {
        if (prev) return false;
        return true;
      });
      if (handleMenuClick) handleMenuClick(e);
    },
    [handleMenuClick]
  );

  const handleNotificationClick = useCallback(
    (e) => {
      setNotificationVisible((prev) => {
        if (prev) return false;
        return true;
      });
      if (handleMenuClick) handleMenuClick(e);
    },
    [handleMenuClick]
  );

  const handleDarkModeToggle = useCallback(() => {
    toggleDarkMode();
  }, [toggleDarkMode]);

  // --- Menu Items ---

  // built externally to keep the component clean, but on this level to prevent unnecessary re-renders
  const accountingChildren = useMemo(
    () =>
      buildAccountingChildren({
        t,
        bodyshop,
        currentUser,
        setBillEnterContext,
        setPaymentContext,
        setCardPaymentContext,
        setTimeTicketContext,
        ImEXPay,
        DmsAp,
        Simple_Inventory
      }),
    [
      t,
      bodyshop,
      currentUser,
      setBillEnterContext,
      setPaymentContext,
      setCardPaymentContext,
      setTimeTicketContext,
      ImEXPay,
      DmsAp,
      Simple_Inventory
    ]
  );

  // Built externally to keep the component clean
  const leftMenuItems = useMemo(
    () =>
      buildLeftMenuItems({
        t,
        bodyshop,
        recentItems,
        setTaskUpsertContext,
        setReportCenterContext,
        signOutStart,
        accountingChildren,
        darkMode,
        handleDarkModeToggle
      }),
    [
      t,
      bodyshop,
      recentItems,
      setTaskUpsertContext,
      setReportCenterContext,
      signOutStart,
      accountingChildren,
      darkMode,
      handleDarkModeToggle
    ]
  );

  const rightMenuItems = useMemo(() => {
    const items = [];
    if (scenarioNotificationsOn) {
      items.push({
        key: "notifications",
        id: "header-notifications",
        icon: unreadLoading ? (
          <Spin size="small" />
        ) : (
          <Badge offset={[8, 0]} size="small" count={isEmployee ? unreadCount : 0}>
            <BellFilled />
          </Badge>
        ),
        onClick: handleNotificationClick
      });
    }
    items.push({
      key: "taskcenter",
      id: "header-taskcenter",
      icon: taskCountLoading ? (
        <Spin size="small" />
      ) : (
        <Badge offset={[8, 0]} size="small" count={incompleteTaskCount > 0 ? incompleteTaskCount : 0} showZero={false}>
          <Tooltip title={t("menus.header.tasks")}>
            <FaTasks />
          </Tooltip>
        </Badge>
      ),
      onClick: handleTaskCenterClick
    });

    return items;
  }, [
    scenarioNotificationsOn,
    unreadLoading,
    unreadCount,
    taskCountLoading,
    incompleteTaskCount,
    isEmployee,
    handleNotificationClick,
    handleTaskCenterClick,
    t
  ]);

  // --- Render ---
  return (
    <Layout.Header style={{ padding: 0, background: "#001529" }}>
      <div style={{ display: "flex", alignItems: "center", height: "100%", overflow: "hidden" }}>
        <div style={{ flexGrow: 1, overflowX: "auto", whiteSpace: "nowrap" }}>
          <Menu
            mode="horizontal"
            theme="dark"
            selectedKeys={[selectedHeader]}
            onClick={handleMenuClick}
            subMenuCloseDelay={0.3}
            items={leftMenuItems}
            style={{ borderBottom: "none", background: "transparent", minWidth: "100%" }}
          />
        </div>
        <div style={{ width: 120, flexShrink: 0 }}>
          <Menu
            mode="horizontal"
            theme="dark"
            selectedKeys={[selectedHeader]}
            onClick={handleMenuClick}
            subMenuCloseDelay={0.3}
            items={rightMenuItems}
            style={{ borderBottom: "none", background: "transparent", justifyContent: "flex-end" }}
          />
        </div>
      </div>
      {scenarioNotificationsOn && (
        <div ref={notificationRef}>
          <NotificationCenterContainer
            visible={notificationVisible}
            onClose={() => setNotificationVisible(false)}
            unreadCount={unreadCount}
          />
        </div>
      )}
      <div ref={taskCenterRef}>
        <TaskCenterContainer
          incompleteTaskCount={incompleteTaskCount}
          visible={taskCenterVisible}
          onClose={() => setTaskCenterVisible(false)}
        />
      </div>
    </Layout.Header>
  );
}

export default connect(mapStateToProps, mapDispatchToProps)(Header);
