import { useEffect, useState } from 'react'
import { useAppSelector } from '@/redux/store';
import { useTranslations } from 'next-intl';
import dynamic from 'next/dynamic';
import Cookies from 'universal-cookie';
import { useDispatch } from 'react-redux';
import { AppDispatch } from '@/redux/store';
import { setCurrentMembersGeneralOverviewDuration } from '@/redux/features/statistics-slice'
import { Loader2 } from 'lucide-react';

const ReactApexChart = dynamic(() => import('react-apexcharts'), {
    ssr: false,
    loading: () => <div className="flex items-center justify-center h-full">
        <Loader2 className="w-8 h-8 animate-spin" />
    </div>
});

export default function MembersOverviewChart()
{
    // get needed redux state
    const report = useAppSelector((state) => state.statisticsReducer.value.report)
    const currentMembersGeneralOverviewDuration = useAppSelector((state) => state.statisticsReducer.value.currentMembersGeneralOverviewDuration)
    const themeType = useAppSelector((state) => state.themeTypeReducer.value.themeType)
    
    // declare global variables
    const dispatch = useDispatch<AppDispatch>()
    const cookies = new Cookies();
    const t = useTranslations('statistics');
    const locale = cookies.get("NEXT_LOCALE")
    const isRtl = locale == 'ar' ? true : false
    const isDark = themeType == 'dark' ? true : false
    const [chartSeries, setChartSeries] = useState<{ name: string; data: number[] }[]>([]);
    const [labels, setLabels] = useState<string[]>([])
    const [isLoading, setIsLoading] = useState(true);

    // revenue Chart
    // prepare chart series and handle the transaction between currentMembersGeneralOverviewDuration
    useEffect(() => {
        if (!report?.membersGeneralOverview) {
            setIsLoading(true);
            return;
        }

        setIsLoading(true);
        
        try {
            // if chart duration is set to this week
            if (currentMembersGeneralOverviewDuration == 'thisWeek') {
                // set the labels       
                setLabels([t('sat'), t('sun'), t('mon'), t('tue'), t('wed'), t('thu'), t('fri')])
                
                // Initialize default data structure
                const defaultWeekData = {
                    sat: { totalMembers: 0, totalActiveSubs: 0, totalUnActiveSubs: 0, totalMansMembers: 0, totalGirlsMembers: 0 },
                    sun: { totalMembers: 0, totalActiveSubs: 0, totalUnActiveSubs: 0, totalMansMembers: 0, totalGirlsMembers: 0 },
                    mon: { totalMembers: 0, totalActiveSubs: 0, totalUnActiveSubs: 0, totalMansMembers: 0, totalGirlsMembers: 0 },
                    tue: { totalMembers: 0, totalActiveSubs: 0, totalUnActiveSubs: 0, totalMansMembers: 0, totalGirlsMembers: 0 },
                    wed: { totalMembers: 0, totalActiveSubs: 0, totalUnActiveSubs: 0, totalMansMembers: 0, totalGirlsMembers: 0 },
                    thu: { totalMembers: 0, totalActiveSubs: 0, totalUnActiveSubs: 0, totalMansMembers: 0, totalGirlsMembers: 0 },
                    fri: { totalMembers: 0, totalActiveSubs: 0, totalUnActiveSubs: 0, totalMansMembers: 0, totalGirlsMembers: 0 }
                };

                // Use data from report if available, otherwise use default data
                const weekData = report?.membersGeneralOverview?.value?.thisWeek?.days || defaultWeekData;
                
                // prepare the chart series
                setChartSeries([
                    {
                        name: t('totalMembers'),
                        data: ['sat', 'sun', 'mon', 'tue', 'wed', 'thu', 'fri'].map(day => weekData[day]?.totalMembers || 0),
                    },
                    {
                        name: t('totalActiveSubs'),
                        data: ['sat', 'sun', 'mon', 'tue', 'wed', 'thu', 'fri'].map(day => weekData[day]?.totalActiveSubs || 0),
                    },
                    {
                        name: t('totalUnActiveSubs'),
                        data: ['sat', 'sun', 'mon', 'tue', 'wed', 'thu', 'fri'].map(day => weekData[day]?.totalUnActiveSubs || 0),
                    },
                    {
                        name: t('totalMansMembers'),
                        data: ['sat', 'sun', 'mon', 'tue', 'wed', 'thu', 'fri'].map(day => weekData[day]?.totalMansMembers || 0),
                    },
                    {
                        name: t('totalGirlsMembers'),
                        data: ['sat', 'sun', 'mon', 'tue', 'wed', 'thu', 'fri'].map(day => weekData[day]?.totalGirlsMembers || 0),
                    },
                ]);
            }
            // if chart duration is set to this month
            else if(currentMembersGeneralOverviewDuration == 'thisMonth')
            {
                let thisMonthTotalSum : {
                    week : number,
                    thisWeekSum : {
                        "totalMembers": number,
                        "totalActiveSubs": number,
                        "totalUnActiveSubs": number,
                        "totalMansMembers": number,
                        "totalGirlsMembers": number
                    }
                }[];
                if(report?.membersGeneralOverview?.value.thisMonth)
                {
                    // if we founded a data for the current month
                    thisMonthTotalSum = report?.membersGeneralOverview?.value.thisMonth.weeks.map((v : any , i : number) : {
                        week: number,
                        thisWeekSum : {
                            "totalMembers": number,
                            "totalActiveSubs": number,
                            "totalUnActiveSubs": number,
                            "totalMansMembers": number,
                            "totalGirlsMembers": number
                        }
                    } => {
                        // we init the this week sum
                        let thisWeekSum = {
                                "totalMembers": 0,
                                "totalActiveSubs": 0,
                                "totalUnActiveSubs": 0,
                                "totalMansMembers": 0,
                                "totalGirlsMembers": 0
                            }
                        // we map through this month weeks
                        v.days.map((w : {
                            'sat': {
                                'totalMembers': number,
                                'totalActiveSubs': number,
                                'totalUnActiveSubs': number,
                                'totalMansMembers': number,
                                'totalGirlsMembers': number,
                            },
                            'sun': {
                                'totalMembers': number,
                                'totalActiveSubs': number,
                                'totalUnActiveSubs': number,
                                'totalMansMembers': number,
                                'totalGirlsMembers': number,
                            },
                            'mon': {
                                'totalMembers': number,
                                'totalActiveSubs': number,
                                'totalUnActiveSubs': number,
                                'totalMansMembers': number,
                                'totalGirlsMembers': number,
                            },
                            'tue': {
                                'totalMembers': number,
                                'totalActiveSubs': number,
                                'totalUnActiveSubs': number,
                                'totalMansMembers': number,
                                'totalGirlsMembers': number,
                            },
                            'wed': {
                                'totalMembers': number,
                                'totalActiveSubs': number,
                                'totalUnActiveSubs': number,
                                'totalMansMembers': number,
                                'totalGirlsMembers': number,
                            },
                            'thu': {
                                'totalMembers': number,
                                'totalActiveSubs': number,
                                'totalUnActiveSubs': number,
                                'totalMansMembers': number,
                                'totalGirlsMembers': number,
                            },
                            'fri': {
                                'totalMembers': number,
                                'totalActiveSubs': number,
                                'totalUnActiveSubs': number,
                                'totalMansMembers': number,
                                'totalGirlsMembers': number,
                            }
                        } , i : number) => {
                            // we loop through week days and we sum there data
                            Object.keys(w).forEach(function(key : "sat" | "sun" | "mon" | "tue" | "wed" | "thu" | "fri" | "_id" , index : number) {
                                if(key == '_id') return
                                thisWeekSum.totalMembers = thisWeekSum.totalMembers + w[key].totalMembers
                                thisWeekSum.totalActiveSubs = thisWeekSum.totalActiveSubs + w[key].totalActiveSubs
                                thisWeekSum.totalUnActiveSubs = thisWeekSum.totalUnActiveSubs + w[key].totalUnActiveSubs
                                thisWeekSum.totalMansMembers = thisWeekSum.totalMansMembers + w[key].totalMansMembers
                                thisWeekSum.totalGirlsMembers = thisWeekSum.totalGirlsMembers + w[key].totalGirlsMembers
                            })
                        })
                        // each week we return there sum data
                        return {
                            week: v.week,
                            thisWeekSum: thisWeekSum
                        }
                    })
                    let labels : [] = [];
                    thisMonthTotalSum.forEach(function(v , i) {
                        labels.push(t('week')+ ' ' +thisMonthTotalSum[i]["week"])
                    })
                    // set the labels       
                    setLabels(labels)
                    // we setup chart_series ( chart data )
                    let a : {
                        name: string,
                        data: {
                            "totalMembers": number,
                            "totalActiveSubs": number,
                            "totalUnActiveSubs": number,
                            "totalMansMembers": number,
                            "totalGirlsMembers": number
                        }
                    }[] = ['totalMembers' , 'totalActiveSubs' , 'totalUnActiveSubs' , 'totalMansMembers' , 'totalGirlsMembers'].map((v : string , i : number) : {
                        name: string,
                        data: {
                            "totalMembers": number,
                            "totalActiveSubs": number,
                            "totalUnActiveSubs": number,
                            "totalMansMembers": number,
                            "totalGirlsMembers": number
                        }
                    } => {
                        let data = thisMonthTotalSum.map((v2 : {
                            week: number,
                            thisWeekSum: {
                                "totalMembers": number,
                                "totalActiveSubs": number,
                                "totalUnActiveSubs": number,
                                "totalMansMembers": number,
                                "totalGirlsMembers": number
                            }
                        },i2 : number) => {
                            let index : 'totalMembers' | 'totalActiveSubs' | 'totalUnActiveSubs' | 'totalMansMembers' | 'totalGirlsMembers' = v;
                            return v2.thisWeekSum[index];
                        })
                        // return the line data
                        return {
                            name: t(v),
                            data: data
                        };
                    })
                    setChartSeries(a)
                }
                // if there was no data we use default return
                else {
                    setChartSeries([
                        {
                            name: '1'+t('week'),
                            data: [0,0,0,0,0],
                        },
                        {
                            name: '2'+t('week'),
                            data:  [0,0,0,0,0],
                        },
                        {
                            name: '3'+t('week'),
                            data:  [0,0,0,0,0],
                        },
                        {
                            name: '4'+t('week'),
                            data:  [0,0,0,0,0],
                        }
                    ])
                }
            }
            // if chart duration is set to this month
            else if(currentMembersGeneralOverviewDuration == 'thisYear')
            {
                // set the labels       
                setLabels([t('1month'), t('2month'), t('3month'), t('4month'), t('5month'), t('6month'), t('7month'), t('8month'), t('9month'), t('10month'), t('11month')])
                // check if there is current month report
                let thisYearTotalSum : {
                    month: number,
                    thisMonthWeeksSum: {
                        "totalMembers": number,
                        "totalActiveSubs": number,
                        "totalUnActiveSubs": number,
                        "totalMansMembers": number,
                        "totalGirlsMembers": number
                    }
                }[]
                if(report?.membersGeneralOverview?.value.thisYear)
                {
                    // if we founded a data for the current month
                    thisYearTotalSum = report?.membersGeneralOverview?.value.thisYear.months.map((v : any , i : number) : {
                        month : number,
                        thisMonthWeeksSum : {
                            "totalMembers": number,
                            "totalActiveSubs": number,
                            "totalUnActiveSubs": number,
                            "totalMansMembers": number,
                            "totalGirlsMembers": number
                        }
                    } => {
                        let summedWeeks = v.weeks.map((w : any , i : number) => {
                            // we map through this month weeks
                            let weekSum = w.days.map((d : {
                                'sat': {
                                    'totalMembers': number,
                                    'totalActiveSubs': number,
                                    'totalUnActiveSubs': number,
                                    'totalMansMembers': number,
                                    'totalGirlsMembers': number,
                                },
                                'sun': {
                                    'totalMembers': number,
                                    'totalActiveSubs': number,
                                    'totalUnActiveSubs': number,
                                    'totalMansMembers': number,
                                    'totalGirlsMembers': number,
                                },
                                'mon': {
                                    'totalMembers': number,
                                    'totalActiveSubs': number,
                                    'totalUnActiveSubs': number,
                                    'totalMansMembers': number,
                                    'totalGirlsMembers': number,
                                },
                                'tue': {
                                    'totalMembers': number,
                                    'totalActiveSubs': number,
                                    'totalUnActiveSubs': number,
                                    'totalMansMembers': number,
                                    'totalGirlsMembers': number,
                                },
                                'wed': {
                                    'totalMembers': number,
                                    'totalActiveSubs': number,
                                    'totalUnActiveSubs': number,
                                    'totalMansMembers': number,
                                    'totalGirlsMembers': number,
                                },
                                'thu': {
                                    'totalMembers': number,
                                    'totalActiveSubs': number,
                                    'totalUnActiveSubs': number,
                                    'totalMansMembers': number,
                                    'totalGirlsMembers': number,
                                },
                                'fri': {
                                    'totalMembers': number,
                                    'totalActiveSubs': number,
                                    'totalUnActiveSubs': number,
                                    'totalMansMembers': number,
                                    'totalGirlsMembers': number,
                                }
                            } , i : number) => {
                                // we init the this week sum
                                let thisWeekSum = {
                                    "totalMembers": 0,
                                    "totalActiveSubs": 0,
                                    "totalUnActiveSubs": 0,
                                    "totalMansMembers": 0,
                                    "totalGirlsMembers": 0
                                }
                                // we loop through week days and we sum there data
                                Object.keys(d).forEach(function(key : "sat" | "sun" | "mon" | "tue" | "wed" | "thu" | "fri" | "_id" , index : number) {
                                    if(key == '_id') return
                                    thisWeekSum.totalMembers = thisWeekSum.totalMembers + d[key].totalMembers
                                    thisWeekSum.totalActiveSubs = thisWeekSum.totalActiveSubs + d[key].totalActiveSubs
                                    thisWeekSum.totalUnActiveSubs = thisWeekSum.totalUnActiveSubs + d[key].totalUnActiveSubs
                                    thisWeekSum.totalMansMembers = thisWeekSum.totalMansMembers + d[key].totalMansMembers
                                    thisWeekSum.totalGirlsMembers = thisWeekSum.totalGirlsMembers + d[key].totalGirlsMembers
                                })
                                // each week we return there sum data
                                return thisWeekSum
                            })
                            return {
                                week: w.week,
                                weekSum: weekSum
                            }
                        })

                        let thisMonthWeeksSum = {
                            "totalMembers": 0,
                            "totalActiveSubs": 0,
                            "totalUnActiveSubs": 0,
                            "totalMansMembers": 0,
                            "totalGirlsMembers": 0
                        }

                        summedWeeks.map((v : {week: number, weekSum: {
                            "totalMembers": number,
                            "totalActiveSubs": number,
                            "totalUnActiveSubs": number,
                            "totalMansMembers": number,
                            "totalGirlsMembers": number
                        }[]},i : number) => {
                            thisMonthWeeksSum.totalMembers += v.weekSum[0].totalMembers
                            thisMonthWeeksSum.totalActiveSubs += v.weekSum[0].totalActiveSubs
                            thisMonthWeeksSum.totalUnActiveSubs += v.weekSum[0].totalUnActiveSubs
                            thisMonthWeeksSum.totalMansMembers += v.weekSum[0].totalMansMembers
                            thisMonthWeeksSum.totalGirlsMembers += v.weekSum[0].totalGirlsMembers
                        })
        
                        return {
                            month: v.month,
                            thisMonthWeeksSum: thisMonthWeeksSum
                        }
                    })
                    // prepare the labels
                    let labels : [] = [];
                    thisYearTotalSum.forEach(function(v , i) {
                        labels.push(t(thisYearTotalSum[i]["month"]+"month"))
                    })
                    setLabels(labels)
                    // we setup chart_series ( chart data )
                    let a : {
                        name: string,
                        data: {
                            "totalMembers": number,
                            "totalActiveSubs": number,
                            "totalUnActiveSubs": number,
                            "totalMansMembers": number,
                            "totalGirlsMembers": number
                        }
                    }[] = ['totalMembers' , 'totalActiveSubs' , 'totalUnActiveSubs' , 'totalMansMembers' , 'totalGirlsMembers'].map((v : string , i : number) : {
                        name: string,
                        data: {
                            "totalMembers": number,
                            "totalActiveSubs": number,
                            "totalUnActiveSubs": number,
                            "totalMansMembers": number,
                            "totalGirlsMembers": number
                        }
                    } => {
                        let data = thisYearTotalSum.map((v2 : {
                            month: number,
                            thisMonthWeeksSum: {
                                "totalMembers": number,
                                "totalActiveSubs": number,
                                "totalUnActiveSubs": number,
                                "totalMansMembers": number,
                                "totalGirlsMembers": number
                            }
                        },i2 : number) => {
                            let index : 'totalMembers' | 'totalActiveSubs' | 'totalUnActiveSubs' | 'totalMansMembers' | 'totalGirlsMembers' = v;
                            return v2.thisMonthWeeksSum[index];
                        })
                        // return the line data
                        return {
                            name: t(v),
                            data: data
                        };
                    })
                    setChartSeries(a)
                }
                // if there was no data we use default return
                else {
                    setChartSeries([
                        {
                            name: '1'+t('week'),
                            data: [0,0,0,0,0],
                        },
                        {
                            name: '2'+t('week'),
                            data:  [0,0,0,0,0],
                        },
                        {
                            name: '3'+t('week'),
                            data:  [0,0,0,0,0],
                        },
                        {
                            name: '4'+t('week'),
                            data:  [0,0,0,0,0],
                        }
                    ])
                }
            }
            
        } catch (error) {
            console.error('Error preparing chart data:', error);
        } finally {
            setIsLoading(false);
        }
    }, [report, currentMembersGeneralOverviewDuration, t]);

    // Chart options
    const chartOptions: ApexCharts.ApexOptions = {
        chart: {
            type: 'bar',
            height: 350,
            stacked: true,
            toolbar: {
                show: true,
            },
            zoom: {
                enabled: true,
            },
            foreColor: isDark ? '#fff' : '#333',
            fontFamily: isRtl ? 'Tajawal, sans-serif' : 'Inter, sans-serif',
        },
        responsive: [
            {
                breakpoint: 480,
                options: {
                    legend: {
                        position: 'bottom',
                        offsetY: 10,
                    },
                },
            },
        ],
        plotOptions: {
            bar: {
                horizontal: false,
                borderRadius: 5,
                dataLabels: {
                    total: {
                        enabled: true,
                        style: {
                            fontSize: '13px',
                            fontWeight: 900,
                        },
                    },
                },
            },
        },
        xaxis: {
            type: 'category',
            categories: labels,
            labels: {
                style: {
                    colors: isDark ? '#fff' : '#333',
                },
            },
        },
        yaxis: {
            labels: {
                style: {
                    colors: isDark ? '#fff' : '#333',
                },
            },
        },
        legend: {
            position: 'right',
            offsetY: 40,
            labels: {
                colors: isDark ? '#fff' : '#333',
            },
        },
        fill: {
            opacity: 1,
        },
        tooltip: {
            theme: isDark ? 'dark' : 'light',
            y: {
                formatter: function (val) {
                    return val.toString();
                },
            },
        },
    };


    if (isLoading || !report?.membersGeneralOverview) {
        return (
            <div className="w-full h-full flex items-center justify-center min-h-[400px]">
                <Loader2 className="w-8 h-8 animate-spin" />
            </div>
        );
    }


    return (
        <div className="w-full h-full">
            <div className="flex flex-col">
                <div className="flex justify-between items-center mb-4">
                    <h3 className="text-lg font-semibold">{t('membersGeneralOverview')}</h3>
                    <div className="flex gap-2">
                        <button
                            onClick={() => dispatch(setCurrentMembersGeneralOverviewDuration('thisWeek'))}
                            className={`px-3 py-1 rounded-md text-sm ${currentMembersGeneralOverviewDuration === 'thisWeek' ? 'bg-primary text-white' : 'bg-gray-200 dark:bg-gray-700'}`}
                        >
                            {t('thisWeek')}
                        </button>
                        <button
                            onClick={() => dispatch(setCurrentMembersGeneralOverviewDuration('thisMonth'))}
                            className={`px-3 py-1 rounded-md text-sm ${currentMembersGeneralOverviewDuration === 'thisMonth' ? 'bg-primary text-white' : 'bg-gray-200 dark:bg-gray-700'}`}
                        >
                            {t('thisMonth')}
                        </button>
                        <button
                            onClick={() => dispatch(setCurrentMembersGeneralOverviewDuration('thisYear'))}
                            className={`px-3 py-1 rounded-md text-sm ${currentMembersGeneralOverviewDuration === 'thisYear' ? 'bg-primary text-white' : 'bg-gray-200 dark:bg-gray-700'}`}
                        >
                            {t('thisYear')}
                        </button>
                    </div>
                </div>
                
                <div className="w-full h-[400px] mt-4">
                    <ReactApexChart
                        options={chartOptions}
                        series={chartSeries}
                        type="bar"
                        height="100%"
                    />
                </div>
            </div>
        </div>
    )
}