import React, { useState } from 'react'

import Button from '../Button/Button'
import Icon from '../Icons/Icon'
import { type chartColors } from '../HeaderMetric/HeaderMetricGroup'
import styles from './_checkbox.module.scss'
import { type HandleCheckType } from './FormTypes'
import { useToggle } from '../../hooks/useToggle/useToggle'

export interface CheckboxProps<StateNameType extends number | string> {
  /** Label for the checkbox */
  label: string
  /** Determines whether the checkbox is checked; for
   * partial checks, set `checked` to `false` and `partialChecked`
   * to `true` */
  checked?: boolean
  /** Determines whether the checkbox is partially checked
   * (used for parent checkboxes that have children checkboxes
   * and some of the children are checked and some are not);
   * a `true` value must always be set from consuming component;
   * only available for checkbox components (not radio components) */
  partialChecked?: boolean
  /** Optional function on checkbox click */
  callout?: (
    stateName: StateNameType | undefined,
    /** check is the updated value of the checkbox */
    check: boolean,
    /** partial, if present, is always a `false` boolean;
     * default behavior should be to transition from partial
     * to all checked (functionality is up to the consuming component) */
    partial?: boolean,
  ) => void
  /** Unique name for the checkbox */
  name?: string
  /** Name of the state for the checkbox. This would be defined in the component consuming this one. */
  stateName?: StateNameType
  /** Used to show an error state */
  error?: boolean
  /** Used to show a disabled state */
  disabled?: boolean
  /** Optional className that can be provided for styling */
  customClass?: string
  /** Optional className for the label */
  labelClass?: string
  /** Type of checkbox style (default: checkbox) */
  type?: 'checkbox' | 'radio'
  /** Size of the radio checkbox */
  radioSize?: string
  /** Option to hide the label */
  hideLabel?: boolean
  /** Potential colors that can be used for the checkbox */
  checkboxColor?: chartColors
  /** Index for the checkbox */
  index?: number
  /** Optional function to handle checkbox click */
  handleCheck?: HandleCheckType
  /** Optional prop to add a test id to the Checkbox for QA testing */
  qaTestId?: string
}
const Checkbox = <StateNameType extends number | string>({
  name = '',
  checked,
  partialChecked,
  label,
  callout,
  customClass = '',
  stateName,
  type,
  disabled,
  error,
  radioSize,
  labelClass = '',
  hideLabel,
  checkboxColor = 'dark-blue',
  handleCheck,
  index,
  qaTestId = 'checkbox',
}: CheckboxProps<StateNameType>): React.JSX.Element => {
  const isTailwindEnabled = useToggle('button_tailwind')
  const [isChecked, setIsChecked] = useState(false)
  const [isPartialChecked, setIsPartialChecked] = useState(false)
  const partial =
    typeof partialChecked === 'boolean' ? partialChecked : isPartialChecked // partialChecked is only updated from consuming component
  const check =
    typeof checked === 'boolean' ? checked && !partialChecked : isChecked

  const toggleChecked = (event?: React.MouseEvent<HTMLButtonElement>) => {
    if (check) {
      setIsChecked(false)
      setIsPartialChecked(false)
      callout?.(stateName, false)
    } else if (partial) {
      setIsPartialChecked(false)
      // default state transition is from partial to checked
      setIsChecked(true)
      callout?.(stateName, false, false)
    } else {
      handleCheck && event && handleCheck(index ?? -1, event, check)
      setIsChecked(true)
      setIsPartialChecked(false)
      callout?.(stateName, true)
    }
  }

  const standardSize = radioSize ? radioSize : type === 'radio' ? '12' : '16'
  const styleCheckboxColor = {
    '--checkbox-color': `var(--${checkboxColor})`,
  } as React.CSSProperties

  const style = {
    '--radio-size': `${standardSize}px`,
  } as React.CSSProperties

  return (
    <div
      className={`${styles.checkboxContainer} ${error ? styles.error : ''} ${
        check ? styles.checked : partial ? styles.partialChecked : ''
      } ${disabled ? styles.disabled : ''} ${customClass}`}
      qa-test-id={qaTestId}
      data-testid='checkbox-component'
    >
      <input
        name={name}
        className={styles.hiddenCheckbox}
        type={type ? type : 'checkbox'}
        disabled={!disabled}
      />
      <Button
        as='unstyled'
        onClick={(event: React.MouseEvent<HTMLButtonElement>) =>
          toggleChecked(event)
        }
        disabled={disabled}
        className={isTailwindEnabled ? 'bg-transparent' : ''}
      >
        <div
          className={`${styles.clickableContainer} ${type ? styles[type] : ''} ${hideLabel ? styles.hideLabel : ''}`}
          style={styleCheckboxColor}
          data-testid='checkbox-clickable-container'
        >
          <div
            className={`${styles.styledCheckbox} ${type ? styles[type] : ''}`}
            style={Object.assign(style, styleCheckboxColor)}
          >
            {check && type !== 'radio' ? (
              <Icon
                icon='checkNoCircle'
                color='white'
                iconSize='12px'
                className={styles.checkmark}
              />
            ) : partial && type !== 'radio' ? (
              <Icon icon='dash' color='white' iconSize='12px' />
            ) : null}
          </div>
          {!hideLabel ? (
            <label
              className={`${styles.checkboxLabel} ${labelClass}`}
              data-testid='checkbox-label'
            >
              {label}
            </label>
          ) : null}
        </div>
      </Button>
    </div>
  )
}

export default Checkbox
