import { computed, defineComponent, h, PropType } from 'vue'

import { CFormCheck } from '../form/'
import { CTableBody, CTableDataCell, CTableRow } from '../table/'

import { isObjectInArray } from '../../utils'

import { ITEM_INTERNAL_KEYS } from './consts'
import {
  getClickedColumnName,
  getColumnName,
  getColumns,
  getTableDataCellProps,
  getTableDataCellStyles,
} from './utils'
import type { Column, Item } from './types'

const CSmartTableBody = defineComponent({
  name: 'CSmartTableBody',
  props: {
    clickableRows: Boolean,
    columnNames: {
      type: Array as PropType<string[]>,
      default: () => [],
    },
    columns: {
      type: Array as PropType<(Column | string)[]>,
      default: () => [],
    },
    currentItems: {
      type: Array as PropType<Item[]>,
      default: () => [],
    },
    firstItemOnActivePageIndex: {
      type: Number,
      default: 0,
    },
    noItemsLabel: String,
    scopedSlots: Object,
    selectable: Boolean,
    selected: Array as PropType<Item[]>,
  },
  emits: ['rowChecked', 'rowClick'],
  setup(props, { emit }) {
    const colspan: number = props.selectable ? props.columns.length + 1 : props.columns.length
    const columns = computed(() => getColumns(props.columns))

    return () =>
      h(
        CTableBody,
        {
          ...(props.clickableRows && { style: 'cursor:pointer;' }),
        },
        {
          default: () =>
            props.currentItems.length > 0
              ? props.currentItems.map((item: Item, trIndex) => [
                  h(
                    CTableRow,
                    {
                      ...(item._props && { ...item._props }),
                      ...(props.clickableRows && { tabindex: 0 }),
                      onClick: (event: MouseEvent) => {
                        emit(
                          'rowClick',
                          item,
                          trIndex + props.firstItemOnActivePageIndex,
                          getClickedColumnName(
                            event.target as HTMLElement,
                            props.columnNames,
                            props.selectable,
                          ),
                          event,
                        )
                      },
                    },
                    {
                      default: () => [
                        props.selectable &&
                          h(CTableDataCell, {}, () =>
                            h(CFormCheck, {
                              checked:
                                props.selected &&
                                isObjectInArray(props.selected, item, ITEM_INTERNAL_KEYS),
                              disabled: item._selectable === false,
                              onChange: (event: Event) => {
                                emit('rowChecked', item, (event.target as HTMLInputElement).checked)
                              },
                            }),
                          ),
                        columns.value.map((column) => {
                          const colName = getColumnName(column)
                          return props.scopedSlots &&
                            props.scopedSlots[colName] &&
                            typeof props.scopedSlots[colName] === 'function'
                            ? h(props.scopedSlots[colName], { item: item })
                            : typeof item[colName] !== 'undefined' &&
                                h(
                                  CTableDataCell,
                                  {
                                    ...getTableDataCellProps(column, item, colName),
                                    style: getTableDataCellStyles(column, item, colName),
                                  },
                                  {
                                    default: () => String(item[colName]),
                                  },
                                )
                        }),
                      ],
                    },
                  ),
                  props.scopedSlots &&
                    props.scopedSlots['details'] && [
                      h(CTableRow, {
                        colspan: props.selectable
                          ? props.columnNames.length + 1
                          : props.columnNames.length,
                        class: 'p-0',
                        style: { 'border-bottom-width': '0' },
                        tabindex: '-1',
                      }),
                      h(
                        CTableRow,
                        {
                          class: 'p-0',
                          key: `details${trIndex}`,
                        },
                        {
                          default: () =>
                            h(
                              CTableDataCell,
                              {
                                colspan: props.selectable
                                  ? props.columnNames.length + 1
                                  : props.columnNames.length,
                                class: 'p-0',
                                style: { border: 0 },
                              },
                              {
                                default: () =>
                                  props.scopedSlots &&
                                  props.scopedSlots['details'] &&
                                  h(props.scopedSlots['details'], {
                                    item: item,
                                  }),
                              },
                            ),
                        },
                      ),
                    ],
                ])
              : h(
                  CTableRow,
                  {},
                  {
                    default: () =>
                      h(
                        CTableDataCell,
                        { colspan: colspan },
                        {
                          default: () => props.noItemsLabel,
                        },
                      ),
                  },
                ),
        },
      )
  },
})

export { CSmartTableBody }
