import type { ChartData } from "chart.js"
import { describe, expect, it } from "vitest"
import { mount } from "@vue/test-utils"
import ChartDisplay from "./ChartDisplay.vue"

const sampleData: ChartData<"line"> = {
  labels: ["Jan", "Feb", "Mar"],
  datasets: [
    {
      label: "Revenue",
      data: [10, 20, 30],
    },
  ],
}

const barData: ChartData<"bar"> = {
  labels: ["A", "B"],
  datasets: [{ label: "Q", data: [1, 2] }],
}

const pieData: ChartData<"pie"> = {
  labels: ["X", "Y"],
  datasets: [{ data: [1, 2] }],
}

describe("ChartDisplay", () => {
  it("mounts a line chart by default", () => {
    const wrapper = mount(ChartDisplay, {
      props: { data: sampleData as ChartData },
    })
    const root = wrapper.find("[data-testid='chart-display']")
    expect(root.exists()).toBe(true)
    expect(root.attributes("data-chart-type")).toBe("line")
    expect(root.find("canvas").exists()).toBe(true)
  })

  it("mounts a bar chart when chartType is bar", () => {
    const wrapper = mount(ChartDisplay, {
      props: { chartType: "bar", data: barData as ChartData },
    })
    expect(
      wrapper
        .find("[data-testid='chart-display']")
        .attributes("data-chart-type"),
    ).toBe("bar")
    expect(wrapper.find("canvas").exists()).toBe(true)
  })

  it("mounts a pie chart when chartType is pie", () => {
    const wrapper = mount(ChartDisplay, {
      props: { chartType: "pie", data: pieData as ChartData },
    })
    expect(
      wrapper
        .find("[data-testid='chart-display']")
        .attributes("data-chart-type"),
    ).toBe("pie")
    expect(wrapper.find("canvas").exists()).toBe(true)
  })

  it("mounts a doughnut chart when chartType is doughnut", () => {
    const wrapper = mount(ChartDisplay, {
      props: { chartType: "doughnut", data: pieData as ChartData },
    })
    expect(
      wrapper
        .find("[data-testid='chart-display']")
        .attributes("data-chart-type"),
    ).toBe("doughnut")
    expect(wrapper.find("canvas").exists()).toBe(true)
  })

  it("forwards the data prop to the underlying chart component", () => {
    const wrapper = mount(ChartDisplay, {
      props: { data: sampleData as ChartData },
    })
    const chart = wrapper.findComponent({ name: "LineChart" })
      ?? wrapper.findAllComponents({ name: "Line" })[0]
      ?? wrapper.findAllComponents("Line" as unknown as never)[0]
    // Fallback: the canvas always exists when the chart mounted successfully
    expect(wrapper.find("canvas").exists()).toBe(true)
    // And vue-chartjs forwards the data prop verbatim
    if (chart && chart.exists()) {
      expect(chart.props("data")).toEqual(sampleData)
    }
  })

  it("merges responsive/maintainAspectRatio defaults with user options", () => {
    const wrapper = mount(ChartDisplay, {
      props: {
        data: sampleData as ChartData,
        options: { plugins: { legend: { display: false } } },
      },
    })
    expect(wrapper.find("canvas").exists()).toBe(true)
  })

  it("applies classList to the wrapper", () => {
    const wrapper = mount(ChartDisplay, {
      props: { data: sampleData as ChartData, classList: "stub-class" },
    })
    expect(
      wrapper.find("[data-testid='chart-display']").attributes("class"),
    ).toContain("stub-class")
  })

  it("applies width and height to the wrapper as inline style", () => {
    const wrapper = mount(ChartDisplay, {
      props: {
        data: sampleData as ChartData,
        width: 640,
        height: "200px",
      },
    })
    const style = wrapper
      .find("[data-testid='chart-display']")
      .attributes("style") ?? ""
    expect(style).toContain("width: 640px")
    expect(style).toContain("height: 200px")
  })

  it("accepts an array classList", () => {
    const wrapper = mount(ChartDisplay, {
      props: {
        data: sampleData as ChartData,
        classList: ["foo", "bar"],
      },
    })
    const cls = wrapper
      .find("[data-testid='chart-display']")
      .attributes("class") ?? ""
    expect(cls).toContain("foo")
    expect(cls).toContain("bar")
  })
})
