import { appsListPath } from "@dashboard/apps/urls";
import {
  extensionMountPoints,
  useExtensions,
} from "@dashboard/apps/useExtensions";
import { useUser } from "@dashboard/auth";
import { categoryListUrl } from "@dashboard/categories/urls";
import { collectionListUrl } from "@dashboard/collections/urls";
import { MARKETPLACE_URL } from "@dashboard/config";
import { configurationMenuUrl } from "@dashboard/configuration";
import { getConfigMenuItemsPermissions } from "@dashboard/configuration/utils";
import { customerListUrl } from "@dashboard/customers/urls";
import { saleListUrl, voucherListUrl } from "@dashboard/discounts/urls";
import { giftCardListUrl } from "@dashboard/giftCards/urls";
import { PermissionEnum } from "@dashboard/graphql";
import { commonMessages, sectionNames } from "@dashboard/intl";
import { marketplaceUrlResolver } from "@dashboard/marketplace/marketplace-url-resolver";
import { orderDraftListUrl, orderListUrl } from "@dashboard/orders/urls";
import { pageListPath } from "@dashboard/pages/urls";
import { productListUrl } from "@dashboard/products/urls";
import { languageListUrl } from "@dashboard/translations/urls";
import {
  ConfigurationIcon,
  CustomersIcon,
  HomeIcon,
  MarketplaceIcon,
  OrdersIcon,
  ProductsIcons,
  StorefrontIcon,
  TranslationsIcon,
  VouchersIcon,
} from "@saleor/macaw-ui/next";
import isEmpty from "lodash/isEmpty";
import React from "react";
import { useIntl } from "react-intl";

import { SidebarMenuItem } from "./types";
import { mapToExtensionsItems } from "./utils";

const iconSettings = {
  color: "iconNeutralSubdued",
  size: "medium",
} as const;

export function useMenuStructure() {
  const extensions = useExtensions(extensionMountPoints.NAVIGATION_SIDEBAR);
  const intl = useIntl();
  const { user } = useUser();

  const appExtensionsHeaderItem: SidebarMenuItem = {
    id: "extensions",
    label: intl.formatMessage(sectionNames.appExtensions),
    type: "divider",
    paddingY: 4,
  };

  // This will be deleted when Marketplace is released
  // Consider this solution as temporary
  const getAppSection = (): SidebarMenuItem => {
    if (MARKETPLACE_URL) {
      return {
        icon: <MarketplaceIcon {...iconSettings} />,
        label: intl.formatMessage(sectionNames.apps),
        permissions: [PermissionEnum.MANAGE_APPS],
        id: "apps_section",
        type: "itemGroup",
        children: [
          {
            label: intl.formatMessage(sectionNames.apps),
            id: "apps",
            url: appsListPath,
            type: "item",
          },
          {
            label: intl.formatMessage(sectionNames.marketplace),
            id: "marketplace-saleor-apps",
            url: marketplaceUrlResolver.getSaleorAppsDashboardPath(),
            type: "item",
          },
          {
            label: intl.formatMessage(sectionNames.appTemplateGallery),
            id: "marketplace-template-gallery",
            url: marketplaceUrlResolver.getTemplateGalleryDashboardPath(),
            type: "item",
          },
        ],
      };
    }

    return {
      icon: <MarketplaceIcon {...iconSettings} />,
      label: intl.formatMessage(sectionNames.apps),
      permissions: [PermissionEnum.MANAGE_APPS],
      id: "apps",
      url: appsListPath,
      type: "item",
    };
  };

  const menuItems: SidebarMenuItem[] = [
    {
      icon: <HomeIcon {...iconSettings} />,
      label: intl.formatMessage(sectionNames.home),
      id: "home",
      url: "/",
      type: "item",
    },
    {
      children: [
        {
          label: intl.formatMessage(sectionNames.categories),
          id: "categories",
          url: categoryListUrl(),
          permissions: [PermissionEnum.MANAGE_PRODUCTS],
          type: "item",
        },
        {
          label: intl.formatMessage(sectionNames.collections),
          id: "collections",
          url: collectionListUrl(),
          permissions: [PermissionEnum.MANAGE_PRODUCTS],
          type: "item",
        },
        {
          label: intl.formatMessage(sectionNames.giftCards),
          id: "giftCards",
          url: giftCardListUrl(),
          permissions: [PermissionEnum.MANAGE_GIFT_CARD],
          type: "item",
        },
        ...mapToExtensionsItems(
          extensions.NAVIGATION_CATALOG,
          appExtensionsHeaderItem,
        ),
      ],
      icon: <ProductsIcons {...iconSettings} />,
      url: productListUrl(),
      label: intl.formatMessage(commonMessages.products),
      permissions: [
        PermissionEnum.MANAGE_GIFT_CARD,
        PermissionEnum.MANAGE_PRODUCTS,
      ],
      id: "products",
      type: "itemGroup",
    },
    {
      children: [
        {
          label: intl.formatMessage(commonMessages.drafts),
          permissions: [PermissionEnum.MANAGE_ORDERS],
          id: "order-drafts",
          url: orderDraftListUrl(),
          type: "item",
        },
        ...mapToExtensionsItems(
          extensions.NAVIGATION_ORDERS,
          appExtensionsHeaderItem,
        ),
      ],
      icon: <OrdersIcon {...iconSettings} />,
      label: intl.formatMessage(sectionNames.orders),
      permissions: [PermissionEnum.MANAGE_ORDERS],
      id: "orders",
      url: orderListUrl(),
      type: "itemGroup",
    },
    {
      children: !isEmpty(extensions.NAVIGATION_CUSTOMERS) && [
        {
          label: intl.formatMessage(sectionNames.customers),
          permissions: [PermissionEnum.MANAGE_USERS],
          id: "customers",
          url: customerListUrl(),
          type: "item",
        },
        ...mapToExtensionsItems(
          extensions.NAVIGATION_CUSTOMERS,
          appExtensionsHeaderItem,
        ),
      ],
      icon: <CustomersIcon {...iconSettings} />,
      label: intl.formatMessage(sectionNames.customers),
      permissions: [PermissionEnum.MANAGE_USERS],
      id: "customers",
      url: customerListUrl(),
      type: !isEmpty(extensions.NAVIGATION_CUSTOMERS) ? "itemGroup" : "item",
    },
    {
      children: [
        {
          label: intl.formatMessage(sectionNames.vouchers),
          id: "vouchers",
          url: voucherListUrl(),
          type: "item",
        },
        ...mapToExtensionsItems(
          extensions.NAVIGATION_DISCOUNTS,
          appExtensionsHeaderItem,
        ),
      ],
      icon: <VouchersIcon {...iconSettings} />,
      label: intl.formatMessage(commonMessages.discounts),
      permissions: [PermissionEnum.MANAGE_DISCOUNTS],
      url: saleListUrl(),
      id: "discounts",
      type: "itemGroup",
    },
    {
      children: !isEmpty(extensions.NAVIGATION_PAGES) && [
        ...mapToExtensionsItems(
          extensions.NAVIGATION_PAGES,
          appExtensionsHeaderItem,
        ),
      ],
      icon: <StorefrontIcon {...iconSettings} />,
      label: intl.formatMessage(sectionNames.content),
      permissions: [PermissionEnum.MANAGE_PAGES],
      id: "pages",
      url: pageListPath,
      type: !isEmpty(extensions.NAVIGATION_PAGES) ? "itemGroup" : "item",
    },
    {
      children: !isEmpty(extensions.NAVIGATION_TRANSLATIONS) && [
        ...mapToExtensionsItems(
          extensions.NAVIGATION_TRANSLATIONS,
          appExtensionsHeaderItem,
        ),
      ],
      icon: <TranslationsIcon {...iconSettings} />,
      label: intl.formatMessage(sectionNames.translations),
      permissions: [PermissionEnum.MANAGE_TRANSLATIONS],
      id: "translations",
      url: languageListUrl,
      type: !isEmpty(extensions.NAVIGATION_TRANSLATIONS) ? "itemGroup" : "item",
    },
    getAppSection(),
    {
      icon: <ConfigurationIcon {...iconSettings} />,
      label: intl.formatMessage(sectionNames.configuration),
      permissions: getConfigMenuItemsPermissions(intl),
      id: "configure",
      url: configurationMenuUrl,
      type: "item",
    },
  ];

  const isMenuItemPermitted = (menuItem: SidebarMenuItem) => {
    const userPermissions = (user?.userPermissions || []).map(
      permission => permission.code,
    );
    if (!menuItem?.permissions || menuItem?.permissions?.length < 1) {
      return true;
    }
    return menuItem.permissions.some(permission =>
      userPermissions.includes(permission),
    );
  };

  const getFilteredMenuItems = (menuItems: SidebarMenuItem[]) =>
    menuItems.filter(isMenuItemPermitted);

  return menuItems.reduce(
    (resultItems: SidebarMenuItem[], menuItem: SidebarMenuItem) => {
      if (!isMenuItemPermitted(menuItem)) {
        return resultItems;
      }
      const { children } = menuItem;
      const filteredChildren = children
        ? getFilteredMenuItems(children)
        : undefined;

      return [...resultItems, { ...menuItem, children: filteredChildren }];
    },
    [],
  );
}
