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 PublisherShiftsModal from '../../../components/publisher/PublisherShiftsModal';
//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';
// import notify api
import { sendPush, broadcastPush } from '../../api/notify';
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 [selectedMonth, setSelectedMonth] = useState(new Date().getMonth());
    const [shifts, setShifts] = React.useState([]);
    const [error, setError] = React.useState(null);
    const [availablePubs, setAvailablePubs] = React.useState([]);
    const [selectedPublisher, setSelectedPublisher] = React.useState(null);

    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
    };
    const [repeatEnabled, setRepeatEnabled] = useState(true);

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

    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) => {
        console.log("handle pub clicked:", publisher);
        setSelectedPublisher(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>;
    };
    //ToDo: DRY - move to common
    const addAssignment = async (publisher, shiftId) => {
        try {
            console.log(`calendar.idx: new assignment for publisher ${publisher.id} - ${publisher.firstName} ${publisher.lastName}`);
            const newAssignment = {
                publisher: { connect: { id: publisher.id } },
                shift: { connect: { id: shiftId } },
                isConfirmed: true
            };
            const { data } = await axiosInstance.post("/api/data/assignments", newAssignment);
            if (selectedShiftId == shiftId) {
                handleShiftSelection(shifts.find(shift => shift.id === shiftId));
            }

            // Update the 'publisher' property of the returned data with the full publisher object
            data.publisher = publisher;
            data.shift = shifts.find(shift => shift.id === shiftId);
            publisher.assignments = [...publisher.assignments, data];
            handleAssignmentChange(publisher.id, 'add');
        } 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(`calendar.idx: remove assignment for shift ${shiftId}`);
            const { data } = await axiosInstance.delete(`/api/data/assignments/${assignment.id}`);
            //remove from local assignments:
            publisher.assignments = publisher.assignments.filter(a => a.id !== assignment.id)
            //
            handleAssignmentChange(publisher.id, 'remove')
        } catch (error) {
            console.error("Error removing assignment:", error);
        }
    }
    function handleAssignmentChange(id, type) {
        // Handle assignment change logic here
        let pub = availablePubs.find(pub => pub.id === id)
        pub.currentMonthAssignments += type === 'add' ? 1 : -1;
        pub.currentWeekAssignments += type === 'add' ? 1 : -1;
        //store in state
        setAvailablePubs([...availablePubs]);

    }

    // ----------------------------------------------------------
    // 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, type = 0) => {
        try {
            setActiveButton(buttonId);
            const endpoint = `/api/shiftgenerate?action=generate&date=${common.getISODateOnly(value)}&copyFromPreviousMonth=${copyFromPrevious}&autoFill=${autoFill}&forDay=${forDay}&type=${type}&repeat=${repeatEnabled}`;
            const { shifts } = await axiosInstance.get(endpoint);
            toast.success('Готово!', { autoClose: 1000 });
            setIsMenuOpen(false);
        } catch (error) {
            console.log(error);
        } finally {
            setActiveButton(null);
        }
    }
    const deleteShifts = async (forDay: Boolean) => {
        try {
            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 [confirmModalProps, setConfirmModalProps] = useState({
        isOpen: false,
        message: '',
        onConfirm: () => { }
    });
    const openConfirmModal = (message, action, actionName) => {
        if (actionName) {
            setActiveButton(actionName);
        }
        setConfirmModalProps({
            isOpen: true,
            message: message,
            onConfirm: () => {
                toast.info('Потвърдено!', { autoClose: 2000 });
                setConfirmModalProps((prevProps) => ({ ...prevProps, isOpen: false }));
                action();
            },
        });
    };

    //const [isConfirmModalDeletOpen, setConfirmModalDeleteOpen] = 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);
        // Generate shift name using the same format as displayed shifts (start-end time)
        const shiftName = common.getTimeRange(lastShiftEndTime, newShiftEndTime);
        await axiosInstance.post(`/api/data/shifts`, {
            name: shiftName,
            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);
        });
    }

    /*
    
    model Settings {
  id          Int     @id @default(autoincrement())
  key         String
  value       String
  description String?
}
*/
    async function setAvailabilityBlockDate(AvailabilityBlockDate: Date): Promise<void> {
        // set AvailabilityBlockDate to the selected date
        let monthInfo = common.getMonthInfo(value);
        await axiosInstance.put(`/api/?action=settings&key=AvailabilityBlockDate&value=${common.getISODateOnly(value)}`)
            .then((response) => {
                console.log("AvailabilityBlockDate set to:", response.data);
                // setShifts([...shifts, response.data]);
                handleCalDateChange(value);
            }
            ).catch((error) => {
                console.error("Error setting AvailabilityBlockDate:", 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={() => openConfirmModal(
                                'Това ще изпрати имейли до всички участници за смените им през избрания месец. Сигурни ли сте?',
                                () => sendMails(),
                                "sendEmails"
                            )}
                        >
                            {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="Това ще изпрати имейли до всички участници за смените им през избрания месец. Сигурни ли сте?"
                        /> */}
                        <ConfirmationModal
                            isOpen={confirmModalProps.isOpen}
                            onClose={() => setConfirmModalProps((prevProps) => ({ ...prevProps, isOpen: false }))}
                            onConfirm={confirmModalProps.onConfirm}
                            message={confirmModalProps.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, 1)}>
                                            {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={() => openConfirmModal(
                                                'Сигурни ли сте че искате да изтриете смените и назначения на този ден?',
                                                () => deleteShifts(true),
                                                "deleteShiftsDay"
                                            )}
                                        >
                                            {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, null, 0)}>
                                            {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 w-full px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 flex items-center justify-between"
                                            onClick={() => generateShifts("genDay", true, true, null, 1)}>
                                            <div className="flex items-center">
                                                {isLoading('genDay') ? (<i className="fas fa-sync-alt fa-spin mr-2"></i>) : (<i className="fas fa-cogs mr-2"></i>)}
                                                Генерирай<span className="text-yellow-500 ml-1 text-xs">✨</span>
                                            </div>
                                            <div className="flex items-center" onClick={(e) => e.stopPropagation()}>
                                                <input
                                                    type="checkbox"
                                                    checked={repeatEnabled}
                                                    onChange={(e) => setRepeatEnabled(e.target.checked)}
                                                    className="mr-2 form-checkbox h-4 w-4 text-blue-600 transition duration-150 ease-in-out"
                                                />
                                                <span className="text-sm text-gray-600">повт.</span>
                                            </div>
                                        </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, null, 2)}>
                                            {isLoading('genDay') ? (<i className="fas fa-sync-alt fa-spin mr-2"></i>) : (<i className="fas fa-cogs mr-2"></i>)}
                                            Генерирай смени 3 </button> */}

                                        <button className="block px-4 py-2 text-sm text-red-500 hover:bg-gray-100"
                                            onClick={() => openConfirmModal(
                                                'Сигурни ли сте че искате да изтриете ВСИЧКИ смени и назначения за месеца?',
                                                () => deleteShifts(false),
                                                "deleteShifts"
                                            )}
                                        >
                                            {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> */}
                                        <button className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" onClick={setAvailabilityBlockDate}><i className="fas fa-copy mr-2"></i> Блокирай предпочитанията до {value.getDate()}-ти</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" id="availablePubsList" name="availablePubsList">
                                    {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}
                                                ${pub.currentMonthAssignments === pub.desiredShiftsPerMonth ? 'text-gray-400' : pub.currentMonthAssignments > pub.desiredShiftsPerMonth ? 'text-orange-300' : 'text-gray-800'}`}
                                                onDoubleClick={() => handlePublisherModalOpen(pub)}
                                            >
                                                <span className={`${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>
                                                    <button tooltip="push" title="push" className={`badge py-1 px-2 rounded-md text-xs bg-red-100`}
                                                        onClick={async () => {
                                                            handleSelectedPublisher(pub);
                                                            addAssignment(pub, selectedShiftId);
                                                        }}
                                                    >+</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}
                                        onAssignmentChange={handleAssignmentChange}
                                        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)}
                            date={value}
                            onAssignmentChange={handleAssignmentChange}
                        />
                    )}
                </ProtectedRoute >
            </Layout >
        </>
    );



}

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,
        },
    };

}