import Icon, { SyncOutlined } from "@ant-design/icons";
import { cloneDeep, isEmpty } from "lodash";
import { useMutation, useQuery } from "@apollo/client";
import { Button, Dropdown, Space } from "antd";
import { PageHeader } from "@ant-design/pro-layout";
import { useMemo, useState } from "react";
import { Responsive, WidthProvider } from "react-grid-layout";
import { useTranslation } from "react-i18next";
import { MdClose } from "react-icons/md";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { logImEXEvent } from "../../firebase/firebase.utils";
import { UPDATE_DASHBOARD_LAYOUT } from "../../graphql/user.queries";
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
import AlertComponent from "../alert/alert.component";
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
import { GenerateDashboardData } from "./dashboard-grid.utils";
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
import componentList from "./componentList.js";
import createDashboardQuery from "./createDashboardQuery.js";

import "./dashboard-grid.styles.scss";

const ResponsiveReactGridLayout = WidthProvider(Responsive);

const mapStateToProps = createStructuredSelector({
  currentUser: selectCurrentUser,
  bodyshop: selectBodyshop
});

const mapDispatchToProps = () => ({
  //setUserLanguage: language => dispatch(setUserLanguage(language))
});

export function DashboardGridComponent({ currentUser, bodyshop }) {
  const { t } = useTranslation();
  const [state, setState] = useState({
    ...(bodyshop.associations[0].user.dashboardlayout
      ? bodyshop.associations[0].user.dashboardlayout
      : { items: [], layout: {}, layouts: [] })
  });
  const notification = useNotification();

  const { loading, error, data, refetch } = useQuery(createDashboardQuery(state), {
    fetchPolicy: "network-only",
    nextFetchPolicy: "network-only"
  });

  const [updateLayout] = useMutation(UPDATE_DASHBOARD_LAYOUT);

  const handleLayoutChange = async (layout, layouts) => {
    logImEXEvent("dashboard_change_layout");

    setState({ ...state, layout, layouts });

    const result = await updateLayout({
      variables: {
        email: currentUser.email,
        layout: { ...state, layout, layouts }
      }
    });

    if (!isEmpty(result?.errors)) {
      notification.error({
        message: t("dashboard.errors.updatinglayout", {
          message: JSON.stringify(result.errors)
        })
      });
    }
  };

  const handleRemoveComponent = (key) => {
    logImEXEvent("dashboard_remove_component", { name: key });
    const idxToRemove = state.items.findIndex((i) => i.i === key);

    const items = cloneDeep(state.items);

    items.splice(idxToRemove, 1);
    setState({ ...state, items });
  };

  const handleAddComponent = (e) => {
    logImEXEvent("dashboard_add_component", { name: e.key });
    setState({
      ...state,
      items: [
        ...state.items,
        {
          i: e.key,
          x: (state.items.length * 2) % (state.cols || 12),
          y: 99, // puts it at the bottom
          w: componentList[e.key].w || 2,
          h: componentList[e.key].h || 2
        }
      ]
    });
  };

  const dashboardData = useMemo(() => GenerateDashboardData(data), [data]);

  const existingLayoutKeys = state.items.map((i) => i.i);

  const menuItems = Object.keys(componentList).map((key) => ({
    key: key,
    label: componentList[key].label,
    value: key,
    disabled: existingLayoutKeys.includes(key)
  }));

  const menu = { items: menuItems, onClick: handleAddComponent };

  if (error) return <AlertComponent message={error.message} type="error" />;

  return (
    <div>
      <PageHeader
        extra={
          <Space>
            <Button onClick={() => refetch()}>
              <SyncOutlined />
            </Button>
            <Dropdown menu={menu} trigger={["click"]}>
              <Button>{t("dashboard.actions.addcomponent")}</Button>
            </Dropdown>
          </Space>
        }
      />

      <ResponsiveReactGridLayout
        className="layout"
        breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }}
        cols={{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }}
        width="100%"
        layouts={state.layouts}
        onLayoutChange={handleLayoutChange}
      >
        {state.items.map((item) => {
          const TheComponent = componentList[item.i].component;
          return (
            <div
              key={item.i}
              data-grid={{
                ...item,
                minH: componentList[item.i].minH || 1,
                minW: componentList[item.i].minW || 1
              }}
            >
              <LoadingSkeleton loading={loading}>
                <Icon
                  component={MdClose}
                  key={item.i}
                  style={{
                    position: "absolute",
                    zIndex: "2",
                    right: ".25rem",
                    top: ".25rem",
                    cursor: "pointer"
                  }}
                  onClick={() => handleRemoveComponent(item.i)}
                />
                <TheComponent className="dashboard-card" bodyshop={bodyshop} data={dashboardData} />
              </LoadingSkeleton>
            </div>
          );
        })}
      </ResponsiveReactGridLayout>
    </div>
  );
}

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