import React, { useEffect, useState, useCallback, useRef } from 'react'
import { connect, useDispatch } from 'react-redux'

import { Card, Table } from 'antd'
import commonStyles from '../../../../Utils/Common.less'
import type { ColumnsType, TableProps } from 'antd/es/table'
import type { TableParamsInterface } from '../../../../Types/CommonType'
import {
    commonTableParams,
    setCommonTableParamsData,
} from '../../../../Utils/CommontTable'
import calculatePagination from '../../../../Utils/Pagination'
import {
    type ProjectManagmentStausListInterface,
    type ProjectManagmentStausListDataTypeInterface,
} from '../../../../Types/ProjectMangement'
import {
    AddStausDetails,
    GetSatusList,
} from '../../../../Services/ProjectManagement'
import { MenuOutlined } from '@ant-design/icons'
import { restrictToVerticalAxis } from '@dnd-kit/modifiers'
import { CSS } from '@dnd-kit/utilities'
import {
    arrayMove,
    SortableContext,
    useSortable,
    verticalListSortingStrategy,
} from '@dnd-kit/sortable'
import type { DragEndEvent } from '@dnd-kit/core'

import { DndContext } from '@dnd-kit/core'
export const ProjectItemDefaultData = {
    projectStatusId: '0',
    projectId: '0',
    projectStatusName: '',
    defaultAssigneeUserId: 0,
    colorCode: '#000000',
    sortingOrder: 0,
    defaultAssigneeUser: '',
}
interface RowProps extends React.HTMLAttributes<HTMLTableRowElement> {
    'data-row-key': string
}

const Row = ({ children, ...props }: RowProps): JSX.Element => {
    const {
        attributes,
        listeners,
        setNodeRef,
        setActivatorNodeRef,
        transform,
        transition,
        isDragging,
    } = useSortable({
        id: props['data-row-key'],
    })

    const style: React.CSSProperties = {
        ...props.style,
        transform:
            transform !== null
                ? CSS.Transform.toString({ ...transform, scaleY: 1 })
                : undefined,
        transition,

        ...(isDragging ? { position: 'relative', zIndex: 9999 } : {}),
    }

    return (
        <tr {...props} ref={setNodeRef} style={style} {...attributes}>
            {React.Children.map(children, (child) => {
                if ((child as React.ReactElement).key === 'sort') {
                    return React.cloneElement(child as React.ReactElement, {
                        children: (
                            <MenuOutlined
                                ref={setActivatorNodeRef}
                                style={{ touchAction: 'none', cursor: 'move' }}
                                {...listeners}
                            />
                        ),
                    })
                }
                return child
            })}
        </tr>
    )
}

const ProjectList = (
    props: ProjectManagmentStausListInterface & { projectId: string }
): React.ReactElement => {
    const dispatch = useDispatch()
    const {
        ProjectManagmentStausList,
        ProjectManagmentStausListCount,
        projectId,
    } = props
    const [tableParams, setTableParams] =
        useState<TableParamsInterface>(commonTableParams)

    useState(false)

    const [currentPage, setCurrentPage] = useState(1)
    const [itemsPerPage, setItemsPerPage] = useState(10)
    const hasFetchedOnce = useRef(false)
    const mappedData = ProjectManagmentStausList?.map((item) => ({
        ...item,
        key: item.projectStatusId,
    }))
    const isSorted = useRef(false)
    useEffect(() => {
        if (isSorted.current) {
            const sortedData = dataSource.map((item, index) => {
                item.sortingOrder = index
                return item
            })
            sortedData.forEach((order) => {
                void AddStausDetails(dispatch, order)
            })

            isSorted.current = false
        }
    }, [isSorted.current])
    const [dataSource, setDataSource] = useState([...mappedData])

    const onDragEnd = ({ active, over }: DragEndEvent): void => {
        isSorted.current = true

        if (active.id !== over?.id) {
            setDataSource((previous) => {
                const activeIndex = previous.findIndex(
                    (i) => i.key === active.id
                )
                const overIndex = previous.findIndex((i) => i.key === over?.id)

                return arrayMove(previous, activeIndex, overIndex)
            })
        }
    }

    const getTableData = useCallback(() => {
        const { pageSize, pageNo, sortOrderList, searchCriteriaList } =
            setCommonTableParamsData(tableParams)
        GetSatusList(dispatch, projectId, {
            pageNo,
            pageSize,
            searchCriteriaList,
            sortOrderList,
        })
    }, [
        projectId,
        tableParams?.sorter,
        tableParams.pagination?.current,
        tableParams?.filter,
    ])

    useEffect(() => {
        if (!hasFetchedOnce.current) {
            hasFetchedOnce.current = true
            return
        }
        getTableData()
    }, [getTableData])

    const handleDataCountChange = useCallback(() => {
        setTableParams({
            ...tableParams,
            pagination: {
                ...tableParams.pagination,
                total: ProjectManagmentStausListCount,
            },
        })
    }, [ProjectManagmentStausListCount])
    useEffect(() => {
        handleDataCountChange()
    }, [handleDataCountChange])

    const handlePageChange = (pageNo: number, pageSize: number): void => {
        window.scrollTo(0, 0)
        setCurrentPage(pageNo)
        setItemsPerPage(pageSize)
    }
    const handlePageSizeChange = (pageSize: number): void => {
        setItemsPerPage(pageSize)
        setCurrentPage(1) // Reset to first page when page size changes
    }
    const pagination = calculatePagination(
        currentPage,
        ProjectManagmentStausListCount,
        itemsPerPage,
        handlePageSizeChange
    )
    useEffect(() => {
        setDataSource([...mappedData])
    }, [ProjectManagmentStausList])

    const columns: ColumnsType<ProjectManagmentStausListDataTypeInterface> = [
        {
            key: 'sort',
        },
        {
            title: 'StausName',
            dataIndex: 'projectStatusName',
        },
        {
            title: ' Default Assignee',
            dataIndex: 'defaultAssigneeUser',
        },
    ]

    const onChangeTableParams: TableProps<ProjectManagmentStausListDataTypeInterface>['onChange'] =
        (pagination, filters, sorter: any) => {
            handlePageChange(pagination.current ?? 1, pagination.pageSize ?? 10)
            setTableParams({
                ...tableParams,
                pagination,
                sorter: {
                    field: sorter?.field ?? '',
                    order: sorter?.order ?? '',
                },
            })
        }

    return (
        <>
            <Card title="Project Management" className={commonStyles.card}>
                <div className={commonStyles.table}>
                    <DndContext
                        modifiers={[restrictToVerticalAxis]}
                        onDragEnd={onDragEnd}
                    >
                        <SortableContext
                            items={dataSource.map((i) => i.key)}
                            strategy={verticalListSortingStrategy}
                        >
                            <Table
                                components={{
                                    body: {
                                        row: Row,
                                    },
                                }}
                                columns={columns}
                                dataSource={dataSource}
                                pagination={pagination}
                                onChange={onChangeTableParams}
                                showHeader={true}
                            />
                        </SortableContext>
                    </DndContext>
                </div>
            </Card>
        </>
    )
}

const mapStateToProps = (state: any): ProjectManagmentStausListInterface => {
    return {
        ProjectManagmentStausList: state.initial.ProjectManagmentStausList,
        ProjectManagmentStausListCount:
            state.initial.ProjectManagmentStausListCount,
    }
}

export default connect(mapStateToProps)(ProjectList)
