import { faker } from "@faker-js/faker"
import { Meta, StoryObj } from "@storybook/react"
import { addHours } from "date-fns"
import { list } from "radash"
import React from "react"
import { useDateTimeFormatter } from "../../../hooks"
import { Text } from "../../Text"
import { ChartPanel } from "../ChartPanel"
import { RenderTooltipFn } from "../ChartTooltip"
import { Scatterplot, ScatterplotProps } from "./Scatterplot"

faker.seed(123456789)

const SECONDS_IN_WEEK = 604800

const getRandomScatterplotData = (count = 1000) => {
  const date = faker.date.anytime({ refDate: new Date(2024, 1, 1) })

  return list(count - 1).flatMap(x => ({
    x: addHours(date, x + faker.number.float()).getTime(),
    y: faker.number.float() ** 3 * 50 + 20,
  }))
}

type Story = StoryObj<typeof Scatterplot<DataPoint>>

const RenderTooltip: RenderTooltipFn<DataPoint> = ({ item: d, point }) => {
  const formatDate = useDateTimeFormatter()

  return (
    <div className="min-w-[64px] text-center">
      <Text.Heading size="sm">{formatDate(new Date(d.x))}</Text.Heading>
      <Text.Body className="block" size="sm">
        {point.series.name}
      </Text.Body>
      <Text.Body className="block" size="sm">
        {d.y.toFixed(2)}
      </Text.Body>
    </div>
  )
}

const meta: Meta<typeof Scatterplot<DataPoint>> = {
  title: "Design System/Scatterplot",
  component: Scatterplot,
  args: {
    className: "h-[600px]",
    series: [
      {
        data: getRandomScatterplotData(),
        getX: (d: DataPoint) => d.x,
        getY: (d: DataPoint) => d.y,
        name: "Blue",
      },
    ],
    renderTooltip: RenderTooltip,
    overrides: {
      xAxis: {
        tickInterval: SECONDS_IN_WEEK * 1000,
      },
    },
  },
}

export default meta

type DataPoint = {
  x: number
  y: number
}

export const RandomPoints: Story = {
  args: {
    series: [
      {
        data: getRandomScatterplotData(),
        getX: (d: DataPoint) => d.x,
        getY: (d: DataPoint) => d.y,
        name: "Blue",
      },
    ],
    renderTooltip: RenderTooltip,
    overrides: {
      xAxis: {
        tickInterval: SECONDS_IN_WEEK * 1000,
      },
    },
  },
}

export const TwoSeries: Story = {
  args: {
    series: [
      {
        data: getRandomScatterplotData(),
        getX: (d: DataPoint) => d.x,
        getY: (d: DataPoint) => d.y,
        name: "Blue",
      },
      {
        data: getRandomScatterplotData(),
        getX: (d: DataPoint) => d.x,
        getY: (d: DataPoint) => d.y,
        name: "Yellow",
      },
    ],
    renderTooltip: RenderTooltip,
    overrides: {
      xAxis: {
        tickInterval: SECONDS_IN_WEEK * 1000,
      },
    },
  },
}

export const Interactive: Story = {
  args: {
    interactive: true,
  },
}

export const OneHundredThousandPoints: Story = {
  args: {
    series: [
      {
        data: getRandomScatterplotData(100_000),
        getX: (d: DataPoint) => d.x,
        getY: (d: DataPoint) => d.y,
        name: "Blue",
        marker: {
          radius: 1,
        },
      },
    ],
    interactive: true,
  },
}

const PanelTemplate = (args: ScatterplotProps<DataPoint>) => {
  return (
    <ChartPanel>
      <ChartPanel.Header>
        <ChartPanel.Title>Scatterplot</ChartPanel.Title>
        <ChartPanel.ResetZoom />
      </ChartPanel.Header>
      <Scatterplot {...args} className="h-[200px]" />
    </ChartPanel>
  )
}
export const WithPanel: Story = {
  render: PanelTemplate,
  args: { interactive: true },
}

export const WithAxisTitles: Story = {
  render: PanelTemplate,
  args: {
    interactive: true,
    xAxisTitle: "Time",
    yAxisTitle: "Price (ETH)",
  },
}

export const Skeleton: Story = {
  render: function Render() {
    return (
      <ChartPanel>
        <ChartPanel.Header>
          <ChartPanel.Title>Scatterplot</ChartPanel.Title>
          <ChartPanel.ResetZoom />
        </ChartPanel.Header>
        <Scatterplot.Skeleton
          className="h-[200px]"
          xAxisLabels={["1", "2", "3", "4"]}
          yAxisLabels={["1 ETH", "2 ETH", "3 ETH"]}
        />
      </ChartPanel>
    )
  },
}

export const EmptyState: Story = {
  render: function Render() {
    return (
      <ChartPanel>
        <ChartPanel.Header>
          <ChartPanel.Title>Scatterplot</ChartPanel.Title>
          <ChartPanel.ResetZoom />
        </ChartPanel.Header>
        <Scatterplot.EmptyState
          className="h-[200px]"
          overrides={{
            Skeleton: {
              xAxisLabels: ["1", "2", "3", "4"],
              yAxisLabels: ["1 ETH", "2 ETH", "3 ETH"],
            },
          }}
        />
      </ChartPanel>
    )
  },
}
