import type { Meta, StoryObj } from "@storybook/react";
import type { ReactNode } from "react";
import type { GridItemProps, GridProps } from ".";
import { Grid } from ".";
import { Box } from "../Box";
import { Flex } from "../Flex";
import type { GridItem } from "./Item";
import { sizeOptions } from "../../utils";

import "./Grid.story.styles.css";

type StoryType = StoryObj<typeof Grid>;

const meta: Meta<typeof Grid> = {
  title: "Layout/Grid",
  component: Grid,
  argTypes: {
    columns: {
      control: { type: "number" },
    },
    gap: {
      control: { type: "select" },
      options: [...sizeOptions],
    },
    rowGap: {
      control: { type: "select" },
      options: [...sizeOptions],
      if: {
        arg: "gap",
        truthy: false,
      },
    },
    columnGap: {
      control: { type: "select" },
      options: [...sizeOptions],
      if: {
        arg: "gap",
        truthy: false,
      },
    },
    alignContent: {
      control: { type: "select" },
      options: [
        "",
        "center",
        "space-around",
        "space-between",
        "space-evenly",
        "stretch",
      ],
    },
    justifyContent: {
      control: { type: "select" },
      options: [
        "",
        "center",
        "start",
        "end",
        "space-around",
        "space-between",
        "space-evenly",
      ],
    },
    alignItems: {
      control: { type: "select" },
      options: ["", "center", "start", "end", "stretch", "baseline"],
    },
    justifyItems: {
      control: { type: "select" },
      options: ["", "start", "end", "center", "stretch"],
    },
  },
  decorators: [Story => <Story />],
};

type SharedProps = {
  children: ReactNode;
};

const Card = ({ children, ...props }: SharedProps) => (
  <Box
    style={{
      borderRadius: "4px",
      padding: "8px",
      backgroundColor: "#dddddd",
      width: "80%",
    }}
    {...props}
  >
    {children}
  </Box>
);

const Square = ({ children, ...props }: SharedProps) => (
  <Flex
    alignItems="center"
    justifyContent="center"
    style={{ height: "100%" }}
    {...props}
  >
    {children}
  </Flex>
);

const AlignSquare = ({ children, ...props }: SharedProps) => (
  <Box style={{}} {...props}>
    {children}
  </Box>
);

export const AlignmentProperties: StoryType = {
  render: (args: GridProps) => (
    <Grid {...args}>
      <Grid.Item className="grid-example-grid-alignment-item" span={4}>
        <Square>1</Square>
      </Grid.Item>
      <Grid.Item className="grid-example-grid-alignment-item" span={4}>
        <Square>2</Square>
      </Grid.Item>
      <Grid.Item className="grid-example-grid-alignment-item" span={4}>
        <Square>3</Square>
      </Grid.Item>
      <Grid.Item className="grid-example-grid-alignment-item" span={4}>
        <Square>4</Square>
      </Grid.Item>
      <Grid.Item className="grid-example-grid-alignment-item" span={4}>
        <Square>5</Square>
      </Grid.Item>
      <Grid.Item className="grid-example-grid-alignment-item" span={4}>
        <Square>6</Square>
      </Grid.Item>
      <Grid.Item className="grid-example-grid-alignment-item" span={4}>
        <Square>7</Square>
      </Grid.Item>
      <Grid.Item className="grid-example-grid-alignment-item" span={4}>
        <Square>8</Square>
      </Grid.Item>
      <Grid.Item className="grid-example-grid-alignment-item" span={4}>
        <Square>9</Square>
      </Grid.Item>
    </Grid>
  ),
  args: {
    columns: 12,
    gap: "xs",
    alignItems: "stretch",
    justifyItems: "stretch",
    className: "grid-example-fixed-size-grid",
  },
};

export const Default: StoryType = {
  render: (args: GridProps) => (
    <Grid {...args}>
      <Grid.Item span={12}>
        <Card>span=12</Card>
      </Grid.Item>
      <Grid.Item span={11}>
        <Card>span=11</Card>
      </Grid.Item>
      <Grid.Item span={1}>
        <Card>span=1</Card>
      </Grid.Item>
      <Grid.Item span={10}>
        <Card>span=10</Card>
      </Grid.Item>
      <Grid.Item span={2}>
        <Card>span=2</Card>
      </Grid.Item>
      <Grid.Item span={9}>
        <Card>span=9</Card>
      </Grid.Item>
      <Grid.Item span={3}>
        <Card>span=3</Card>
      </Grid.Item>
      <Grid.Item span={8}>
        <Card>span=8</Card>
      </Grid.Item>
      <Grid.Item span={4}>
        <Card>span=4</Card>
      </Grid.Item>
      <Grid.Item span={7}>
        <Card>span=7</Card>
      </Grid.Item>
      <Grid.Item span={5}>
        <Card>span=5</Card>
      </Grid.Item>
      <Grid.Item span={6}>
        <Card>span=6</Card>
      </Grid.Item>
      <Grid.Item span={6}>
        <Card>span=6</Card>
      </Grid.Item>
    </Grid>
  ),
  args: {
    columns: 12,
    gap: "xs",
    alignItems: "stretch",
    justifyItems: "stretch",
  },
};

export const EightColumns: StoryType = {
  render: (args: GridProps) => (
    <Grid {...args}>
      {[...new Array(8)].map((_, k) => (
        <Card key={k}>span=1</Card>
      ))}
    </Grid>
  ),
  args: {
    columns: 8,
    gap: "xs",
    alignItems: "stretch",
    justifyItems: "stretch",
    className: "grid-example-eight-columns",
  },
};

export const Responsive: Meta<typeof GridItem> = {
  render: (args: GridItemProps) => {
    const breakpointArgs = ["xs", "sm", "md", "lg", "xl", "xxl"];
    const allArgs = Object.entries(args)
      .filter(([breakpoint]) => breakpointArgs.includes(breakpoint))
      .map(([breakpoint, value]) => `${breakpoint}=${value}`)
      .join(" ");

    return (
      <Grid gap="xs" alignItems="stretch" justifyItems="stretch">
        <Grid.Item {...args}>
          <Card>{allArgs}</Card>
        </Grid.Item>
        <Grid.Item lg={4}>
          <Card>lg=4</Card>
        </Grid.Item>
        <Grid.Item xs={5}>
          <Card>xs=5</Card>
        </Grid.Item>
        <Grid.Item span={5}>
          <Card>span=5</Card>
        </Grid.Item>
      </Grid>
    );
  },
  args: {
    xs: 12,
    sm: 6,
    md: 2,
    lg: 8,
    xl: 12,
    xxl: 4,
  },
  parameters: {
    controls: {
      exclude: ["columns"],
    },
  },
};

export const ItemPositioning: Meta<typeof GridItem> = {
  render: (args: GridItemProps) => (
    <Grid
      columns={12}
      gap="xs"
      alignItems="stretch"
      justifyItems="stretch"
      className="grid-example-fixed-size-grid"
    >
      <Grid.Item className="grid-example-align-square-item" span={4} {...args}>
        <AlignSquare>1</AlignSquare>
      </Grid.Item>
      <Grid.Item className="grid-example-align-square-item" span={4}>
        <AlignSquare>2</AlignSquare>
      </Grid.Item>
      <Grid.Item className="grid-example-align-square-item" span={4}>
        <AlignSquare>3</AlignSquare>
      </Grid.Item>
      <Grid.Item className="grid-example-align-square-item" span={4}>
        <AlignSquare>4</AlignSquare>
      </Grid.Item>
    </Grid>
  ),
  args: {
    alignSelf: "center",
    justifySelf: "end",
  },
  argTypes: {
    alignSelf: {
      control: { type: "select" },
      options: ["", "center", "start", "end", "stretch"],
    },
    justifySelf: {
      control: { type: "select" },
      options: ["", "center", "start", "end", "stretch"],
    },
  },
  parameters: {
    controls: {
      exclude: [
        "columns",
        "gap",
        "rowGap",
        "columnGap",
        "alignContent",
        "justifyContent",
        "alignItems",
        "justifyItems",
      ],
    },
  },
};

export default meta;
