/**
 * Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022-2026)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { BooleanCell, GridCellKind } from "@glideapps/glide-data-grid"
import { Bool, Field } from "apache-arrow"

import { DataFrameCellType } from "~lib/dataframes/arrowTypeUtils"
import { mockTheme } from "~lib/mocks/mockTheme"
import { convertRemToPx } from "~lib/theme"

import CheckboxColumn from "./CheckboxColumn"
import { isErrorCell } from "./utils"

const MOCK_CHECKBOX_COLUMN_PROPS = {
  id: "1",
  name: "checkbox_column",
  title: "Checkbox column",
  indexNumber: 0,
  isEditable: false,
  isHidden: false,
  isIndex: false,
  isPinned: false,
  isStretched: false,
  arrowType: {
    type: DataFrameCellType.DATA,
    arrowField: new Field("checkbox_column", new Bool(), true),
    pandasType: {
      field_name: "checkbox_column",
      name: "checkbox_column",
      pandas_type: "bool",
      numpy_type: "bool",
      metadata: null,
    },
  },
}

describe("CheckboxColumn", () => {
  it("creates a valid column instance", () => {
    const mockColumn = CheckboxColumn(
      MOCK_CHECKBOX_COLUMN_PROPS,
      mockTheme.emotion
    )
    expect(mockColumn.kind).toEqual("checkbox")
    expect(mockColumn.title).toEqual(MOCK_CHECKBOX_COLUMN_PROPS.title)
    expect(mockColumn.id).toEqual(MOCK_CHECKBOX_COLUMN_PROPS.id)
    expect(mockColumn.sortMode).toEqual("default")

    const mockCell = mockColumn.getCell(true)
    expect(mockCell.kind).toEqual(GridCellKind.Boolean)
    expect((mockCell as BooleanCell).data).toEqual(true)
  })

  it.each([
    [true, true],
    [false, false],
    ["true", true],
    ["false", false],
    ["yes", true],
    ["no", false],
    ["t", true],
    ["f", false],
    ["y", true],
    ["n", false],
    ["on", true],
    ["off", false],
    ["1", true],
    ["0", false],
    [1, true],
    [0, false],
    [[], null],
    [null, null],
    [undefined, null],
    ["", null],
  ])(
    "supports boolean compatible value (%p parsed as %p)",
    // eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: Replace 'any' with a more specific type.
    (input: any, value: boolean | null) => {
      const mockColumn = CheckboxColumn(
        MOCK_CHECKBOX_COLUMN_PROPS,
        mockTheme.emotion
      )
      const cell = mockColumn.getCell(input)
      expect(mockColumn.getCellValue(cell)).toEqual(value)
      expect(isErrorCell(cell)).toEqual(false)
    }
  )

  it.each([["foo"], [12345], [0.1], [["foo", "bar"]]])(
    "%p results in error cell: %p",
    // eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: Replace 'any' with a more specific type.
    (input: any) => {
      const mockColumn = CheckboxColumn(
        MOCK_CHECKBOX_COLUMN_PROPS,
        mockTheme.emotion
      )
      const cell = mockColumn.getCell(input)
      expect(isErrorCell(cell)).toEqual(true)
    }
  )

  it("applies themeOverride roundingRadius based on theme radii", () => {
    const mockColumn = CheckboxColumn(
      MOCK_CHECKBOX_COLUMN_PROPS,
      mockTheme.emotion
    )

    expect(mockColumn.themeOverride).toBeDefined()

    const expectedRoundingRadius = Math.round(
      Math.min(
        convertRemToPx(mockTheme.emotion.radii.md),
        convertRemToPx(mockTheme.emotion.radii.maxCheckbox)
      )
    )

    expect(mockColumn.themeOverride?.roundingRadius).toEqual(
      expectedRoundingRadius
    )
  })
})
