<script>
    function formatOperators(operators, maxVisible) {
        let visible = operators;
        let hidden = [];
        if (operators.length <= maxVisible) {
            return `<div class="operators-main-display">
                ${operators.map(op => `<span class="operator-badge">${op}</span>`).join('')}
            </div>`;
        }
        if (maxVisible > 0) {
            visible = operators.slice(0, maxVisible);
            hidden = operators.slice(maxVisible);
        }
        return `
            <div class="operators-main-display">
                ${visible.map(op => `<span class="operator-badge">${op}</span>`).join('')}
                ${hidden.length > 0 ? `
                        <button class="more-operators-btn">+${hidden.length} more</button>
                        <div class="operators-dropdown">
                            ${hidden.map(op => `<span class="operator-badge">${op}</span>`).join('')}
                        </div>
                    `: ''}
            </div>
            `;
    }

    function dotwalk(obj, path) {
        if (!path) return null;
        return path.split('.').reduce((o, p) => (o || {})[p], obj);
    }

    function getFormData(form, callback = () => {}) {
        return [...(new FormData(form)).entries()].reduce((col, [key, value]) => {
            let retValue = {
                ...col,
                [key]: value
            };
            let callReturn = callback(key, value, retValue);
            return callReturn ? callReturn : retValue;
        }, {});
    }

    function formatDate(dateObj, format) {
        const pad = (n) => n.toString().padStart(2, '0');
        const tokens = {
            dd: pad(dateObj.getDate()),
            d: dateObj.getDate(),
            mm: pad(dateObj.getMonth() + 1),
            m: dateObj.getMonth() + 1,
            yyyy: dateObj.getFullYear(),
            yy: dateObj.getFullYear().toString().slice(-2),
            hh: pad(dateObj.getHours()),
            h: dateObj.getHours(),
            ii: pad(dateObj.getMinutes()),
            i: dateObj.getMinutes(),
            ss: pad(dateObj.getSeconds()),
            s: dateObj.getSeconds(),
        };
        return format.replace(/dd|d|mm|m|yyyy|yy|hh|h|ii|i|ss|s/g, match => tokens[match]);
    }

    function time2Date(time, baseDate = '1970-01-01') {
        return new Date(`${baseDate}T${time}`)
    }

    function setTime(date, time) {
        let [hours, minutes] = time.split(":").map(Number);
        let newdate = new Date(date);
        newdate.setHours(hours, minutes, 0, 0);
        return newdate;
    }

    function addTime(base, timeToAdd) {
        let [addHours, addMinutes] = timeToAdd.split(":").map(Number);
        const newDate = new Date(base);
        newDate.setMinutes(newDate.getMinutes() + addHours * 60 + addMinutes);
        return newDate;
    }

    function getHourDifference(startTime, endTime) {
        const baseDate = '1970-01-01';
        let start = new Date(`${baseDate}T${startTime}:00`);
        let end = new Date(`${baseDate}T${endTime}:00`);

        if (end < start) {
            end.setDate(end.getDate() + 1); // Move to next day
        }

        const diffMs = end - start;
        return diffMs / (1000 * 60 * 60);
    }

    function calculateExpectedEnd({
        shiftStartTime, // e.g., '08:00'
        shiftEndTime, // e.g., '20:00'
        cycleHours, // e.g., 1
        cycleMinutes, // e.g., 0
        expectedStartDate // e.g., '2025-07-09'
    }) {
        if (expectedStartDate.includes("T")) {
            expectedStartDate = expectedStartDate.split("T")[0];
        }
        const workHoursPerDay = getHourDifference(shiftStartTime, shiftEndTime);
        const workMinutesPerDay = workHoursPerDay * 60;
        const totalCycleMinutes = (cycleHours * 60) + cycleMinutes;
        const fullDays = Math.floor(totalCycleMinutes / workMinutesPerDay);
        const remainingMinutes = totalCycleMinutes % workMinutesPerDay;
        const startDateTime = new Date(`${expectedStartDate}T${shiftStartTime}:00`);
        const endDateTime = new Date(startDateTime);
        endDateTime.setDate(endDateTime.getDate() + fullDays);
        endDateTime.setMinutes(endDateTime.getMinutes() + remainingMinutes);
        return endDateTime;
    }

    function confirmAction({
        title = "Do you want to save the changes?",
        confirmText = "Save",
        denyText = "Don't save"
    } = {}) {
        return new Promise((res, rej) => {
            Swal.fire({
                title: title,
                showDenyButton: true,
                showCancelButton: false,
                confirmButtonText: confirmText,
                denyButtonText: denyText
            }).then((result) => {
                if (result.isConfirmed) {
                    return res();
                } else if (result.isDenied) {
                    return rej(false);
                } else {
                    return rej(null); // user cancelled
                }
            })
        });
    }

    function showSuccess(message) {
        Swal.fire({
            title: 'Success',
            text: message,
            icon: 'success'
        });
    }

    function updateDateTime() {
        const date = new Date();
        // Arrays for day and month names
        const days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
        const months = [
            "January", "February", "March", "April", "May", "June",
            "July", "August", "September", "October", "November", "December"
        ];
        
        // Helper to safe update
        const safeSetText = (id, text) => {
            const el = document.getElementById(id);
            if (el) el.textContent = text;
        };

        // Date
        safeSetText("day", days[date.getDay()]);
        safeSetText("daynum", String(date.getDate()).padStart(2, '0'));
        safeSetText("month", months[date.getMonth()]);
        safeSetText("year", date.getFullYear());
        
        // Time
        const hours = String(date.getHours()).padStart(2, '0');
        const minutes = String(date.getMinutes()).padStart(2, '0');
        const seconds = String(date.getSeconds()).padStart(2, '0');
        
        const timeEl = document.querySelector(".display-time");
        if (timeEl) timeEl.textContent = `${hours}:${minutes}:${seconds}`;
    }

    function numberToWords(num) {
        const ones = ["", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"];
        const teens = ["", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen",
            "Nineteen"
        ];
        const tens = ["", "Ten", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"];
        const higherUnits = ["", "Thousand", "Lakh", "Crore"];

        if (isNaN(num) || num === 0) return 'Zero';

        let word = '';

        function processHundred(number) {
            let result = '';
            if (number > 99) {
                result += ones[Math.floor(number / 100)] + ' Hundred ';
                number %= 100;
            }
            if (number > 10 && number < 20) {
                result += teens[number - 10] + ' ';
            } else {
                result += tens[Math.floor(number / 10)] + ' ';
                result += ones[number % 10] + ' ';
            }
            return result.trim();
        }

        // Process the number in pairs for Indian format (thousands, lakhs, crores)
        const crorePart = Math.floor(num / 10000000);
        const lakhPart = Math.floor((num % 10000000) / 100000);
        const thousandPart = Math.floor((num % 100000) / 1000);
        const hundredPart = num % 1000;

        if (crorePart > 0) {
            word += processHundred(crorePart) + ' Crore ';
        }
        if (lakhPart > 0) {
            word += processHundred(lakhPart) + ' Lakh ';
        }
        if (thousandPart > 0) {
            word += processHundred(thousandPart) + ' Thousand ';
        }
        if (hundredPart > 0) {
            word += processHundred(hundredPart) + ' Only';
        }

        return word.trim();
    }

    function resetInitials() {
        $('.item-select').each(function() {
            if ($(this).hasClass("select2-hidden-accessible")) {
                $(this).find("+ .select2-container").remove();
            }
        });
        // Re-initialize all
        $('.item-select').select2({
            allowClear: true
        });
    }
</script>
