import React from "react";
import { useIntl } from "react-intl";

import { WindowTitle } from "@saleor/components/WindowTitle";
import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config";
import useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier";
import useShop from "@saleor/hooks/useShop";
import useCategorySearch from "@saleor/searches/useCategorySearch";
import useCollectionSearch from "@saleor/searches/useCollectionSearch";
import useProductTypeSearch from "@saleor/searches/useProductTypeSearch";
import useWarehouseSearch from "@saleor/searches/useWarehouseSearch";
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
import { SearchWarehouses_search_edges_node } from "@saleor/searches/types/SearchWarehouses";
import { decimal, maybe } from "../../misc";
import ProductCreatePage, {
  ProductCreatePageSubmitData
} from "../components/ProductCreatePage";
import { TypedProductCreateMutation } from "../mutations";
import { ProductCreate } from "../types/ProductCreate";
import {
  productListUrl,
  productUrl,
  ProductAddUrlDialog,
  ProductAddUrlQueryParams,
  productAddUrl
} from "../urls";
import ProductWarehousesDialog from "../components/ProductWarehousesDialog";

interface ProductCreateViewProps {
  params: ProductAddUrlQueryParams;
}

export const ProductCreateView: React.FC<ProductCreateViewProps> = ({
  params
}) => {
  const navigate = useNavigator();
  const notify = useNotifier();
  const shop = useShop();
  const intl = useIntl();
  const {
    loadMore: loadMoreCategories,
    search: searchCategory,
    result: searchCategoryOpts
  } = useCategorySearch({
    variables: DEFAULT_INITIAL_SEARCH_DATA
  });
  const {
    loadMore: loadMoreCollections,
    search: searchCollection,
    result: searchCollectionOpts
  } = useCollectionSearch({
    variables: DEFAULT_INITIAL_SEARCH_DATA
  });
  const {
    loadMore: loadMoreProductTypes,
    search: searchProductTypes,
    result: searchProductTypesOpts
  } = useProductTypeSearch({
    variables: DEFAULT_INITIAL_SEARCH_DATA
  });
  const { result: searchWarehousesOpts } = useWarehouseSearch({
    variables: {
      ...DEFAULT_INITIAL_SEARCH_DATA,
      first: 20
    }
  });
  const [warehouses, setWarehouses] = React.useState<
    SearchWarehouses_search_edges_node[]
  >([]);

  const [openModal, closeModal] = createDialogActionHandlers<
    ProductAddUrlDialog,
    ProductAddUrlQueryParams
  >(navigate, productAddUrl, params);

  const handleBack = () => navigate(productListUrl());

  const handleSuccess = (data: ProductCreate) => {
    if (data.productCreate.errors.length === 0) {
      notify({
        text: intl.formatMessage({
          defaultMessage: "Product created"
        })
      });
      navigate(productUrl(data.productCreate.product.id));
    }
  };

  return (
    <TypedProductCreateMutation onCompleted={handleSuccess}>
      {(productCreate, productCreateOpts) => {
        const handleSubmit = (formData: ProductCreatePageSubmitData) => {
          productCreate({
            variables: {
              attributes: formData.attributes.map(attribute => ({
                id: attribute.id,
                values: attribute.value
              })),
              basePrice: decimal(formData.basePrice),
              category: formData.category,
              chargeTaxes: formData.chargeTaxes,
              collections: formData.collections,
              descriptionJson: JSON.stringify(formData.description),
              isPublished: formData.isPublished,
              name: formData.name,
              productType: formData.productType,
              publicationDate:
                formData.publicationDate !== ""
                  ? formData.publicationDate
                  : null,
              seo: {
                description: formData.seoDescription,
                title: formData.seoTitle
              },
              sku: formData.sku,
              stocks: formData.stocks.map(stock => ({
                quantity: parseInt(stock.value, 0),
                warehouse: stock.id
              })),
              trackInventory: formData.trackInventory
            }
          });
        };

        return (
          <>
            <WindowTitle
              title={intl.formatMessage({
                defaultMessage: "Create Product",
                description: "window title"
              })}
            />
            <ProductCreatePage
              currency={maybe(() => shop.defaultCurrency)}
              categories={maybe(
                () => searchCategoryOpts.data.search.edges,
                []
              ).map(edge => edge.node)}
              collections={maybe(
                () => searchCollectionOpts.data.search.edges,
                []
              ).map(edge => edge.node)}
              disabled={productCreateOpts.loading}
              errors={productCreateOpts.data?.productCreate.errors || []}
              fetchCategories={searchCategory}
              fetchCollections={searchCollection}
              fetchProductTypes={searchProductTypes}
              header={intl.formatMessage({
                defaultMessage: "New Product",
                description: "page header"
              })}
              productTypes={maybe(() =>
                searchProductTypesOpts.data.search.edges.map(edge => edge.node)
              )}
              warehouses={warehouses}
              onBack={handleBack}
              onSubmit={handleSubmit}
              saveButtonBarState={productCreateOpts.status}
              fetchMoreCategories={{
                hasMore: maybe(
                  () => searchCategoryOpts.data.search.pageInfo.hasNextPage
                ),
                loading: searchCategoryOpts.loading,
                onFetchMore: loadMoreCategories
              }}
              fetchMoreCollections={{
                hasMore: maybe(
                  () => searchCollectionOpts.data.search.pageInfo.hasNextPage
                ),
                loading: searchCollectionOpts.loading,
                onFetchMore: loadMoreCollections
              }}
              fetchMoreProductTypes={{
                hasMore: maybe(
                  () => searchProductTypesOpts.data.search.pageInfo.hasNextPage
                ),
                loading: searchProductTypesOpts.loading,
                onFetchMore: loadMoreProductTypes
              }}
              onWarehouseEdit={() => openModal("edit-stocks")}
            />
            <ProductWarehousesDialog
              confirmButtonState="default"
              disabled={false}
              errors={[]}
              onClose={closeModal}
              open={params.action === "edit-stocks"}
              warehouses={searchWarehousesOpts.data?.search.edges.map(
                edge => edge.node
              )}
              warehousesWithStocks={warehouses.map(warehouse => warehouse.id)}
              onConfirm={data => {
                setWarehouses(
                  [
                    ...warehouses,
                    ...data.added.map(
                      addedId =>
                        searchWarehousesOpts.data.search.edges.find(
                          edge => edge.node.id === addedId
                        ).node
                    )
                  ].filter(warehouse => !data.removed.includes(warehouse.id))
                );
                closeModal();
              }}
            />
          </>
        );
      }}
    </TypedProductCreateMutation>
  );
};
export default ProductCreateView;
