import React, { useState, useEffect, use } from 'react';
import { useSession } from "next-auth/react"
import Link from 'next/link';
import Calendar from 'react-calendar';
import 'react-calendar/dist/Calendar.css';
import axiosInstance from '../../../src/axiosSecure';
import Layout from "../../../components/layout"
import Shift from '../../../components/calendar/ShiftComponent';
import { DayOfWeek, UserRole } from '@prisma/client';
import { env } from 'process'
import ShiftComponent from '../../../components/calendar/ShiftComponent';
//import { set } from 'date-fns';
const common = require('src/helpers/common');
import { toast } from 'react-toastify';
import ProtectedRoute from '../../../components/protectedRoute';
import ConfirmationModal from '../../../components/ConfirmationModal';
import LocalShippingIcon from '@mui/icons-material/LocalShipping';
const { DateTime } = require('luxon');

// import { FaPlus, FaCogs, FaTrashAlt, FaSpinner } from 'react-icons/fa'; // Import FontAwesome icons



// import { useSession,} from 'next-auth/react';
// import { getToken } from "next-auth/jwt"

//define Shift type
interface Shift {
    id: number;
    startTime: Date;
    endTime: Date;
    cartEventId: number;
    assignments: Assignment[];
}
interface Assignment {
    id: number;
    publisherId: number;
    shiftId: number;
    isConfirmed: boolean;
    publisher: Publisher;
}
interface Publisher {
    id: number;
    firstName: string;
    lastName: string;
    isImported: boolean;
}

// https://www.npmjs.com/package/react-calendar
export default function CalendarPage({ initialEvents, initialShifts }) {

    const { data: session } = useSession()
    //if logged in, get the user's email
    // var email = "";
    // const [events, setEvents] = useState(initialEvents);

    const events = initialEvents;


    const [allShifts, setAllShifts] = useState(initialShifts);
    const [isPublished, setIsPublished] = useState(() => initialShifts.some(shift => shift.isPublished));
    const [value, onChange] = useState<Date>(new Date());
    const [shifts, setShifts] = React.useState([]);
    const [error, setError] = React.useState(null);
    const [availablePubs, setAvailablePubs] = React.useState([]);

    const [selectedShiftId, setSelectedShiftId] = useState(null);

    const [isOperationInProgress, setIsOperationInProgress] = useState(false);
    const [progress, setProgress] = useState(0);

    const [activeButton, setActiveButton] = useState(null);
    const isLoading = (buttonId) => activeButton === buttonId;

    // ------------------ MODAL ------------------
    const [isModalOpen, setIsModalOpen] = useState(false);
    const [modalPub, setModalPub] = useState(null);

    // ------------------ no assignments checkbox ------------------
    const [filterShowWithoutAssignments, setFilterShowWithoutAssignments] = useState(false);
    const handleCheckboxChange = (event) => {
        setFilterShowWithoutAssignments(!filterShowWithoutAssignments); // Toggle the checkbox state
    };

    useEffect(() => {
        console.log("checkbox checked: " + filterShowWithoutAssignments);
        handleCalDateChange(value); // Call handleCalDateChange whenever isCheckboxChecked changes
    }, [filterShowWithoutAssignments]); // Dependency array

    const [selectedMonth, setSelectedMonth] = useState(new Date().getMonth());
    useEffect(() => {
        const newMonth = value.getMonth();
        if (newMonth !== selectedMonth) {
            setSelectedMonth(newMonth);
        }
    }, [value, selectedMonth]);


    const handleCalDateChange = async (selectedDate) => {
        var date = new Date(common.getDateFromDateTime(selectedDate));//ToDo: check if seting the timezone affects the selectedDate?!
        var dateStr = common.getISODateOnly(date);
        console.log("Setting date to '" + date.toLocaleDateString() + "' from '" + selectedDate.toLocaleDateString() + "'. ISO: " + date.toISOString(), "locale ISO:", common.getISODateOnly(date));
        if (filterShowWithoutAssignments) {
            console.log(`getting unassigned publishers for ${common.getMonthName(date.getMonth())} ${date.getFullYear()}`);
            const { data: availablePubsForDate } = await axiosInstance.get(`/api/?action=getUnassignedPublishers&date=${dateStr}&select=id,firstName,lastName,isActive,desiredShiftsPerMonth`);
            setAvailablePubs(availablePubsForDate);
        }
        else {
            console.log(`getting shifts for ${common.getISODateOnly(date)}`)
            try {
                const { data: shiftsForDate } = await axiosInstance.get(`/api/?action=getShiftsForDay&date=${dateStr}`);
                setShifts(shiftsForDate);
                setIsPublished(shiftsForDate.some(shift => shift.isPublished));
                let { data: availablePubsForDate } = await axiosInstance.get(`/api/?action=filterPublishersNew&date=${dateStr}&select=id,firstName,lastName,isActive,desiredShiftsPerMonth&includeOldAvailabilities=${filterShowWithoutAssignments}`);

                availablePubsForDate.forEach(pub => {
                    pub.canTransport = pub.availabilities.some(av =>
                        av.isWithTransportIn || av.isWithTransportOut
                    );
                });
                //remove availabilities that are isFromPreviousAssignment or from previous month for each publisher
                // availablePubsForDate = availablePubsForDate.map(pub => {
                //     pub.availabilities = pub.availabilities.filter(avail => avail.isFromPreviousAssignment == false);
                //     return pub;
                // });


                //commented for now: remove unavailable publishers
                // availablePubsForDate = availablePubsForDate.map(pub => {
                //     pub.availabilities = pub.availabilities.filter(avail => avail.isFromPreviousAssignment == false);
                //     return pub;
                // });

                setAvailablePubs(availablePubsForDate);
                console.log(`found shifts for ${dateStr}: ${shiftsForDate.length}`);
            } catch (err) {
                console.error("Error fetching shifts:", err);
                setError(err);
            }
            onChange(selectedDate);
        }
    }

    const handleShiftSelection = (selectedShift) => {
        setSelectedShiftId(selectedShift.id);
        const updatedPubs = availablePubs.map(pub => {
            pub.isAvailableForShift = false;
            pub.canTransport = false;
            const av = pub.availabilities?.find(avail =>
                avail.startTime <= selectedShift.startTime
                && avail.endTime >= selectedShift.endTime
            );
            if (av) {
                pub.isAvailableForShift = true;
                pub.canTransport = av.isWithTransportIn || av.isWithTransportOut;
            }

            // const isAvailableForShift = pub.availabilities.some(avail =>
            //     avail.startTime <= selectedShift.startTime
            //     && avail.endTime >= selectedShift.endTime
            //     && avail.isFromPreviousAssignment == false
            // );
            const isAvailableForShiftWithPrevious = pub.availabilities.some(avail =>
                avail.startTime <= selectedShift.startTime
                && avail.endTime >= selectedShift.endTime
            );
            // //! console.log(`Publisher ${pub.firstName} ${pub.lastName} is available for shift ${selectedShift.id}: ${isAvailableForShift}`);
            // //// console.log(`Publisher ${pub.firstName} ${pub.lastName} has ${pub.availabilities.length} availabilities :` + pub.availabilities.map(avail => avail.startTime + " - " + avail.endTime));
            // //// console.log(`Publisher ${pub.firstName} ${pub.lastName} has ${pub.availabilities.length} availabilities :` + stringify.join(', 'pub.availabilities.map(avail => avail.id)));

            // const availabilitiesIds = pub.availabilities.map(avail => avail.id).join(', ');
            // //! console.log(`Publisher ${pub.firstName} ${pub.lastName} has ${pub.availabilities.length} availabilities with IDs: ${availabilitiesIds}`);
            return { ...pub, isAvailableForShiftWithPrevious, isSelected: pub.id === selectedShift.selectedPublisher?.id };
        });

        // Sort publishers based on their availability state. use currentDayAssignments, currentWeekAssignments,
        // currentMonthAssignments and previousMonthAssignments properties
        // Sort publishers based on availability and then by assignment counts.
        const sortedPubs = updatedPubs.sort((a, b) => {
            if (a.isActive !== b.isActive) {
                return a.isActive ? -1 : 1;
            }
            // First, sort by isselected.
            if (a.isSelected !== b.isSelected) {
                return a.isSelected ? -1 : 1;
            }

            // Them, sort by availability.
            if (a.isAvailableForShift !== b.isAvailableForShift) {
                return a.isAvailableForShift ? -1 : 1;
            }

            // If both are available (or unavailable) for the shift, continue with the additional sorting logic.

            // Prioritize those without currentDayAssignments.
            if (!!a.currentDayAssignments !== !!b.currentDayAssignments) {
                return a.currentDayAssignments ? 1 : -1;
            }

            // Then prioritize those without currentWeekAssignments.
            if (!!a.currentWeekAssignments !== !!b.currentWeekAssignments) {
                return a.currentWeekAssignments ? 1 : -1;
            }
            // Prioritize those with fewer currentMonthAvailabilityHoursCount.
            if (a.currentMonthAvailabilityHoursCount !== b.currentMonthAvailabilityHoursCount) {
                return a.currentMonthAvailabilityHoursCount - b.currentMonthAvailabilityHoursCount;
            }
            // Finally, sort by (currentMonthAssignments - previousMonthAssignments).
            return (a.currentMonthAssignments - a.previousMonthAssignments) - (b.currentMonthAssignments - b.previousMonthAssignments);
        });
        setAvailablePubs(sortedPubs);
    };

    const handleSelectedPublisher = (publisher) => {
        // Do something with the selected publisher
        console.log("handle pub clicked:", publisher);
    }
    const handlePublisherModalOpen = async (publisher) => {
        // Do something with the selected publisher
        console.log("handle pub modal opened:", publisher.firstName + " " + publisher.lastName);
        let date = new Date(value);
        const { data: publisherInfo } = await axiosInstance.get(`/api/?action=getPublisherInfo&id=${publisher.id}&date=${common.getISODateOnly(date)}`);
        publisher.assignments = publisherInfo.assignments;
        publisher.availabilities = publisherInfo.availabilities;
        publisher.email = publisherInfo.email;
        setModalPub(publisher);
        setIsModalOpen(true);

    }

    // file uploads
    const [fileActionUrl, setFileActionUrl] = useState('');
    const [file, setFile] = useState(null);
    const handleFileUpload = async (event) => {
        setIsOperationInProgress(true);
        console.log('handleFileUpload(): Selected file:', event.target.files[0], 'actionUrl:', fileActionUrl);
        setFile(event.target.files[0]);

        if (!event.target.files[0]) {
            toast.error('Моля, изберете файл!');
            return;
        }

        uploadToServer(fileActionUrl, event.target.files[0]);
    };


    const uploadToServer = async (actionUrl, file) => {

        const formData = new FormData();
        formData.append('file', file);
        try {

            const response = await fetch('/' + actionUrl, {
                method: 'POST',
                body: formData,
            });
            const result = await response.json();
            if (result.fileId) {
                pollProgress(result.fileId);
            }
            console.log('Result from server-side API:', result);
            toast.info(result.message || "Файла е качен! Започна обработката на данните...");

        } catch (error) {
            toast.error(error.message || "Възникна грешка при обработката на данните.");
        } finally {
        }

    };


    const pollProgress = (fileId: any) => {
        fetch(`/api/upload?fileId=${fileId}`)
            .then(response => response.json())
            .then(data => {
                updateProgressBar(data.progress); // Update the progress bar

                if (data.progress < 98 && data.progress > 0) {
                    // Poll every second if progress is between 0 and 100
                    setTimeout(() => pollProgress(fileId), 1000);
                } else if (data.progress === 0) {
                    // Handle error case
                    toast.error("Възникна грешка при обработката на данните.");
                    setIsOperationInProgress(false);
                } else {
                    // Handle completion case
                    toast.success("Файла беше обработен успешно!");
                    setIsOperationInProgress(false);
                }
            })
            .catch(error => {
                console.error('Error polling for progress:', error);
                toast.error("Грешка при обновяването на напредъка");
                setIsOperationInProgress(false)
            })
            .finally();

    };

    const updateProgressBar = (progress: string) => {
        // Implement the logic to update your progress bar based on the 'progress' value
        // For example, updating the width of a progress bar element
        const progressBar = document.getElementById('progress-bar');
        if (progressBar) {
            progressBar.style.width = progress + '%';
        }
    };

    function getEventClassname(event, allShifts, date) {
        if (event && allShifts) {
            const matchingShifts = allShifts.filter(shift => {
                const shiftDate = new Date(shift.startTime);
                return shift.cartEventId === event.id && shiftDate.getDate() === date.getDate() && shiftDate.getMonth() === date.getMonth();
            });

            //get matching shifts with assignments using nextcrud
            //const { data: withAss } = await axiosInstance.get(`/shifts?include=assignments&where={"id":{"$in":[${matchingShifts.map(shift => shift.id)}]}}`);
            const minCount = Math.min(...matchingShifts.map(shift => shift.assignedCount)) || 0;
            //const minCount = 4;
            //console.log("matchingShifts: " + matchingShifts) + " for date " + date;
            if (matchingShifts.length < 3) { return "text-gray"; }
            else {
                if (minCount === 0) return "text-red-700 font-bold ";
                if (minCount === 1) return "text-brown-900 font-bold ";
                if (minCount === 2) return "text-orange-500";
                if (minCount === 3) return "text-yellow-500";
                if (minCount >= 4) return "text-blue-500";
            }
        }
        return "text-default";  // A default color in case none of the conditions are met.
    }


    const onTileContent = ({ date, view }) => {
        // Add your logic here
        var dayName = common.DaysOfWeekArray[date.getDayEuropean()];
        var classname = "";

        if (events == null) {
            return <div>{"  "}</div>;
        }

        const event = events.find((event) => {
            return event.dayofweek == dayName;
        });
        if (event != null) {
            const classname = getEventClassname(event, allShifts, date);
            return <div className={classname}>
                {new Date(event.startTime).getHours() + "-" + new Date(event.endTime).getHours()}ч.
            </div>

        }
        return <div>{"  "}</div>;
    };

    const addAssignment = async (publisher, shiftId) => {
        try {
            console.log(`new assignment for publisher ${publisher.id} - ${publisher.firstName} ${publisher.lastName}`);
            const newAssignment = {
                publisher: { connect: { id: publisher.id } },
                shift: { connect: { id: shiftId } },
                isActive: true,
                isConfirmed: true
            };
            const { data } = await axiosInstance.post("/api/data/assignments", newAssignment);
            // Update the 'publisher' property of the returned data with the full publisher object
            data.publisher = publisher;
        } catch (error) {
            console.error("Error adding assignment:", error);
        }
    };
    const removeAssignment = async (publisher, shiftId) => {
        try {
            const assignment = publisher.assignments.find(ass => ass.shift.id === shiftId);
            console.log(`remove assignment for shift ${shiftId}`);
            const { data } = await axiosInstance.delete(`/api/data/assignments/${assignment.id}`);
        } catch (error) {
            console.error("Error removing assignment:", error);
        }
    }

    // ----------------------------------------------------------
    // button handlers
    // ----------------------------------------------------------
    const importShifts = async () => {
        try {
            setActiveButton("importShifts");
            setIsOperationInProgress(true);
            let date = new Date(value);
            date.setDate(date.getDate() + 1);
            const dateString = common.getISODateOnly(date);
            const fileInput = document.getElementById('fileInput');
            // setFileActionUrl(`readword/${dateString.slice(0, 4)}/${dateString.slice(5, 7)}/${dateString.slice(8, 10)}?action=import`);
            setFileActionUrl(`api/upload?action=readword&date=${dateString}`);
            console.log('fileaction set to ' + fileActionUrl);

            fileInput.click();
            //handleFileUpload({ target: { files: [file] } });
            fileInput.value = null;
        } catch (error) {
            toast.error(error);
        } finally {
            setIsOperationInProgress(false);
            setActiveButton(null);
        }
    }

    const fetchShifts = async () => {
        try {
            setActiveButton("fetchShifts");
            // where:{"startTime":"$and":{{ "$gte": "2022-12-04T15:09:47.768Z", "$lt": "2022-12-10T15:09:47.768Z" }}}
            const { data } = await axiosInstance.get(`/api/data/shifts?include=assignments.publisher&where={"startTime":{"$and":[{"$gte":"2022-12-04T15:09:47.768Z","$lt":"2022-12-10T15:09:47.768Z"}]}}`);
            setShifts(data);
            toast.success('Готово!', { autoClose: 1000 });
        } catch (error) {
            console.log(error);
        } finally {
            setActiveButton(null);
        }
    }
    const generateShifts = async (buttonId, copyFromPrevious = false, autoFill = false, forDay?: Boolean | null) => {
        try {
            setActiveButton(buttonId);
            const endpoint = `/api/shiftgenerate?action=generate&date=${common.getISODateOnly(value)}&copyFromPreviousMonth=${copyFromPrevious}&autoFill=${autoFill}&forDay=${forDay}`;
            const { shifts } = await axiosInstance.get(endpoint);
            toast.success('Готово!', { autoClose: 1000 });
            setIsMenuOpen(false);
        } catch (error) {
            console.log(error);
        } finally {
            setActiveButton(null);
        }
    }
    const deleteShifts = async (buttonId, forDay: Boolean) => {
        try {
            setActiveButton(buttonId);
            await axiosInstance.get(`/api/shiftgenerate?action=delete&date=${common.getISODateOnly(value)}&forDay=${forDay}`);
            toast.success('Готово!', { autoClose: 1000 });
            setIsMenuOpen(false);
        } catch (error) {
            console.log(error);
        } finally {
            setActiveButton(null);
        }
    }
    const sendMails = async () => {
        try {
            var month = new Date(value).getMonth() + 1;
            // where:{"startTime":"$and":{{ "$gte": "2022-12-04T15:09:47.768Z", "$lt": "2022-12-10T15:09:47.768Z" }}}
            const { data } = await axiosInstance.get(`/sendmails/${new Date(value).getFullYear()}/${month}`);
        } catch (error) {
            console.log(error);
        }
    }
    const generateXLS = async () => {
        try {
            var month = new Date(value).getMonth() + 1;
            // where:{"startTime":"$and":{{ "$gte": "2022-12-04T15:09:47.768Z", "$lt": "2022-12-10T15:09:47.768Z" }}}
            const { data } = await axiosInstance.get(`/generatexcel/${new Date(value).getFullYear()}/${month}/2`);
        } catch (error) {
            console.log(error);
        }
    }
    const generateDOCX = async () => {
        try {
            setActiveButton("generateDOCX");
            var month = new Date(value).getMonth() + 1;
            const response = await axiosInstance.get(`/getDocxFile/${new Date(value).getFullYear()}/${month}`, { responseType: 'blob' });

            const url = window.URL.createObjectURL(new Blob([response.data]));
            const link = document.createElement('a');
            link.href = url;
            link.setAttribute('download', `График 2023.${month}.docx`);
            document.body.appendChild(link);
            link.click();
            link.remove();
        } catch (error) {
            console.log(error);
        }
    }
    //get all publishers and create txt file with their names, current and previous month assignments count (getPublisherInfo)
    //
    const generateMonthlyStatistics = async () => {
        try {
            var month = new Date(value).getMonth() + 1;
            let { data: allPublishersInfo } = await axiosInstance.get(`/api/?action=getMonthlyStatistics&date=${common.getISODateOnly(value)}`);
            //order by name and generate the list
            allPublishersInfo = allPublishersInfo.sort((a, b) => {
                if (a.firstName !== b.firstName) {
                    return a.firstName < b.firstName ? -1 : 1;
                } if (a.lastName !== b.lastName) {
                    return a.lastName < b.lastName ? -1 : 1;
                }
                return 0;
            });
            var list = "";
            allPublishersInfo.forEach(pub => {
                // list += `${pub.firstName} ${pub.lastName}\t ${pub.currentMonthAssignments} / ${pub.previousMonthAssignments}\n`;
                list += `${pub.firstName} ${pub.lastName}\t ${pub.currentMonthAssignments}\n`;
            });

            //write to google sheets file


            //download the file
            const url = window.URL.createObjectURL(new Blob([list]));
            const link = document.createElement('a');
            link.href = url;
            link.setAttribute('download', `Статистика 2023.${month}.txt`);
            document.body.appendChild(link);
            link.click();
            link.remove();
        } catch (error) {
            console.log(error);
        }
    }

    const togglePublished = async () => {
        try {
            const publishState = !isPublished; // Toggle the state
            const isPublishedParam = publishState ? 'true' : 'fasle';
            await axiosInstance.get(`/api/?action=updateShifts&isPublished=${isPublishedParam}&date=${common.getISODateOnly(value)}`);
            setIsPublished(publishState); // Update state based on the action

        } catch (error) {
            console.log(error);
        }
    }



    const [isMenuOpen, setIsMenuOpen] = useState(false);
    const [isConfirmModalOpen, setConfirmModalOpen] = useState(false);
    async function copyOldAvailabilities(event: MouseEvent<HTMLButtonElement, MouseEvent>): Promise<void> {
        await axiosInstance.get(`/api/?action=copyOldAvailabilities&date=${common.getISODateOnly(value)}`);
    }

    async function handleCreateNewShift(event: MouseEvent<HTMLButtonElement, MouseEvent>): Promise<void> {
        //get last shift end time
        let lastShift = shifts.sort((a, b) => new Date(b.endTime).getTime() - new Date(a.endTime).getTime())[0];
        //default to 9:00 if no shifts
        if (!lastShift) {
            //get cart event id
            var dayName = common.DaysOfWeekArray[value.getDayEuropean()];
            const cartEvent = events.find(event => event.dayofweek == dayName);
            lastShift = {
                endTime: DateTime.fromJSDate(value).setZone('Europe/Sofia', { keepLocalTime: true }).set({ hour: 9 }).toJSDate(),
                cartEventId: cartEvent.id
            };
        }
        const lastShiftEndTime = new Date(lastShift.endTime);
        //add 90 minutes
        const newShiftEndTime = new Date(lastShiftEndTime.getTime() + 90 * 60000);
        await axiosInstance.post(`/api/data/shifts`, {
            name: "Нова смяна",
            startTime: lastShiftEndTime,
            endTime: newShiftEndTime,
            isPublished: false,
            cartEvent: { connect: { id: lastShift.cartEventId } }
        }).then((response) => {
            console.log("New shift created:", response.data);
            // setShifts([...shifts, response.data]);
            handleCalDateChange(value);
        }
        ).catch((error) => {
            console.error("Error creating new shift:", error);
        });
    }

    return (
        <>
            <Layout>
                <ProtectedRoute allowedRoles={[UserRole.ADMIN, UserRole.POWERUSER]}>
                    {/* Page Overlay */}
                    {isOperationInProgress && (
                        <div className="loading-overlay">
                            <div className="spinner"></div>
                        </div>
                    )}
                    <input id="fileInput" title="file input" type="file" onChange={handleFileUpload}
                        accept=".json, .doc, .docx, .xls, .xlsx" style={{ display: 'none' }}
                    />

                    <div className="mb-4">

                        <button className="button m-2 bg-blue-800" onClick={importShifts}>
                            {isLoading('importShifts') ? (<i className="fas fa-sync-alt fa-spin mr-2"></i>) : (<i className="fa fa-file-import"></i>)}  Импорт от Word
                        </button>
                        <button className="button btn m-2 bg-blue-800" onClick={generateDOCX}>
                            {isLoading('generateDOCX') ? (<i className="fas fa-sync-alt fa-spin mr-2"></i>) : (<i className="fa fa-file-export"></i>)}Експорт в Word
                        </button>
                        <button className="button btn m-2 bg-yellow-500 hover:bg-yellow-600 text-white" onClick={() => { setActiveButton("sendEmails"); setConfirmModalOpen(true) }}>
                            {isLoading('sendEmails') ? (<i className="fas fa-sync-alt fa-spin mr-2"></i>) : (<i className="fas fa-envelope mr-2"></i>)} изпрати мейли!
                        </button>
                        <ConfirmationModal
                            isOpen={isConfirmModalOpen}
                            onClose={() => setConfirmModalOpen(false)}
                            onConfirm={() => {
                                toast.info("Потвърдено!", { autoClose: 2000 });
                                setConfirmModalOpen(false);
                                sendMails()
                            }}
                            message="Това ще изпрати имейли до всички участници за смените им през избрания месец. Сигурни ли сте?"
                        />
                        <button
                            className={`button btn m-2 ${isPublished ? 'hover:bg-gray-500 bg-yellow-500' : 'hover:bg-red-300 bg-blue-400'}`}
                            onClick={togglePublished}>
                            <i className={`fas ${isPublished ? 'fa-check' : 'fa-close'} mr-2`}></i>
                            {isPublished ? "Скрий" : "Публикувай"} графика (м.)
                        </button>
                        <div className="relative inline-block text-left">
                            <button
                                className={`button m-2 ${isMenuOpen ? 'bg-gray-400 border border-blue-500' : 'bg-gray-300'} hover:bg-gray-400`}
                                onClick={() => { setIsMenuOpen(!isMenuOpen) }}>
                                <i className="fa fa-ellipsis-h"></i> Още
                            </button>
                            {isMenuOpen && (
                                <div className="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5">
                                    <div className="py-1" role="menu" aria-orientation="vertical" aria-labelledby="options-menu">
                                        {/* Group 1: Daily actions */}
                                        <button className="block w-full px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 flex items-center" onClick={() => generateShifts("genEmptyDay", false, false, true)}>
                                            {isLoading('genEmptyDay') ? (<i className="fas fa-sync-alt fa-spin mr-2"></i>) : (<i className="fas fa-plus mr-2"></i>)}
                                            създай празни ({value.getDate()}-ти) </button>
                                        <button className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" onClick={() => generateShifts("genDay", false, true, true)}>
                                            {isLoading('genDay') ? (<i className="fas fa-sync-alt fa-spin mr-2"></i>) : (<i className="fas fa-cogs mr-2"></i>)}
                                            Генерирай смени ({value.getDate()}-ти)                                        </button>
                                        <button className="block px-4 py-2 text-sm text-red-500 hover:bg-gray-100" onClick={() => { deleteShifts("deleteShiftsDay", true) }}>
                                            {isLoading('deleteShiftsDay') ? (<i className="fas fa-sync-alt fa-spin mr-2"></i>) : (<i className="fas fa-trash-alt mr-2"></i>)}
                                            изтрий смените ({value.getDate()}-ти)</button>

                                        <hr className="my-1" />
                                        <button className="block w-full px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 flex items-center" onClick={() => generateShifts("genEmpty", false, false)}>
                                            {isLoading('genEmpty') ? (<i className="fas fa-sync-alt fa-spin mr-2"></i>) : (<i className="fas fa-plus mr-2"></i>)}
                                            създай празни </button>
                                        <button className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 whitespace-nowrap" onClick={() => generateShifts("genCopy", true)}>
                                            {isLoading('genCopy') ? (<i className="fas fa-sync-alt fa-spin mr-2"></i>) : (<i className="fas fa-copy mr-2"></i>)}
                                            копирай от миналия месец</button>
                                        <button className="block w-full px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 flex items-center" onClick={() => generateShifts("genDay", true, true)}>
                                            {isLoading('genDay') ? (<i className="fas fa-sync-alt fa-spin mr-2"></i>) : (<i className="fas fa-cogs mr-2"></i>)}
                                            Генерирай смени </button>
                                        <button className="block px-4 py-2 text-sm text-red-500 hover:bg-gray-100" onClick={() => { deleteShifts("deleteShifts", false) }}>
                                            {isLoading('deleteShifts') ? (<i className="fas fa-sync-alt fa-spin mr-2"></i>) : (<i className="fas fa-trash-alt mr-2"></i>)}
                                            изтрий смените</button>


                                        <hr className="my-1" />

                                        <button className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" onClick={generateXLS}><i className="fas fa-file-excel mr-2"></i> Генерирай XLSX</button>
                                        <button className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" onClick={fetchShifts}>
                                            {isLoading('fetchShifts') ? (<i className="fas fa-sync-alt fa-spin mr-2"></i>) : (<i className="fas fa-sync-alt mr-2"></i>)} презареди</button>
                                        <button className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" onClick={generateMonthlyStatistics}><i className="fas fa-chart-bar mr-2"></i> Генерирай статистика</button>
                                        <button className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" onClick={copyOldAvailabilities}><i className="fas fa-copy mr-2"></i> Прехвърли предпочитанията</button>
                                    </div>
                                </div>
                            )}
                        </div>
                    </div>
                    {/* progress bar holder */}
                    {isOperationInProgress && (
                        <div id="progress" className="w-full h-2 bg-gray-300">
                            <div id="progress-bar" className="h-full bg-green-500" style={{ width: `${progress}%` }}></div>
                        </div>
                    )}
                    <div className="flex">
                        {/* Calendar section */}
                        <div className="flex-3">
                            <Calendar
                                className={['customCalendar']}
                                onChange={handleCalDateChange}
                                value={value}
                                tileContent={onTileContent}
                                locale="bg-BG"
                            />
                            {/* ------------------------------- PUBLISHERS LIST ----------------------------------

                                      list of publishers for the selected date with availabilities 
                            
                            ------------------AVAILABLE PUBLISHERS LIST FOR THE SELECTED DATE0 ------------------ */}
                            <div className="flex flex-col items-center my-4 sticky top-0">

                                <h2 className="text-lg font-semibold mb-4">Достъпни за този ден: <span className="text-blue-600">{availablePubs.length}</span></h2>
                                <label className="toggle pb-3">
                                    <input type="checkbox" className="toggle-checkbox" id="filterShowWithoutAssignments" onChange={handleCheckboxChange} />
                                    <span className="toggle-slider m-1">без назначения за месеца</span>
                                    <input type="checkbox" className="toggle-checkbox" id="filterIncludeOldAvailabilities" onChange={handleCheckboxChange} />
                                    <span className="toggle-slider m-1">със стари предпочитания</span>
                                </label>
                                <ul className="w-full max-w-md">
                                    {Array.isArray(availablePubs) && availablePubs?.map((pub, index) => {
                                        // Determine background and border classes based on conditions
                                        let bgAndBorderColorClass;
                                        if (pub.isAvailableForShift) {
                                            if (pub.currentDayAssignments === 0) {
                                                const comparisonResultClass = pub.currentMonthAvailabilityDaysCount < pub.previousMonthAssignments ? 'bg-green-100' : 'bg-green-50';
                                                bgAndBorderColorClass = `${comparisonResultClass} border-l-4 border-green-400`;
                                            } else if (!pub.isSelected) {
                                                bgAndBorderColorClass = 'bg-orange-50 border-l-4 border-orange-400';
                                            }
                                        } else {
                                            if (pub.isAvailableForShiftWithPrevious) // add left orange border
                                            {
                                                bgAndBorderColorClass = 'border-l-4 border-orange-400';
                                            }
                                            else {
                                                bgAndBorderColorClass = 'bg-white';
                                            }
                                        }
                                        //tOdO: CHECK WHY THIS IS NOT WORKING
                                        if (!pub.hasEverFilledForm) {
                                            //bgAndBorderColorClass = 'border-t-2 border-yellow-400';
                                        }

                                        // Determine border class if selected
                                        const selectedBorderClass = pub.isSelected ? 'border-blue-400 border-b-4' : '';
                                        // Determine opacity class
                                        const activeOpacityClass = pub.isActive ? '' : 'opacity-25';


                                        return (
                                            <li key={index}
                                                className={`flex justify-between items-center p-4 sm:py-2 rounded-lg shadow-sm mb-2 
                                                ${bgAndBorderColorClass} ${selectedBorderClass} ${activeOpacityClass}`}
                                                onDoubleClick={(handlePublisherModalOpen.bind(this, pub))}
                                            >
                                                <span className={`text-gray-700 ${pub.isAvailableForShift ? 'font-bold' : 'font-medium'} `}>
                                                    {pub.firstName} {pub.lastName}
                                                    {pub.canTransport && (<LocalShippingIcon className="mx-2 text-gray-500" />)}
                                                </span>
                                                <div className="flex space-x-1 overflow-hidden">
                                                    <span title="Възможност: часове | дни" className={`badge py-1 px-2 rounded-md text-xs ${pub.currentMonthAvailabilityHoursCount || pub.currentMonthAvailabilityDaysCount ? 'bg-teal-500 text-white' : 'bg-teal-200 text-gray-300'} hover:underline`} >
                                                        {pub.currentMonthAvailabilityDaysCount || 0} | {pub.currentMonthAvailabilityHoursCount || 0}
                                                    </span>
                                                    <span title="участия тази седмица" className={`badge py-1 px-2 rounded-full text-xs ${pub.currentWeekAssignments ? 'bg-yellow-500 text-white' : 'bg-yellow-200 text-gray-400'}`}>{pub.currentWeekAssignments || 0}</span>
                                                    <span title="участия този месец" className={`badge py-1 px-2 rounded-full text-xs ${pub.currentMonthAssignments ? 'bg-green-500 text-white' : 'bg-green-200 text-gray-400'}`}>{pub.currentMonthAssignments || 0}</span>
                                                    <span tooltip="участия миналия месец" title="участия миналия месец" className={`badge py-1 px-2 rounded-full text-xs ${pub.previousMonthAssignments ? 'bg-blue-500 text-white' : 'bg-blue-200 text-gray-400'}`}>{pub.previousMonthAssignments || 0}</span>
                                                    <button tooltip="желани участия този месец" title="желани участия" className={`badge py-1 px-2 rounded-md text-xs ${pub.desiredShiftsPerMonth ? 'bg-purple-500 text-white' : 'bg-purple-200 text-gray-400'}`}>{pub.desiredShiftsPerMonth || 0}</button>
                                                </div>
                                            </li>
                                        );

                                    })}
                                </ul>
                            </div>
                        </div>

                        {/* Shift list section */}
                        <div className="flex-grow mx-5">
                            <div className="flex-col" id="shiftlist">
                                {shifts.map((shift, index) => (
                                    <ShiftComponent key={index} shift={shift}
                                        onShiftSelect={handleShiftSelection} isSelected={shift.id == selectedShiftId}
                                        onPublisherSelect={handleSelectedPublisher} showAllAuto={true}
                                        allPublishersInfo={availablePubs} />
                                ))}
                            </div>
                            <button
                                className="mt-4 bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
                                onClick={handleCreateNewShift}
                            >
                                Добави нова смяна
                            </button>
                        </div>
                    </div>

                    <div>
                        {/* <CustomCalendar date={value} shifts={shifts} /> */}
                    </div>
                    {isModalOpen && <PublisherShiftsModal publisher={modalPub} shifts={allShifts} onClose={() => setIsModalOpen(false)} />}
                </ProtectedRoute >
            </Layout >
        </>
    );

    function PublisherShiftsModal({ publisher, shifts, onClose }) {
        const monthInfo = common.getMonthDatesInfo(new Date(value));
        const monthShifts = shifts.filter(shift => {
            const shiftDate = new Date(shift.startTime);
            return shiftDate > monthInfo.firstDay && shiftDate < monthInfo.lastDay;
        });
        const weekShifts = monthShifts.filter(shift => {
            const shiftDate = new Date(shift.startTime);
            return common.getStartOfWeek(value) <= shiftDate && shiftDate <= common.getEndOfWeek(value);
        });
        const dayShifts = weekShifts.map(shift => {
            const isAvailable = publisher.availabilities.some(avail =>
                avail.startTime <= shift.startTime && avail.endTime >= shift.endTime
            );
            let color = isAvailable ? getColorForShift(shift) : 'bg-gray-300';
            if (shift.isFromPreviousMonth) {
                color += ' border-l-4 border-orange-500 ';
            }
            if (shift.isFromPreviousAssignment) {
                color += ' border-l-4 border-red-500 ';
            }
            return { ...shift, isAvailable, color };
        }).reduce((acc, shift) => {
            const dayIndex = new Date(shift.startTime).getDay();
            acc[dayIndex] = acc[dayIndex] || [];
            acc[dayIndex].push(shift);
            return acc;
        }, {});
        console.log("dayShifts:", dayShifts);

        const hasAssignment = (shiftId) => {
            // return publisher.assignments.some(ass => ass.shift.id == shiftId);
            return publisher.assignments.some(ass => {
                console.log(`Comparing: ${ass.shift.id} to ${shiftId}: ${ass.shift.id === shiftId}`);
                return ass.shift.id === shiftId;
            });
        };


        useEffect(() => {
            const handleKeyDown = (event) => {
                if (event.key === 'Escape') {
                    console.log('ESC: closing modal.');
                    onClose(); // Call the onClose function when ESC key is pressed
                }
            };

            // Add event listener
            window.addEventListener('keydown', handleKeyDown);

            // Remove event listener on cleanup
            return () => {
                window.removeEventListener('keydown', handleKeyDown);
            };
        }, [onClose]); // Include onClose in the dependency array

        return (
            <div className="fixed top-0 left-0 w-full h-full flex items-center justify-center bg-black bg-opacity-50 z-50">
                <div className="relative bg-white p-8 rounded-lg shadow-xl max-w-xl w-full h-auto overflow-y-auto">
                    <h2 className="text-xl font-semibold mb-4">График на <span title={publisher.email} className='publisher'>
                        <strong>{publisher.firstName} {publisher.lastName}</strong>
                        <span className="publisher-tooltip" onClick={common.copyToClipboard}>{publisher.email}</span>
                    </span> тази седмица:</h2>

                    {/* ... Display shifts in a calendar-like UI ... */}
                    <div className="grid grid-cols-6 gap-4 mb-4">
                        {Object.entries(dayShifts).map(([dayIndex, shiftsForDay]) => (
                            <div key={dayIndex} className="flex flex-col space-y-2 justify-end">
                                {/* Day header */}
                                <div className="text-center font-medium">{new Date(shiftsForDay[0].startTime).getDate()}-ти</div>

                                {shiftsForDay.map((shift, index) => {
                                    const assignmentExists = hasAssignment(shift.id);
                                    const availability = publisher.availabilities.find(avail =>
                                        avail.startTime <= shift.startTime && avail.endTime >= shift.endTime
                                    );
                                    const isFromPrevMonth = availability && availability.isFromPreviousMonth;
                                    return (
                                        <div
                                            key={index}
                                            className={`text-sm text-white p-2 rounded-md  ${isFromPrevMonth ? 'border-l-6 border-black-500' : ''} ${assignmentExists ? 'bg-blue-200' : shift.color} h-24 flex flex-col justify-center`}
                                        >
                                            {common.getTimeRange(shift.startTime, shift.endTime)} {shift.id}

                                            {!assignmentExists && shift.isAvailable && (
                                                <button onClick={() => { addAssignment(publisher, shift.id); onClose() }}
                                                    className="mt-2 bg-green-500 text-white p-1 rounded hover:bg-green-600 active:bg-green-700 focus:outline-none"
                                                >
                                                    добави
                                                </button>
                                            )}
                                            {assignmentExists && (
                                                <button onClick={() => { removeAssignment(publisher, shift.id) }} // Implement the removeAssignment function
                                                    className="mt-2 bg-red-500 text-white p-1 rounded hover:bg-red-600 active:bg-red-700 focus:outline-none"
                                                >
                                                    махни
                                                </button>
                                            )}
                                        </div>
                                    );
                                }
                                )}
                            </div>
                        ))}
                    </div>

                    {/* Close button in the top right corner */}
                    <button
                        onClick={onClose}
                        className="absolute top-3 right-2 p-2 px-3 bg-red-500 text-white rounded-full hover:bg-red-600 active:bg-red-700 focus:outline-none"
                    >
                        &times;
                    </button>

                    {/* <Link href={`/cart/publishers/edit/${modalPub.id}`}
                        className="mt-2 bg-blue-500 text-white p-1 rounded hover:bg-blue-600 active:bg-blue-700 focus:outline-none">
                        <i className="fas fa-edit" />
                    </Link> */}
                    {/* Edit button in the top right corner, next to the close button */}
                    <Link href={`/cart/publishers/edit/${modalPub.id}`} className="absolute top-3 right-12 p-2 bg-blue-500 text-white rounded-full hover:bg-blue-600 active:bg-blue-700 focus:outline-none">
                        <i className="fas fa-edit" />
                    </Link>

                </div>
            </div >
        );
    }

    function getColorForShift(shift) {
        const assignedCount = shift.assignedCount || 0; // Assuming each shift has an assignedCount property
        switch (assignedCount) {
            case 0: return 'bg-blue-300';
            case 1: return 'bg-green-300';
            case 2: return 'bg-yellow-300';
            case 3: return 'bg-orange-300';
            case 4: return 'bg-red-200';
            default: return 'bg-gray-300';
        }
    }
}

import axiosServer from '../../../src/axiosServer';
import { start } from 'repl';
import { filter } from 'jszip';
export const getServerSideProps = async (context) => {
    const axios = await axiosServer(context);
    // const baseUrl = common.getBaseUrl();
    // console.log('runtime BaseUrl: ' + baseUrl);
    console.log('runtime NEXT_PUBLIC_PUBLIC_URL: ' + process.env.NEXT_PUBLIC_PUBLIC_URL);
    console.log('Runtime Axios Base URL:', axios.defaults.baseURL);

    const currentDate = new Date();
    const firstDayOfMonth = new Date(currentDate.getFullYear(), currentDate.getMonth() - 3, 1);
    const lastDayOfMonth = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 0); // 0th day of the next month gives the last day of the current month

    const url = `/api/data/shifts?where={"startTime":{"$and":[{"$gte":"${common.getISODateOnly(firstDayOfMonth)}","$lt":"${common.getISODateOnly(lastDayOfMonth)}"}]}}`;

    const prismaClient = common.getPrismaClient();
    const { data: events } = await axios.get(`/api/data/cartevents?where={"isActive":true}`);
    //const { data: shifts } = await axios.get(url);

    // get all shifts for the month, including assigments
    let shifts = await prismaClient.shift.findMany({
        where: {
            isActive: true,
            startTime: {
                gte: firstDayOfMonth,
                //lt: lastDayOfMonth
            }
        },
        include: {
            assignments: {
                include: {
                    publisher: {
                        select: {
                            id: true,
                        }
                    }
                }
            }
        }
    });

    //calculate assCount for each shift
    shifts = shifts.map(shift => ({
        ...shift,
        assignedCount: shift.assignments.length,
        startTime: shift.startTime.toISOString(),
        endTime: shift.endTime.toISOString(),
    }));


    return {
        props: {
            initialEvents: events,
            initialShifts: shifts,
        },
    };

}