import React from 'react'
import type { GridPreferencesAdapter } from '../types'
import type { useGrid } from './use-grid'

export type UsePreferencesAdapterProps = {
    grid: ReturnType<typeof useGrid>
    preferencesAdapter?: GridPreferencesAdapter
}

export const usePreferencesAdapter = ({
    grid,
    preferencesAdapter,
}: UsePreferencesAdapterProps) => {
    const [initialized, setInitialized] = React.useState(
        preferencesAdapter ? false : true
    )
    React.useEffect(() => {
        if (preferencesAdapter) {
            const adapter = preferencesAdapter
            return grid.events.on('onColumnStateChange', () => {
                const state = grid.getState()
                adapter.save({
                    columns: grid.selectors.selectColumnPreferences(state),
                })
            })
        }
    }, [grid, preferencesAdapter])

    React.useEffect(() => {
        if (preferencesAdapter) {
            const adapter = preferencesAdapter

            let abort = false

            const load = async () => {
                try {
                    const data = await adapter.load()
                    if (!abort && data) {
                        const state = grid.getState()
                        const columnIdsSet = new Set(
                            grid.selectors.selectColumnIdsWithoutInternal(state)
                        )
                        const incomingIdsSet = data.columns.map((c) => c.id)

                        if (
                            columnIdsSet.size !== incomingIdsSet.length ||
                            !incomingIdsSet.every((id) => columnIdsSet.has(id))
                        ) {
                            throw new Error(
                                'Preferences do not match current column configuration'
                            )
                        }

                        grid.dispatch({
                            type: 'applyPreferences',
                            payload: {
                                preferences: data,
                                multiSelection:
                                    grid.selectors.selectSelectionMode(
                                        state
                                    ) === 'multi',
                            },
                        })
                    }
                } catch (error) {
                    /* Eventually we may want to trigger a general error on the grid */
                } finally {
                    setInitialized(true)
                }
            }

            void load()

            return () => {
                abort = true
            }
        }
    }, [grid, preferencesAdapter])

    return initialized
}
