import type { ComputedRef, Ref } from 'vue'
import type { TableSelectionOptions } from '../../types/TableSchema'
import { computed, ref } from 'vue'

export interface UseTableSelectionOptions<T> extends TableSelectionOptions<T> {
	cleanData?: (item: T) => T
	data: Ref<T[]> | ComputedRef<T[]>
}

export function useTableSelection<T extends { [key: string]: any }>(options: UseTableSelectionOptions<T>) {
	const allSelectorEl = ref<HTMLInputElement>()
	const computedSelectedItems = computed(() => options.selectedItems.value)
	const isSelectable = computed(() => options.selectable === true && Array.isArray(options.selectedItems.value))
	const allItems = $computed(() => options.data.value)

	function updateAllSelectorState() {
		if (allSelectorEl.value === undefined) return

		// If we don't know the total items, we can't determine if "all" are selected
		if (!allItems) {
			allSelectorEl.value.indeterminate = options.selectedItems.value.length > 0
			return
		}

		// Get all possible item IDs
		const allItemIds = allItems.map(item => item.id)

		// Check if all items are selected
		const allSelected
    = allItemIds.length > 0
    	&& options.selectedItems.value.length === allItemIds.length
    	&& allItemIds.every(id => options.selectedItems.value.includes(id))

		// Set checked state
		allSelectorEl.value.checked = allSelected

		// Set indeterminate state (some but not all items selected)
		allSelectorEl.value.indeterminate
    = !allSelected && options.selectedItems.value.length > 0
	}

	function toggleSelectItem(item: T) {
		if (computedSelectedItems.value.length === 0) {
			// Clean the item if a cleanData function is provided, otherwise use the default cleaning
			const cleanItem = options.cleanData ? options.cleanData(item) : { ...item }

			// If no cleanData function is provided, use the default cleaning
			if (!options.cleanData) {
				Object.keys(cleanItem).forEach((key) => {
					if (key.startsWith('_')) {
						delete cleanItem[key]
					}
				})
			}

			options.onSelect(cleanItem)
			return
		}
		const index = computedSelectedItems.value.indexOf(item.id)
		if (index > -1) {
			options.selectedItems.value.splice(index, 1)
		} else {
			options.selectedItems.value.push(item.id)
		}
	}

	// Update toggleSelectAll to pass allItems to updateAllSelectorState
	function toggleSelectAll(event: Event) {
		const value = (event.target as HTMLInputElement).checked

		if (allItems && value) {
			options.selectedItems.value = allItems.map(item => item.id)
		} else {
			options.selectedItems.value = []
		}
	}

	return {
		computedSelectedItems,
		isSelectable,
		allSelectorEl,
		updateAllSelectorState,
		toggleSelectItem,
		toggleSelectAll
	}
}
