import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { Box, Button } from '@chakra-ui/react';
import { HugeiconsIcon } from '@hugeicons/react';
import { CheckmarkCircle02Icon } from '@hugeicons/core-free-icons';
import { CodeTab, PreviewTab, TabsLayout } from '../../components/common/TabsLayout';
import useComponentProps from '../../hooks/useComponentProps';
import { ComponentPropsProvider } from '../../components/context/ComponentPropsContext';
import { useColorModeValue } from '../../components/setup/color-mode';

import CodeExample from '../../components/code/CodeExample';
import Dependencies from '../../components/code/Dependencies';
import PropTable from '../../components/common/Preview/PropTable';
import Customize from '../../components/common/Preview/Customize';
import PreviewSlider from '../../components/common/Preview/PreviewSlider';
import PreviewSwitch from '../../components/common/Preview/PreviewSwitch';
import PreviewSelect from '../../components/common/Preview/PreviewSelect';
import PreviewInput from '../../components/common/Preview/PreviewInput';
import PreviewColorPickerCustom from '../../components/common/Preview/PreviewColorPickerCustom';
import RefreshButton from '../../components/common/Preview/RefreshButton';

import SwipeToast from '../../content/Micro/SwipeToast/SwipeToast';
import { swipeToast } from '../../constants/code/Micro/swipeToastCode';

const DEFAULT_PROPS = {
  title: 'File archived',
  description: 'Moved to Archive',
  actionLabel: 'Undo',
  background: '#27272a',
  color: '#f5f5f5',
  fuseColor: '#f5a524',
  width: 356,
  radius: 12,
  slideMs: 400,
  settleBounce: 0.2,
  swipeDistance: 40,
  duration: 4000,
  fuse: 'bottom',
  pauseOnHover: true,
  closeButton: false,
  inline: true
};

const FUSE_OPTIONS = [
  { value: 'bottom', label: 'Bottom' },
  { value: 'top', label: 'Top' },
  { value: 'none', label: 'None' }
];
const MAX_TOASTS = 3;

const SwipeToastDemo = () => {
  const { props, updateProp, resetProps, hasChanges } = useComponentProps(DEFAULT_PROPS);
  const {
    title,
    description,
    actionLabel,
    background,
    color,
    fuseColor,
    width,
    radius,
    slideMs,
    settleBounce,
    swipeDistance,
    duration,
    fuse,
    pauseOnHover,
    closeButton,
    inline
  } = props;

  const renderedBackground = useColorModeValue(
    background === DEFAULT_PROPS.background ? '#ffffff' : background,
    background
  );
  const renderedColor = useColorModeValue(color === DEFAULT_PROPS.color ? '#18181b' : color, color);

  const [toasts, setToasts] = useState([]);
  const nextId = useRef(0);
  const show = useCallback(() => {
    setToasts(current => {
      const next = [...current, { id: nextId.current++, open: true }];
      const live = next.filter(t => t.open);
      if (live.length > MAX_TOASTS) {
        const oldest = live[0].id;
        return next.map(t => (t.id === oldest ? { ...t, open: false } : t));
      }
      return next;
    });
  }, []);
  const remove = useCallback(id => setToasts(current => current.filter(t => t.id !== id)), []);
  const reset = () => {
    setToasts([]);
    show();
  };
  useEffect(() => {
    show();
  }, [show]);

  const propData = useMemo(
    () => [
      { name: 'title', type: 'ReactNode', default: '"File archived"', description: 'The first line.' },
      { name: 'description', type: 'ReactNode', default: '""', description: 'The dimmer second line. Empty hides it.' },
      { name: 'icon', type: 'ReactNode', default: 'undefined', description: 'An 18px icon before the text.' },
      { name: 'actionLabel', type: 'ReactNode', default: '""', description: 'The inverted button. Empty hides it.' },
      {
        name: 'onAction',
        type: '() => void',
        default: '-',
        description: 'Called when the action is pressed, before the close.'
      },
      {
        name: 'open',
        type: 'boolean',
        default: 'true',
        description: 'Flip to false to close from outside. True again re-enters.'
      },
      {
        name: 'onClose',
        type: '(reason) => void',
        default: '-',
        description:
          'Called after the exit, and after the inline slot has collapsed. Reason is timeout, swipe, action, close, escape or programmatic.'
      },
      {
        name: 'background',
        type: 'string',
        default: '"#27272a"',
        description: 'The card surface, and the action text.'
      },
      {
        name: 'color',
        type: 'string',
        default: '"#f5f5f5"',
        description: 'Ink: title, description at 62% and the action fill.'
      },
      { name: 'fuseColor', type: 'string', default: '"#f5a524"', description: 'The burning line.' },
      {
        name: 'width',
        type: 'number',
        default: '356',
        description: 'Card width in pixels, capped at the parent when inline.'
      },
      { name: 'radius', type: 'number', default: '12', description: 'Corner radius in pixels.' },
      { name: 'slideMs', type: 'number', default: '400', description: 'How long the rise and the drop take.' },
      {
        name: 'settleBounce',
        type: 'number',
        default: '0.2',
        description: 'Overshoot of the return after an abandoned swipe. 0 stops dead.'
      },
      {
        name: 'swipeDistance',
        type: 'number',
        default: '40',
        description: 'How far a slow drag must go before release dismisses. A flick always does.'
      },
      {
        name: 'duration',
        type: 'number',
        default: '4000',
        description: 'Milliseconds until it closes itself. Changing it re-arms the fuse. 0 keeps it until dismissed.'
      },
      {
        name: 'fuse',
        type: '"bottom" | "top" | "none"',
        default: '"bottom"',
        description: 'Which edge the line burns along. None keeps the timer but shows nothing.'
      },
      {
        name: 'pauseOnHover',
        type: 'boolean',
        default: 'true',
        description: 'Hovering freezes the line and the timer.'
      },
      { name: 'closeButton', type: 'boolean', default: 'false', description: 'Adds a cross at the end of the row.' },
      {
        name: 'inline',
        type: 'boolean',
        default: 'false',
        description: 'In flow inside the parent instead of fixed to the bottom-right of the viewport.'
      },
      { name: 'dismissible', type: 'boolean', default: 'true', description: 'Off removes the swipe and Escape.' },
      { name: 'className', type: 'string', default: '""', description: 'Extra classes for the root.' }
    ],
    []
  );

  return (
    <ComponentPropsProvider props={props} defaultProps={DEFAULT_PROPS} resetProps={resetProps} hasChanges={hasChanges}>
      <TabsLayout>
        <PreviewTab>
          <Box position="relative" className="demo-container" h={400} overflow="hidden">
            <RefreshButton onClick={reset} />
            <Button
              position="absolute"
              top="24px"
              left="50%"
              transform="translateX(-50%)"
              size="sm"
              variant="ghost"
              fontSize="13px"
              fontWeight={500}
              rounded="full"
              onClick={show}
            >
              Show toast
            </Button>
            <Box
              position="absolute"
              left="24px"
              right="24px"
              bottom="32px"
              display="flex"
              flexDirection="column"
              alignItems="flex-end"
            >
              {toasts.map(toast => (
                <SwipeToast
                  key={toast.id}
                  open={toast.open}
                  onClose={() => remove(toast.id)}
                  icon={<HugeiconsIcon icon={CheckmarkCircle02Icon} size={18} strokeWidth={2} />}
                  title={title}
                  description={description}
                  actionLabel={actionLabel}
                  background={renderedBackground}
                  color={renderedColor}
                  fuseColor={fuseColor}
                  width={width}
                  radius={radius}
                  slideMs={slideMs}
                  settleBounce={settleBounce}
                  swipeDistance={swipeDistance}
                  duration={duration}
                  fuse={fuse}
                  pauseOnHover={pauseOnHover}
                  closeButton={closeButton}
                  inline={inline}
                />
              ))}
            </Box>
          </Box>

          <Customize>
            <PreviewInput title="Title" value={title} maxLength={32} onChange={val => updateProp('title', val)} />
            <PreviewInput
              title="Description"
              value={description}
              maxLength={48}
              onChange={val => updateProp('description', val)}
            />
            <PreviewInput
              title="Action Label"
              value={actionLabel}
              maxLength={12}
              onChange={val => updateProp('actionLabel', val)}
            />
            <PreviewColorPickerCustom
              title="Background"
              color={renderedBackground}
              onChange={val => updateProp('background', val)}
            />
            <PreviewColorPickerCustom title="Text" color={renderedColor} onChange={val => updateProp('color', val)} />
            <PreviewColorPickerCustom title="Fuse" color={fuseColor} onChange={val => updateProp('fuseColor', val)} />
            <PreviewSlider
              title="Width"
              min={280}
              max={420}
              step={4}
              value={width}
              valueUnit="px"
              onChange={val => updateProp('width', val)}
            />
            <PreviewSlider
              title="Radius"
              min={0}
              max={24}
              step={1}
              value={radius}
              valueUnit="px"
              onChange={val => updateProp('radius', val)}
            />
            <PreviewSlider
              title="Slide"
              min={200}
              max={700}
              step={20}
              value={slideMs}
              valueUnit="ms"
              onChange={val => updateProp('slideMs', val)}
            />
            <PreviewSlider
              title="Settle Bounce"
              min={0}
              max={0.4}
              step={0.02}
              value={settleBounce}
              onChange={val => updateProp('settleBounce', val)}
            />
            <PreviewSlider
              title="Swipe Distance"
              min={12}
              max={96}
              step={2}
              value={swipeDistance}
              valueUnit="px"
              onChange={val => updateProp('swipeDistance', val)}
            />
            <PreviewSlider
              title="Duration"
              min={0}
              max={10000}
              step={250}
              value={duration}
              valueUnit="ms"
              onChange={val => updateProp('duration', val)}
            />
            <PreviewSelect
              title="Fuse"
              options={FUSE_OPTIONS}
              value={fuse}
              onChange={val => updateProp('fuse', val)}
              width={120}
            />
            <PreviewSwitch
              title="Pause On Hover"
              isChecked={pauseOnHover}
              onChange={val => updateProp('pauseOnHover', val)}
            />
            <PreviewSwitch
              title="Close Button"
              isChecked={closeButton}
              onChange={val => updateProp('closeButton', val)}
            />
            <PreviewSwitch title="Inline" isChecked={inline} onChange={val => updateProp('inline', val)} />
          </Customize>

          <PropTable data={propData} />
          <Dependencies dependencyList={['motion', '@hugeicons/react', '@hugeicons/core-free-icons']} />
        </PreviewTab>

        <CodeTab>
          <CodeExample codeObject={swipeToast} componentName="SwipeToast" />
        </CodeTab>
      </TabsLayout>
    </ComponentPropsProvider>
  );
};

export default SwipeToastDemo;