import { memo, useCallback, useEffect, useState } from 'react'
import { ColumnsType } from 'antd/lib/table'
import { Button, Modal, Switch, Table } from 'antd'
import { SettingOutlined } from '@ant-design/icons'

import { ColumnSettings, makeSettings, mergeSettings, TableSettings } from '@utils/table_settings'
import { TableColumns } from './Table'
import { makeColumn } from '.'

const parseSettings = (columns?: TableColumns, settings?: TableSettings | null): ColumnSettings[] => {
    const newSettings = mergeSettings(makeSettings(columns ?? []), settings ?? {})
    return Object.values(newSettings).map((set, i) => ({ ...set, key: i }))
}

const unparseSettings = (columns: ColumnSettings[]): TableSettings =>
    Object.fromEntries(columns.map((column) => [column.columnName, column]))

export type TableSettingsChangerProps = {
    title?: string
    columns?: TableColumns
    settings?: TableSettings | null
    onChange: (settings: TableSettings | null) => void
}

export const TableSettingsChanger = memo<TableSettingsChangerProps>(({ title, columns, settings, onChange }) => {
    const [visible, setVisible] = useState<boolean>(false)
    const [newSettings, setNewSettings] = useState<ColumnSettings[]>(parseSettings(columns, settings))
    const [tableColumns, setTableColumns] = useState<ColumnsType<ColumnSettings>>([])

    const onVisibilityChange = useCallback((index: number, visible: boolean) => {
        setNewSettings((oldSettings) => {
            const newSettings = [...oldSettings]
            newSettings[index].visible = visible
            return newSettings
        })
    }, [])

    const toogleAll = useCallback((show: boolean) => {
        setNewSettings((oldSettings) => oldSettings.map((column) => {
            column.visible = show
            return column
        }))
    }, [])

    useEffect(() => {
        setTableColumns([
            makeColumn('Название', 'title'),
            makeColumn(null, 'visible', {
                title: () => (
                    <>
                        Показать
                        <Button type={'link'} onClick={() => toogleAll(true)}>Показать все</Button>
                    </>
                ),
                render: (visible: boolean, _?: ColumnSettings, index: number = NaN) => (
                    <Switch
                        checked={visible}
                        checkedChildren={'Отображён'}
                        unCheckedChildren={'Скрыт'}
                        onChange={(visible) => onVisibilityChange(index, visible)}
                    />
                )
            }),
        ])
    }, [toogleAll, onVisibilityChange])

    useEffect(() => setNewSettings(parseSettings(columns, settings)), [columns, settings])

    const onModalOk = useCallback(() => {
        onChange(unparseSettings(newSettings))
        setVisible(false)
    }, [newSettings, onChange])

    const onModalCancel = useCallback(() => {
        setNewSettings(parseSettings(columns, settings))
        setVisible(false)
    }, [columns, settings])

    return (
        <>
            <Modal
                centered
                visible={visible}
                onCancel={onModalCancel}
                onOk={onModalOk}
                title={title ?? 'Настройка отображения таблицы'}
                width={1000}
            >
                <Table columns={tableColumns} dataSource={newSettings} />
            </Modal>
            <Button size={'small'} style={{ position: 'absolute', left: 0, top: 0, opacity: .5 }} type={'link'} onClick={() => setVisible(true)} icon={<SettingOutlined />}/>
        </>
    )
})

export default TableSettingsChanger
