import React, { useCallback, useEffect, useRef, useState } from 'react';
import { useAppDispatch, useAppSelector } from '../../stores/hooks';
import Axios from 'axios';
import CardBox from '../CardBox';
import CardBoxModal from '../CardBoxModal';
import { AsyncThunk } from '@reduxjs/toolkit';
import { useDrop } from 'react-dnd';
import KanbanCard from './KanbanCard';
import { useTranslation } from 'react-i18next';
import { translateCrudLabel } from '../../helpers/translateCrudLabel';

type Props = {
    column: { id: string; label: string };
    entityName: string;
    columnFieldName: string;
    showFieldName: string;
    filtersQuery: any;
    deleteThunk: AsyncThunk<any, any, any>;
    updateThunk: AsyncThunk<any, any, any>;
};

type DropResult = {
    sourceColumn: { id: string; label: string };
    item: any;
};

const perPage = 10;

const KanbanColumn = ({
                          column,
                          entityName,
                          columnFieldName,
                          showFieldName,
                          filtersQuery,
                          deleteThunk,
                          updateThunk,
                      }: Props) => {
    const { t, i18n } = useTranslation('common');
    const [currentPage, setCurrentPage] = useState(0);
    const [count, setCount] = useState(0);
    const [data, setData] = useState(null);
    const [loading, setLoading] = useState(false);
    const [itemIdToDelete, setItemIdToDelete] = useState('');
    const currentUser = useAppSelector((state) => state.auth.currentUser);
    const listInnerRef = useRef<HTMLDivElement | null>(null);
    const dispatch = useAppDispatch();

    const [{ dropResult }, drop] = useDrop<
        {
            item: any;
            column: {
                id: string;
                label: string;
            };
        },
        unknown,
        {
            dropResult: DropResult;
        }
    >(
        () => ({
            accept: 'box',
            drop: ({
                       item,
                       column: sourceColumn,
                   }: {
                item: any;
                column: { id: string; label: string };
            }) => {
                if (sourceColumn.id === column.id) return;

                dispatch(
                    updateThunk({
                        id: item.id,
                        data: {
                            [columnFieldName]: column.id,
                        },
                    }),
                ).then((res) => {
                    setData((prevState) => (prevState ? [...prevState, item] : [item]));
                    setCount((prevState) => prevState + 1);
                });

                return { sourceColumn, item };
            },
            collect: (monitor) => ({
                dropResult: monitor.getDropResult(),
            }),
        }),
        [],
    );

    const loadData = useCallback(
        (page: number, filters = '') => {
            const query = `?page=${page}&limit=${perPage}&field=createdAt&sort=desc&${columnFieldName}=${column.id}&${filters}`;
            setLoading(true);
            Axios.get(`${entityName}${query}`)
                .then((res) => {
                    setData((prevState) =>
                        page === 0 ? res.data.rows : [...prevState, ...res.data.rows],
                    );
                    setCount(res.data.count);
                    setCurrentPage(page);
                })
                .catch((err) => {
                    console.error(err);
                })
                .finally(() => {
                    setLoading(false);
                });
        },
        [currentUser, column, i18n.language],
    );

    useEffect(() => {
        if (!currentUser) return;
        loadData(0, filtersQuery);
    }, [currentUser, loadData, filtersQuery]);

    useEffect(() => {
        loadData(0, filtersQuery);
    }, [loadData, filtersQuery]);

    useEffect(() => {
        if (dropResult?.sourceColumn && dropResult.sourceColumn.id === column.id) {
            setData((prevState) =>
                prevState.filter((item) => item.id !== dropResult.item.id),
            );
            setCount((prevState) => prevState - 1);
        }
    }, [dropResult]);

    const onScroll = () => {
        if (listInnerRef.current) {
            const { scrollTop, scrollHeight, clientHeight } = listInnerRef.current;
            if (Math.floor(scrollTop + clientHeight) === scrollHeight) {
                if (data.length < count && !loading) {
                    loadData(currentPage + 1, filtersQuery);
                }
            }
        }
    };

    const onDeleteConfirm = () => {
        if (!itemIdToDelete) return;

        dispatch(deleteThunk(itemIdToDelete))
            .then((res) => {
                if (res.meta.requestStatus === 'fulfilled') {
                    setItemIdToDelete('');
                    loadData(0, filtersQuery);
                }
            })
            .catch((err) => {
                console.error(err);
            })
            .finally(() => {
                setItemIdToDelete('');
            });
    };

    return (
        <>
            <CardBox
                hasComponentLayout
                className={
                    'w-72 rounded-md h-fit max-h-full overflow-hidden flex flex-col'
                }
            >
                <div className={'flex items-center justify-between p-3'}>
                    <p className={'uppercase'}>{translateCrudLabel(column.label, t)}</p>
                    <p>{count}</p>
                </div>
                <div
                    ref={(node) => {
                        drop(node);
                        listInnerRef.current = node;
                    }}
                    className={'p-3 space-y-3 flex-1 overflow-y-auto max-h-[400px]'}
                    onScroll={onScroll}
                >
                    {data?.map((item) => (
                        <div key={item.id}>
                          <KanbanCard
                              item={item}
                              column={column}
                              showFieldName={showFieldName}
                              entityName={entityName}
                              setItemIdToDelete={setItemIdToDelete}
                          />
                        </div>
                    ))}
                    {!data?.length && (
                        <p className={'text-center py-8 bg-gray-50 dark:bg-dark-800'}>{translateCrudLabel('No data', t)}</p>
                    )}
                </div>
            </CardBox>
            <CardBoxModal
                title='Please confirm'
                buttonColor='info'
                buttonLabel={loading ? 'Deleting...' : 'Confirm'}
                isActive={!!itemIdToDelete}
                onConfirm={onDeleteConfirm}
                onCancel={() => setItemIdToDelete('')}
            >
                <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
            </CardBoxModal>
        </>
    );
};

export default KanbanColumn;
