import { useEffect, useState } from 'react';
import { useDispatch } from 'react-redux';
import { DndProvider, useDrag, useDrop } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';

import { setPageTitle } from '../../../store/themeConfigSlice';

import ProtectedRoute from '@/components/ProtectedRoute';
import { coloredToast } from '@/lib/toast';
import { logActivity } from '@/utils/activityLogger';

interface ImageList {
    id: number;
    img_url: string;
    alt: string;
    link: string;
}

const BannerSettings = () => {
    const dispatch = useDispatch();
    const [isMounted, setIsMounted] = useState(false);

    useEffect(() => {
        setIsMounted(true);
        dispatch(setPageTitle('Banner Setting'));
    }, []);

    const [bannerDesktop, setBannerDesktop] = useState<ImageList[]>([]);
    const [bannerMobile, setBannerMobile] = useState<ImageList[]>([]);
    const [initialBannerDesktop, setInitialBannerDesktop] = useState<ImageList[]>([]);
    const [initialBannerMobile, setInitialBannerMobile] = useState<ImageList[]>([]);


    const [isLoading, setIsLoading] = useState(false);

    const fetchDataPoint = async () => {
        const api_url = process.env.API_URL;
        const response = await fetch(`${api_url}api/setting/banner`, {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json',
            },
            credentials: 'include',
        });
        if (response.ok) {
            const { banner } = await response.json();
            setBannerDesktop(banner.desktop);
            setBannerMobile(banner.mobile);
            setInitialBannerDesktop(JSON.parse(JSON.stringify(banner.desktop)));
            setInitialBannerMobile(JSON.parse(JSON.stringify(banner.mobile)));
        }
    };
    useEffect(() => {
        if (isMounted) {
            fetchDataPoint();
        }
    }, [isMounted]);

    const addBanner = (type: string, setBanner: Function, banner: Array<any>) => {
        const maxId = banner.length ? banner.reduce((max: number, character: any) => (character.id > max ? character.id : max), banner[0].id) : 0;

        setBanner([
            ...banner,
            {
                id: maxId + 1,
                img_url: '',
                alt: '',
                link: '',
            },
        ]);
    };

    const removeBanner = (type: string, setBanner: Function, banner: Array<any>, item: any = null) => {
        setBanner(banner.filter((d: any) => d.id !== item.id));
    };

    const changeBanner = (type: string, setBanner: Function, banner: Array<any>, value: any, id: number) => {
        const updatedBanner = banner.map((item) => {
            if (item.id === id) {
                return {
                    ...item,
                    [type]: value,
                };
            }
            return item;
        });

        setBanner(updatedBanner);
    };

    const addBannerDesktop = () => {
        addBanner('desktop', setBannerDesktop, bannerDesktop);
    };

    const removeBannerDesktop = (item: any = null) => {
        removeBanner('desktop', setBannerDesktop, bannerDesktop, item);
    };

    const changeDesktop = (type: string, value: any, id: number) => {
        changeBanner(type, setBannerDesktop, bannerDesktop, value, id);
    };

    const addBannerMobile = () => {
        addBanner('mobile', setBannerMobile, bannerMobile);
    };

    const removeBannerMobile = (item: any = null) => {
        removeBanner('mobile', setBannerMobile, bannerMobile, item);
    };

    const changeMobile = (type: string, value: any, id: number) => {
        changeBanner(type, setBannerMobile, bannerMobile, value, id);
    };

    const getBannerChangesDescription = () => {
        const changes: string[] = [];
    
        const compareBanners = (initial: ImageList[], current: ImageList[], label: string) => {
            initial.forEach((item, index) => {
                const currentItem = current.find((c) => c.id === item.id);
                if (!currentItem) {
                    changes.push(`${label} [${index}]: Removed`);
                    return;
                }
    
                if (item.img_url !== currentItem.img_url) {
                    changes.push(`${label} [${index}]: img_url changed`);
                }
                if (item.alt !== currentItem.alt) {
                    changes.push(`${label} [${index}]: alt changed`);
                }
                if (item.link !== currentItem.link) {
                    changes.push(`${label} [${index}]: link changed`);
                }
            });
    
            // Check newly added
            current.forEach((item, index) => {
                const existing = initial.find((i) => i.id === item.id);
                if (!existing) {
                    changes.push(`${label} [${index}]: Added`);
                }
            });
        };
    
        compareBanners(initialBannerDesktop, bannerDesktop, 'Desktop');
        compareBanners(initialBannerMobile, bannerMobile, 'Mobile');
    
        return changes.length ? changes.join(' | ') : 'No changes made.';
    };
    

    const saveBannerSetting = async () => {
        const bannerSetting = {
            desktop: bannerDesktop.filter((banner) => banner.img_url),
            mobile: bannerMobile.filter((banner) => banner.img_url),
        };
        setIsLoading(true);
        try {
            const api_url = process.env.API_URL;
            const response = await fetch(`${api_url}api/setting/banner/update`, {
                method: 'PATCH',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify(bannerSetting),
                credentials: 'include',
            });

            const res = await response.json();
            if (!response.ok) {
                throw new Error(res.message);
            }

            coloredToast('success', 'Banner setting has been saved');
            await logActivity({
                location: 'Banner Setting',
                description: `Banner Updated: ${getBannerChangesDescription()}`,
            });
        } catch (error: any) {
            coloredToast('warning', error.message || 'Something went wrong');
            await logActivity({
                location: 'Banner Setting',
                description: `Banner Error: ${error.message}`,
            });
        }
        setIsLoading(false);
    };

    return (
        <DndProvider backend={HTML5Backend}>
            <>
                {isMounted && (
                        <>
                            <div className="flex flex-col gap-2.5 xl:flex-row">
                                <div className="panel flex-1 px-0 py-2 ltr:xl:mr-6 rtl:xl:ml-6">
                                    <div className="flex flex-wrap justify-between px-4">
                                        <div className="mb-4 w-full lg:w-1/2 ">
                                            <div className="text-lg">Banner Desktop</div>
                                            <div className="mb-4 mt-4 w-full ">
                                                <div className="mb-4 mt-2 table w-full">
                                                    <table>
                                                        <thead>
                                                            <tr>
                                                                <th></th>
                                                                <th>Image Url</th>
                                                                <th>Alt</th>
                                                                <th>Link</th>
                                                                <th></th>
                                                            </tr>
                                                        </thead>
                                                        <tbody>
                                                            {bannerDesktop.length <= 0 && (
                                                                <tr>
                                                                    <td colSpan={2} className="!text-center font-semibold">
                                                                        No Banner Available
                                                                    </td>
                                                                </tr>
                                                            )}
                                                            {bannerDesktop.map((list: any, index: number) => (
                                                                <DraggableBannerRow
                                                                    key={list.id}
                                                                    list={list}
                                                                    banner={bannerDesktop}
                                                                    setBanner={setBannerDesktop}
                                                                    index={index}
                                                                    changeBanner={changeDesktop}
                                                                    removeBanner={removeBannerDesktop}
                                                                />
                                                            ))}
                                                        </tbody>
                                                    </table>
                                                    <div className="m-4">
                                                        <button type="button" className="btn btn-outline-primary btn-sm" onClick={addBannerDesktop}>
                                                            Add Banner Desktop
                                                        </button>
                                                    </div>
                                                </div>
                                            </div>
                                        </div>
                                        <div className="mb-4 w-full lg:w-1/2 ">
                                            <div className="text-lg">Banner Mobile</div>
                                            <div className="mb-4 mt-4 w-full ">
                                                <div className="mb-4 mt-2 table w-full">
                                                    <table>
                                                        <thead>
                                                            <tr>
                                                                <th></th>
                                                                <th>Image Url</th>
                                                                <th>Alt</th>
                                                                <th>Link</th>
                                                                <th></th>
                                                            </tr>
                                                        </thead>
                                                        <tbody>
                                                            {bannerMobile.length <= 0 && (
                                                                <tr>
                                                                    <td colSpan={2} className="!text-center font-semibold">
                                                                        No Banner Available
                                                                    </td>
                                                                </tr>
                                                            )}
                                                            {bannerMobile.map((list: any, index: number) => (
                                                                <DraggableBannerRow
                                                                    key={list.id}
                                                                    list={list}
                                                                    index={index}
                                                                    banner={bannerMobile}
                                                                    setBanner={setBannerMobile}
                                                                    changeBanner={changeMobile}
                                                                    removeBanner={removeBannerMobile}
                                                                />
                                                            ))}
                                                        </tbody>
                                                    </table>
                                                    <div className="m-4">
                                                        <button type="button" className="btn btn-outline-primary btn-sm" onClick={addBannerMobile}>
                                                            Add Banner Mobile
                                                        </button>
                                                    </div>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div className="panel mt-3 w-fit">
                                <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4 xl:grid-cols-1">
                                    <button type="button" disabled={isLoading} onClick={saveBannerSetting} className="btn btn-success w-full gap-2">
                                        {isLoading ? (
                                            <span className="inline-block h-5 w-5 animate-spin rounded-full border-2 border-white border-l-transparent align-middle ltr:mr-4 rtl:ml-4"></span>
                                        ) : (
                                            <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 shrink-0 ltr:mr-2 rtl:ml-2">
                                                <path
                                                    d="M3.46447 20.5355C4.92893 22 7.28595 22 12 22C16.714 22 19.0711 22 20.5355 20.5355C22 19.0711 22 16.714 22 12C22 11.6585 22 11.4878 21.9848 11.3142C21.9142 10.5049 21.586 9.71257 21.0637 9.09034C20.9516 8.95687 20.828 8.83317 20.5806 8.58578L15.4142 3.41944C15.1668 3.17206 15.0431 3.04835 14.9097 2.93631C14.2874 2.414 13.4951 2.08581 12.6858 2.01515C12.5122 2 12.3415 2 12 2C7.28595 2 4.92893 2 3.46447 3.46447C2 4.92893 2 7.28595 2 12C2 16.714 2 19.0711 3.46447 20.5355Z"
                                                    stroke="currentColor"
                                                    strokeWidth="1.5"
                                                />
                                                <path
                                                    d="M17 22V21C17 19.1144 17 18.1716 16.4142 17.5858C15.8284 17 14.8856 17 13 17H11C9.11438 17 8.17157 17 7.58579 17.5858C7 18.1716 7 19.1144 7 21V22"
                                                    stroke="currentColor"
                                                    strokeWidth="1.5"
                                                />
                                                <path opacity="0.5" d="M7 8H13" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" />
                                            </svg>
                                        )}
                                        Save
                                    </button>
                                </div>
                            </div>
                        </>
                    )}
            </>
        </DndProvider>
    );
};

const DraggableBannerRow = ({
    list,
    index,
    banner,
    setBanner,
    changeBanner,
    removeBanner,
}: {
    list: ImageList;
    index: number;
    banner: Array<any>;
    setBanner: Function;
    changeBanner: Function;
    removeBanner: Function;
}) => {
    const [{ isDragging }, drag] = useDrag({
        type: 'BANNER_ROW',
        item: { id: list.id, index },
        collect: (monitor) => ({
            isDragging: !!monitor.isDragging(),
        }),
    });

    const [, drop] = useDrop({
        accept: 'BANNER_ROW',
        hover(item: { id: number; index: number }) {
            if (item.id !== list.id) {
                const dragIndex = item.index;
                const hoverIndex = index;

                const updatedBannerList = [...banner];
                const dragItem = updatedBannerList[dragIndex];
                updatedBannerList.splice(dragIndex, 1);
                updatedBannerList.splice(hoverIndex, 0, dragItem);

                setBanner(updatedBannerList);

                item.index = hoverIndex;
            }
        },
    });

    return (
        <tr className={`align-center ${isDragging ? 'dragging' : ''}`} key={list.id} ref={(node) => { drag(drop(node)); }}>
            <td className="align-middle">
                <svg height="18" viewBox="0 0 48 48" width="48" xmlns="http://www.w3.org/2000/svg" fill='currentColor'>
                    <path d="M4 31v4h40v-4h-40zm0-10v4h40v-4h-40zm0-10v4h40v-4h-40z" />
                    <path d="M0 0h48v48h-48z" fill="none" />
                </svg>
            </td>
            <td>
                <input type="text" className="form-input w-full" placeholder="https://..." value={list.img_url} onChange={(e) => changeBanner('img_url', e.target.value, list.id)} />
            </td>
            <td>
                <input type="text" className="form-input w-full" placeholder="alt text image" value={list.alt} onChange={(e) => changeBanner('alt', e.target.value, list.id)} />
            </td>
            <td>
                <input type="text" className="form-input w-full" placeholder="link" value={list.link} onChange={(e) => changeBanner('link', e.target.value, list.id)} />
            </td>

            <td>
                <button type="button" onClick={() => removeBanner(list)}>
                    <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
                        <line x1="18" y1="6" x2="6" y2="18"></line>
                        <line x1="6" y1="6" x2="18" y2="18"></line>
                    </svg>
                </button>
            </td>
        </tr>
    );
};

export default BannerSettings;
