import React, { Children, ReactNode, useEffect, useRef } from 'react';
import { Box, Container, useViewport } from '@nova-hf/ui';
import Steps from 'beta/store/steps';
import { gsap } from 'gsap';
import { reaction } from 'mobx';
import { inject, observer } from 'mobx-react';
import { useRouter } from 'next/router';

type CheckoutLayoutProps = {
  steps?: Steps;
  children?: ReactNode;
  returnUrl?: string;
  sideOverviewChildren: ReactNode;
};

const CheckoutLayout = ({
  steps,
  children,
  returnUrl,
  sideOverviewChildren,
}: CheckoutLayoutProps) => {
  const router = useRouter();

  const host = useRef(null);
  const swipePanel = useRef(null);
  const sideCartWrapperRef = useRef(null);
  const sideCartContent = useRef(null);
  const mainContent = useRef(null);
  const { isLarge, isXLarge } = useViewport();
  const isDesktop = isLarge || isXLarge;

  useEffect(() => {
    if (sideCartWrapperRef.current && host.current) {
      const t = gsap.timeline();
      t.fromTo(
        host.current,
        { opacity: 0 },
        { position: 'relative', opacity: 1, ease: 'power4.inOut', duration: 0.5 },
      );
      t.fromTo(
        swipePanel.current,
        { right: 0 },
        { right: '100%', ease: 'power4.inOut', duration: 1 },
        '-=.5',
      );
      t.fromTo(
        sideCartWrapperRef.current,
        { alpha: 0 },
        { alpha: 1, ease: 'power4.inOut', duration: 0.2 },
        '-=1',
      );
      if (isDesktop) {
        t.fromTo(
          [sideCartContent.current, mainContent.current],
          {
            x: 40,
            opacity: 0,
          },
          {
            x: 0,
            opacity: 1,
            ease: 'power4.out',
            duration: 0.4,
            stagger: 0.15,
          },
          '-=0.2',
        );
      }
    }

    const stepReaction = reaction(
      () => steps?.onCompleteSteps,
      (onCompleteSteps) => {
        if ((onCompleteSteps as boolean) === true) {
          onClose();
        }
      },
    );

    return () => {
      stepReaction();
    };
  }, []);

  const onClose = () => {
    if (sideCartWrapperRef.current && host.current) {
      const t = gsap.timeline();

      t.to([sideCartContent.current, mainContent.current], {
        opacity: 0,
        ease: 'power4.inOut',
        duration: 0.25,
      });
      t.set(host.current, { zIndex: 2 });
      t.addLabel('fadeOut');
      if (isDesktop) {
        t.fromTo(
          sideCartWrapperRef.current,
          {
            alpha: 1,
          },
          {
            ease: 'power4.out',
            duration: 0.8,
          },
          'fadeOut-=0.15',
        );
        t.fromTo(
          swipePanel.current,
          { right: '100%' },
          { right: 0, ease: 'power4.out', duration: 0.8 },
          'fadeOut-=.15',
        );
      } else {
        t.fromTo(
          sideCartWrapperRef.current,
          {
            alpha: 1,
          },
          {
            alpha: 0,
            ease: 'power4.out',
            duration: 0.8,
          },
          'fadeOut-=0.15',
        );
      }
      t.to(
        host.current,
        {
          alpha: 0,
          ease: 'power4.inOut',
          onComplete: () => onComplete(),
          duration: 0.35,
        },
        'fadeOut+=0.3',
      );
      t.set(sideCartWrapperRef.current, { clearProps: 'all' });
      t.set(host.current, { clearProps: 'all' });
      t.set([sideCartContent.current, mainContent.current], { clearProps: 'all' });
    }
  };

  const onComplete = () => {
    if (returnUrl) {
      router?.push(returnUrl);
    }
  };

  return (
    <Box
      ref={host}
      inset="0"
      display="flex"
      flexDirection={{ sm: 'column', lg: 'column' }}
      style={{ maxHeight: '100vh' }}
    >
      <Box
        ref={sideCartWrapperRef}
        position={{ sm: 'unset', lg: 'fixed' }}
        left={0}
        top={0}
        width={{ sm: '100%', lg: '4/12', xl: '3/12' }}
        bottom={{ sm: undefined, lg: 0 }}
        background="black100"
        flexDirection="column"
      >
        <Box height="100%" ref={sideCartContent} display="flex" flexGrow={1} flexDirection="column">
          {Children.toArray(sideOverviewChildren).map((child) =>
            React.isValidElement(child)
              ? React.cloneElement(child, {
                  onClose: () => onClose(),
                })
              : child,
          )}
        </Box>
      </Box>
      <Box
        ref={mainContent}
        position={{ sm: undefined, lg: 'fixed' }}
        right={0}
        top={{ sm: undefined, lg: 0 }}
        bottom={0}
        background="white"
        width={{ sm: '100%', lg: '8/12', xl: '9/12' }}
        height={{ sm: '100%', lg: undefined }}
        overflow="scroll"
      >
        <Container
          paddingTop={7}
          paddingBottom={{ sm: 7, lg: 10 }}
          marginBottom={{ sm: 16, lg: 0 }}
          height="100%"
        >
          <Box display="flex" flexWrap="wrap" height="100%" width="100%">
            <Box position="relative" height="100%" width="100%">
              {children}
            </Box>
          </Box>
        </Container>
      </Box>
      <Box
        ref={swipePanel}
        position="fixed"
        left={0}
        top={0}
        right={0}
        bottom={0}
        background="black100"
        display={{ sm: 'none', lg: 'block' }}
      />
    </Box>
  );
};

const CheckoutLayoutWithSteps = inject('steps')(observer(CheckoutLayout));
export default CheckoutLayoutWithSteps;
