/* eslint-disable react-hooks/rules-of-hooks */
import { useCallback, useState } from "react";
import { motion } from "framer-motion";

import { commonProps } from "../../utils/storybook";
import { styled } from "../../theme";
import { pxToRem, useBreakpoints } from "../../utils";
import { Button } from "../button";
import { Box } from "../box";
import { Flex } from "../flex";
import { Text } from "../text";
import { Carousel } from "./";

import type { StoryObj, Meta } from "@storybook/react";

function clamp(value: number, min: number, max: number): number {
  return Math.floor(Math.min(Math.max(value, min), max));
}

const StyledMotionLink = styled(motion.a, {
  display: "flex",
  p: "$1",
  flexDirection: "column",
  gap: "$1",
  borderRadius: "$s",
  border: "2px solid transparent",
  "&:focus": {
    boxShadow: "0px 0px 0px 2px $off-white-72",
    scale: "0.9",
  },
});

const Placeholder: React.FC<{ i: number; width: number; height: number }> = ({
  i,
  width,
  height,
}) => {
  return (
    <StyledMotionLink whileHover={{ scale: 0.9 }} whileTap={{ scale: 0.8 }} href={`#${i}`}>
      <Flex
        css={{
          width: pxToRem(width),
          height: pxToRem(height),
          borderRadius: "$s",
          overflow: "hidden",
          backgroundColor: "$off-white-72",
          alignItems: "center",
          justifyContent: "center",
        }}
      >
        <Text
          variant="body2"
          css={{ fontWeight: "$bold", color: "$off-white-72" }}
        >{`${width}x${height}`}</Text>
      </Flex>

      <Text variant="body4" css={{ color: "$light-off-white" }}>
        {`Chromia ${i}`}
      </Text>
    </StyledMotionLink>
  );
};

const ResponsivePlaceholder = styled("div", {
  width: 150,
  height: 150,
  backgroundColor: "$off-white-72",
  m: "$1",
  borderRadius: "$s",
  border: "2px solid transparent",

  "@s": {
    width: 100,
    height: 100,
  },
});

const defaultItems = [...Array(10).keys()].map((i) => (
  <Placeholder key={i} i={i} width={180} height={100} />
));

const meta: Meta<typeof Carousel> = {
  title: "Carousel",
  component: Carousel,
  tags: ["autodocs"],
  argTypes: {
    gap: {
      table: {
        category: "Grid Props",
      },
    },
    span: {
      table: {
        category: "Grid Props",
      },
    },
    gapX: {
      table: {
        category: "Grid Props",
      },
    },
    gapY: {
      table: {
        category: "Grid Props",
      },
    },
    disableDrag: { table: { defaultValue: { summary: "false" } } },
    ...commonProps,
  },
  args: {
    children: defaultItems,
    rows: 2,
    columns: 4,
    css: { rowGap: "20px" },
  },
  decorators: [
    (Story) => (
      <Box css={{ width: "fit-content", mx: "auto" }}>
        <Story />
      </Box>
    ),
  ],
};

export default meta;

type Story = StoryObj<typeof Carousel>;

/**
 * The internal navigation buttons are enabled by default
 */
export const Uncontrolled: Story = {
  render: (args) => <Carousel {...args} />,
};

/**
 * The carousel can be fully controlled
 */
export const Controlled: Story = {
  render: (args) => {
    const [step, setStep] = useState(0);
    const handlePreviousClick = useCallback(() => {
      setStep((prev) => clamp(prev - 1, 0, defaultItems.length / 2 - 4));
    }, []);
    const handleNExtClick = useCallback(() => {
      setStep((prev) => clamp(prev + 1, 0, defaultItems.length / 2 - 4));
    }, []);
    const handleChange = useCallback((currentStep: number) => {
      setStep(currentStep);
    }, []);
    return (
      <Box>
        <Carousel {...args} step={step} onStepChange={handleChange} />
        <Flex gap="2">
          <Button text="previous" onClick={handlePreviousClick} />
          <Button text="next" onClick={handleNExtClick} />
        </Flex>
      </Box>
    );
  },
};

/**
 * Add an optional link title/url
 */
export const WithHeaderLink: Story = {
  render: (args) => <Carousel {...args} header={{ title: "With Header Link", href: "#" }} />,
};

/**
 * The Grid will adapt if children change (either by re-render or style change)
 */
export const WithDynamicChildren: Story = {
  render: (args) => {
    const [toggleChildren, setToggleChildre] = useState(false);
    return (
      <>
        <Carousel {...args}>
          {toggleChildren
            ? defaultItems
            : [...Array(10).keys()].map((i) => (
                <ResponsivePlaceholder key={i + "uninque"}>
                  responsive item #{i}
                </ResponsivePlaceholder>
              ))}
        </Carousel>
        <Button text="Toggle Children" onClick={() => setToggleChildre((prev) => !prev)} />
      </>
    );
  },
};

/**
 * The current step of the carousel will be recalculated whenever `columns` change
 */
export const WithReactiveColumns: Story = {
  render: (args) => {
    const { xl, l, m } = useBreakpoints();
    return (
      <>
        <Carousel {...args} columns={xl || l ? 4 : m ? 3 : 2} />
        <Text variant="body2" css={{ fontWeight: "$bold", color: "$off-white-72" }}>
          Resize window to change number of columns
        </Text>
      </>
    );
  },
};
