import { describe, expectTypeOf, it, expect } from "vitest"
import type {
  CardElement,
  DataTableCard,
  DisplayCard,
  ElementListCard,
  InputElement,
} from "@/definitions"
import {
  CardElementMetadataMap,
  DisplayCardMetadataMap,
  ElementListCardDefaults,
  InputElementDefaults,
} from "@/definitions"

describe("CardElement union", () => {
  it("narrows on the `type` discriminator", () => {
    const el: CardElement = {
      id: "1",
      type: "input.text",
      name: "first_name",
      label: "First name",
    }

    if (el.type === "input.text") {
      expectTypeOf(el).toMatchTypeOf<InputElement>()
      // style-specific fields available after narrowing
      expectTypeOf(el.placeholder).toEqualTypeOf<string | undefined>()
    }
  })

  it("validates that every element has a registered metadata entry", () => {
    const expected = [
      "action",
      "boolean",
      "builder",
      "code",
      "configuration-block",
      "display",
      "editor",
      "file",
      "input",
      "option-select",
      "picker",
    ] as const
    for (const key of expected) {
      expect(CardElementMetadataMap[key]).toBeDefined()
      expect(CardElementMetadataMap[key].elementCategory).toBe(key)
    }
  })

  it("preserves Defaults shape", () => {
    expect(InputElementDefaults.type).toBe("input.text")
    expect(InputElementDefaults.columns).toBe(12)
  })
})

describe("DisplayCard union", () => {
  it("narrows on the `cardType` discriminator", () => {
    const card: DisplayCard = {
      id: "c1",
      cardType: "element-list",
      elementList: ["e1", "e2"],
    }

    if (card.cardType === "element-list") {
      expectTypeOf(card).toMatchTypeOf<ElementListCard>()
      expectTypeOf(card.elementList).toEqualTypeOf<string[]>()
    }
  })

  it("validates that every card has a registered metadata entry", () => {
    const expected = [
      "card-list",
      "datatable",
      "element-display",
      "element-list",
      "grid-view",
      "info-card",
      "tab-list",
    ] as const
    for (const key of expected) {
      expect(DisplayCardMetadataMap[key]).toBeDefined()
    }
  })

  it("accepts a fully-typed DataTableCard config", () => {
    const card: DataTableCard = {
      id: "users",
      cardType: "datatable",
      tableTitle: "Users",
      headers: [
        { key: "name", title: "Name", sortable: true },
        { key: "email", title: "Email" },
      ],
      options: {
        searchRoute: { route: "api.users.index" },
        paginated: true,
        perPage: 25,
      },
    }
    expect(card.headers?.length).toBe(2)
  })

  it("preserves Defaults shape", () => {
    expect(ElementListCardDefaults.cardType).toBe("element-list")
    expect(ElementListCardDefaults.showCard).toBe(true)
  })
})
