import {CloseButton, Dialog, Heading, Portal, Stack, Text, useDisclosure} from "@chakra-ui/react";
import React, {useMemo, useState} from "react";
import {useAppStore} from "../appstore";
import {PrimaryButton} from "../components/primaryButton";
import {toast, updateToast} from "../components/ui/toaster";
import {api} from "../api";
import {OpenChangeDetails} from "@chakra-ui/react/dist/types/components/dialog/namespace";

export function SubmitOrderButton() {
  const {orderList, orderName} = useAppStore();
  const {open, onOpen, onClose} = useDisclosure();
  const [addingToCart, setAddingToCart] = useState(false);
  const [dialogMessage, setDialogMessage] = useState<React.ReactNode | null>(null);

  const invalidQuantityItems = useMemo(() => {
    return orderList.filter(oli => !Number.isInteger(oli.quantity) || oli.quantity <= 0)
  }, [orderList]);

  const outOfStockItems = useMemo(() => {
    return orderList.filter(oli => {
      if (!oli.stock_quantity || !Number.isInteger(oli.stock_quantity)) {
        return false; // we don't have what to compare with.
      }
      return oli.stock_quantity < oli.quantity;
    })
  }, [orderList]);

  const handleSubmit = async () => {
    if (invalidQuantityItems.length > 0 || outOfStockItems.length > 0) {
      setDialogMessage(
        <Stack mt="1rem" mb="1rem">
          {
            invalidQuantityItems.length > 0 && <Text textStyle="md">
                  Some items in your order have a quantity of 0.
              </Text>
          }
          {
            outOfStockItems.length > 0 && <Text textStyle="md">
                  Not enough stock quantity for some of the items in your order.
              </Text>
          }
          <Text textStyle="md">Do you still want to proceed?</Text>
        </Stack>
      )
      onOpen();
    } else {
      await addToCart();
    }
  };

  const addToCart = async () => {
    if (invalidQuantityItems.length === orderList.length) {
      toast({
        type: "error",
        title: "All order quantities are not valid",
        description: "Nothing to submit"
      });
      return;
    }
    const addToCartToastId = toast({
      title: "Adding to cart...",
      type: "loading",
    });

    setAddingToCart(true);

    try {
      const addToCartResult = await api.addToCart(
        orderList.filter(oli => !invalidQuantityItems.includes(oli))
          .map(oli => ({
            product_id: oli.id,
            qty: oli.quantity
          })));
      setAddingToCart(false);

      if (addToCartResult.success) {
        const okResults = addToCartResult.results.filter(result => result.ok);
        const failedResults = addToCartResult.results.filter(result => !result.ok);

        const type = failedResults.length === 0 ? 'success' : okResults.length > 0 ? 'warning' : 'error';

        updateToast(addToCartToastId, {
          type,
          title: `${okResults.length} items added`,
          description: `${failedResults.length} items failed to add`
        });

        if (okResults.length > 0) {
          window.location.href = addToCartResult.cart_url;
        }
      } else {
        updateToast(addToCartToastId, {type: 'error', title: 'Add to cart failed'});
      }
    } catch (e) {
      setAddingToCart(false);
      updateToast(addToCartToastId, {type: 'error', title: 'Add to cart failed'});
    }
  }

  const clearAndClose = () => {
    onClose();
    setDialogMessage(null);
  }

  const proceedOrder = async () => {
    // actual order submission logic
    await addToCart();
    clearAndClose();
  };

  return (
    <>
      <PrimaryButton loading={addingToCart}
                     loadingText="Adding items to Cart..."
                     colorScheme="blue"
                     variant="solid"
                     onClick={handleSubmit}
                     disabled={orderList.length === 0 || addingToCart}>
        Proceed to Cart
      </PrimaryButton>

      <Dialog.Root
        size={{md: "md"}}
        open={open}
        onOpenChange={(e: OpenChangeDetails) => {
          // @ts-expect-error
          if (!e.open) {
            clearAndClose();
          }
        }}
        closeOnInteractOutside={false}
        closeOnEscape={false}
        onEscapeKeyDown={() => {
          clearAndClose();
        }}
      >
        <Portal>
          <Dialog.Backdrop/>
          {/* @ts-expect-error chakra dialog typing issue */}
          <Dialog.Positioner>
            {/* @ts-expect-error chakra dialog typing issue */}
            <Dialog.Content>
              <Dialog.Body>
                <Stack gap="1rem" margin="1rem 0">
                  <Heading size="3xl">
                    Invalid quantities detected
                  </Heading>
                  <Stack>
                    {dialogMessage}
                    <Stack direction="row">
                      <PrimaryButton flex="1" onClick={clearAndClose}>
                        Cancel
                      </PrimaryButton>
                      <PrimaryButton flex="1" colorPalette="red" variant="solid" onClick={proceedOrder} ml={3}>
                        Proceed Anyway
                      </PrimaryButton>
                    </Stack>
                  </Stack>
                </Stack>
              </Dialog.Body>

              {/* @ts-expect-error chakra dialog typing issue */}
              <Dialog.CloseTrigger asChild>
                <CloseButton size="sm"/>
              </Dialog.CloseTrigger>
            </Dialog.Content>
          </Dialog.Positioner>
        </Portal>
      </Dialog.Root>
    </>
  );
}
