AtoZ OnCall Allowance Sheet Generator & Work Statistics

Combined tool for OnCall allowance management and work statistics from AtoZ

// ==UserScript==
// @name         AtoZ OnCall Allowance Sheet Generator & Work Statistics
// @namespace    http://tampermonkey.net/
// @version      2.6
// @description  Combined tool for OnCall allowance management and work statistics from AtoZ
// @author       wmehedis
// @match        https://atoz.amazon.work/time/balance-ledger/TimeOff_ATPLUS_DE_CF_PaidAbsenceFlexDismantlingHour
// @grant        GM_xmlhttpRequest
// @connect      oncall-api.corp.amazon.com
// @connect      atoz-apps.amazon.work
// ==/UserScript==


(function () {
'use strict';

const styles = `
    @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');

    .punch-column-header {
        font-weight: 600;
        text-align: center;
        padding: 12px;
        font-family: 'Inter', sans-serif;
    }

    .combined-panel {
        position: fixed !important;
        right: 0 !important;
        top: 63px !important;
        z-index: 9999 !important;
        height: 100vh;
        width: 320px;
        background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
        backdrop-filter: blur(10px);
        box-shadow: -10px 0 30px rgba(0,0,0,0.15);
        border-left: 1px solid rgba(255,255,255,0.2);
        display: flex;
        flex-direction: column;
        overflow: hidden;
        font-family: 'Inter', sans-serif;
    }

    .punch-cell {
        font-size: 12px;
        text-align: center;
        padding: 8px;
        font-family: 'Inter', sans-serif;
        margin: 2px;
    }

    .punch-card {
        display: inline-block;
        background: rgba(255,255,255,0.9);
        border: 1px solid rgba(255,255,255,0.3);
        border-radius: 12px;
        padding: 6px 12px;
        margin: 2px;
        box-shadow: 0 4px 15px rgba(0,0,0,0.1);
        backdrop-filter: blur(5px);
        transition: all 0.3s ease;
    }

    .punch-card:hover {
        transform: translateY(-2px);
        box-shadow: 0 8px 25px rgba(0,0,0,0.15);
    }

    .punch-out {
        color: #e74c3c;
        font-weight: 600;
    }

    .punch-in {
        color: #27ae60;
        font-weight: 600;
    }

    .panel-content {
        flex: 1;
        overflow-y: auto;
        padding: 18px;
        scrollbar-width: thin;
        scrollbar-color: rgba(0,0,0,0.2) transparent;
    }

    .panel-content::-webkit-scrollbar {
        width: 6px;
    }

    .panel-content::-webkit-scrollbar-track {
        background: transparent;
    }

    .panel-content::-webkit-scrollbar-thumb {
        background: rgba(0,0,0,0.2);
        border-radius: 3px;
    }

    .section {
        background: rgba(255,255,255,0.8);
        border-radius: 16px;
        padding: 12px;
        margin-bottom: 12px;
        box-shadow: 0 8px 32px rgba(0,0,0,0.1);
        backdrop-filter: blur(10px);
        border: 1px solid rgba(255,255,255,0.2);
        transition: all 0.3s ease;
    }

    .section:hover {
        transform: translateY(-2px);
        box-shadow: 0 12px 40px rgba(0,0,0,0.15);
    }

    .oncall-input {
        width: calc(50% - 8px) !important;
        margin: 8px 4px;
        padding: 12px;
        border: 2px solid rgba(255,255,255,0.3);
        border-radius: 12px;
        background: rgba(255,255,255,0.9);
        font-family: 'Inter', sans-serif;
        font-size: 14px;
        transition: all 0.3s ease;
    }

    .oncall-input:focus {
        outline: none;
        border-color: #667eea;
        box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
        transform: translateY(-1px);
    }

    .action-button {
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        color: white;
        border: none;
        padding: 14px 20px;
        border-radius: 12px;
        cursor: pointer;
        margin-top: 12px;
        width: 100%;
        font-family: 'Inter', sans-serif;
        font-weight: 600;
        font-size: 14px;
        transition: all 0.3s ease;
        box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
    }

    .action-button:hover {
        transform: translateY(-2px);
        box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
        background: linear-gradient(135deg, #5a67d8 0%, #6b46c1 100%);
    }

    .action-button:active {
        transform: translateY(0);
    }

    .date-range {
        background: rgba(255,255,255,0.6);
        padding: 16px;
        border-radius: 12px;
        margin-bottom: 12px;
        border: 1px solid rgba(255,255,255,0.3);
        backdrop-filter: blur(5px);
    }

    .shift-type-container {
        margin-bottom: 12px;
        font-size: 13px;
    }

    .shift-type-container label {
        display: inline-flex;
        align-items: center;
        cursor: pointer;
        padding: 8px 12px;
        border-radius: 8px;
        transition: all 0.2s ease;
        font-weight: 500;
    }

    .shift-type-container label:hover {
        background: rgba(102, 126, 234, 0.1);
    }

    .shift-type-container input[type="radio"] {
        margin-right: 8px;
        accent-color: #667eea;
    }

    .main-content {
        margin-right: 320px;
    }

    .nav-header {
        margin-bottom: 18px;
        padding-bottom: 15px;
        border-bottom: 2px solid rgba(255,255,255,0.3);
        text-align: center;
    }

    .nav-header h3 {
        margin: 0;
        color: #2d3748;
        font-family: 'Inter', sans-serif;
        font-weight: 700;
        font-size: 20px;
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
        background-clip: text;
    }

    .content-wrapper {
        margin-bottom: 20px;
    }

    .footer {
        padding: 15px;
        background: rgba(255,255,255,0.9);
        backdrop-filter: blur(10px);
        border-top: 1px solid rgba(255,255,255,0.2);
        text-align: center;
        font-size: 11px;
        color: #666;
        flex-shrink: 0;
        width: 100%;
    }

    .creator-text {
        color: #666;
        display: inline-block;
        font-weight: 500;
    }

    .creator-text a {
        color: #667eea;
        text-decoration: none;
        font-weight: 600;
        transition: all 0.3s ease;
    }

    .creator-text a:hover {
        color: white;
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        border-radius: 8px;
        padding: 4px 8px;
        margin: -4px -8px;
        transform: translateY(-1px);
    }

    .feature-request {
        color: #667eea;
        text-decoration: none;
        font-size: 12px;
        display: block;
        text-align: center;
        margin-top: 8px;
        font-weight: 500;
        transition: all 0.3s ease;
    }

    .feature-request:hover {
        color: #5a67d8;
        transform: translateY(-1px);
    }

    h4, h5 {
        font-family: 'Inter', sans-serif;
        font-weight: 700;
        color: #2d3748;
        margin-bottom: 10px;
        font-size: 14px;
    }

    @keyframes flash {
        0%, 50% { opacity: 1; }
        51%, 100% { opacity: 0.3; }
    }

    input, select {
        font-family: 'Inter', sans-serif;
    }

    .stats-card {
        background: rgba(255,255,255,0.7);
        border-radius: 12px;
        padding: 8px;
        margin-bottom: 6px;
        border: 1px solid rgba(255,255,255,0.3);
        backdrop-filter: blur(5px);
        transition: all 0.3s ease;
    }

    .stats-card:hover {
        transform: translateY(-1px);
        box-shadow: 0 4px 15px rgba(0,0,0,0.1);
    }

    .modal-backdrop {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background: rgba(0, 0, 0, 0.5);
        backdrop-filter: blur(8px);
        z-index: 99998;
        opacity: 0;
        transition: all 0.3s ease;
    }

    .modal-backdrop.show {
        opacity: 1;
    }
`;

function formatTime(dateTime) {
let time = new Date(dateTime).toLocaleTimeString([], {
hour: '2-digit',
minute: '2-digit',
hour12: false,
timeZone: 'Europe/Berlin'
});
return time === '00:00' ? '24:00' : time;
}

function getPunchesForDate(punchData, date) {
if (!punchData || !punchData.punchesTimeSegments) return [];
return punchData.punchesTimeSegments.filter(p =>
new Date(p.startDateTime).toDateString() === date.toDateString()
);
}

function injectStyles() {
    const styleSheet = document.createElement("style");
    styleSheet.textContent = styles;
    document.head.appendChild(styleSheet);
}
function fetchAPI(url) {
// For internal Amazon URLs, use regular fetch
if (url.includes('atoz-apps.amazon.work')) {
return fetch(url, {
headers: {
'accept': '/',
'x-atoz-client-id': 'ATOZ_TIMEOFF_SERVICE'
},
credentials: 'include'
}).then(response => response.json());
}

// For OnCall API, use GM_xmlhttpRequest
return new Promise((resolve, reject) => {
    GM_xmlhttpRequest({
        method: "GET",
        url: url,
        headers: {
            "Accept": "application/json",
            "Content-Type": "application/json"
        },
        credentials: 'include',
        onload: function(response) {
            if (response.status >= 200 && response.status < 300) {
                try {
                    const data = JSON.parse(response.responseText);
                    resolve(data);
                } catch (e) {
                    reject(new Error('Failed to parse response'));
                }
            } else {
                reject(new Error(`API call failed: ${response.status} ${response.statusText}`));
            }
        },
        onerror: function(error) {
            reject(new Error('Network error occurred'));
        }
    });
});
}

async function getUserTeams(loginId) {
try {
const teams = await fetchAPI(`https://oncall-api.corp.amazon.com/teams?q=members:'${loginId}' OR owners:'${loginId}'`);
return teams;
} catch (error) {
console.error('Error fetching teams:', error);
return [];
}
}

async function fetchPunchData() {
try {
console.log('Attempting to fetch punch data...');
let employeeId = null;

    // Method 1: Try to get from URL
    const urlParams = new URLSearchParams(window.location.search);
    employeeId = urlParams.get('employeeId');

    // Method 2: Try to get from page content
    if (!employeeId) {
        const pageContent = document.documentElement.innerHTML;
        const matches = pageContent.match(/employeeId["']?\s*:\s*["']([A-Z0-9]+)["']/i) ||
                       pageContent.match(/employee_id["']?\s*:\s*["']([A-Z0-9]+)["']/i) ||
                       pageContent.match(/userId["']?\s*:\s*["']([A-Z0-9]+)["']/i);

        if (matches && matches[1]) {
            employeeId = matches[1];
            console.log('Found employee ID from page content:', employeeId);
        }
    }

    // Method 3: Try to get from meta tags
    if (!employeeId) {
        const metaTags = document.getElementsByTagName('meta');
        for (let tag of metaTags) {
            if (tag.getAttribute('name') === 'employee-id' ||
                tag.getAttribute('name') === 'user-id') {
                employeeId = tag.getAttribute('content');
                break;
            }
        }
    }

    // Method 4: Try to get from localStorage
    if (!employeeId) {
        try {
            const stored = localStorage.getItem('AtoZContext');
            if (stored) {
                const parsed = JSON.parse(stored);
                employeeId = parsed?.employee?.employeeId;
            }
        } catch (e) {
            console.log('Error reading from localStorage:', e);
        }
    }

    // If still no employee ID, try one last method
    if (!employeeId) {
        const scripts = document.getElementsByTagName('script');
        for (let script of scripts) {
            const content = script.textContent;
            const match = content.match(/employeeId["']?\s*:\s*["']([A-Z0-9]+)["']/i);
            if (match) {
                employeeId = match[1];
                break;
            }
        }
    }

    if (!employeeId) {
        console.error('Failed to find employee ID using all methods');
        return null;
    }

    console.log('Employee ID found:', employeeId);

    const endDate = new Date();
    const startDate = new Date();
    startDate.setMonth(startDate.getMonth() - 2);

    const url = `https://atoz-apps.amazon.work/apis/AtoZTimeoffService/punches?employeeId=${employeeId}&startDate=${startDate.toISOString().split('T')[0]}&endDate=${endDate.toISOString().split('T')[0]}`;

    console.log('Fetching punch data from URL:', url);

    const response = await fetch(url, {
        headers: {
            'accept': '*/*',
            'x-atoz-client-id': 'ATOZ_TIMEOFF_SERVICE'
        },
        credentials: 'include'
    });

    if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json();
    console.log('Punch data received successfully');
    return data;

} catch (error) {
    console.error('Error in fetchPunchData:', error);
    return null;
}
}



function parseDate(text) {
    const match = text.match(/(\d+)\.\s+(\w+\.?)\s+(\d{4})/) || text.match(/(\w+)\s+(\d+),\s+(\d{4})/);
    if (!match) return null;

    const [_, part1, part2, year] = match;
    const day = part1.length <= 2 ? part1 : part2;
    const monthName = (part1.length <= 2 ? part2 : part1).replace('.', '');

    const months = {
        Jan: '01', January: '01',
        Feb: '02', February: '02',
        Mar: '03', March: '03',
        Apr: '04', April: '04',
        May: '05',
        Jun: '06', June: '06',
        Jul: '07', July: '07',
        Aug: '08', August: '08',
        Sep: '09', September: '09',
        Oct: '10', October: '10',
        Nov: '11', November: '11',
        Dec: '12', December: '12'
    };

    const month = months[monthName];
    if (!month) return null;

    return new Date(`${year}-${month}-${day.padStart(2, '0')}`);
}



function addPunchColumnHeader(table) {
    const headerRow = table.querySelector('thead tr');
    const th = document.createElement('th');
    th.className = 'punch-column-header';
    th.textContent = 'Punch Times';
    headerRow.appendChild(th);
}

function calculateWorkHours(inTime, outTime) {
    const start = new Date(`2000-01-01 ${inTime}`);
    const end = new Date(`2000-01-01 ${outTime}`);
    let totalHours = (end - start) / (1000 * 60 * 60);

    // Apply break time deductions
    if (totalHours < 6) {
        // No break deduction for less than 6 hours
    } else if (totalHours >= 9) {
        // 45 min break for 9+ hours
        totalHours -= 0.75;
    } else if (totalHours >= 6) {
        // 30 min break for 6+ hours
        totalHours -= 0.5;
    }

    return Math.round(totalHours * 100) / 100;
}

function exportToExcel(punchData) {
    const rows = [
        ['Date', 'Punch In', 'Punch Out', 'Hours Worked']
    ];

    const punchesByDate = {};
    punchData.punchesTimeSegments.forEach(punch => {
        const date = new Date(punch.startDateTime).toLocaleDateString();
        if (!punchesByDate[date]) {
            punchesByDate[date] = [];
        }
        punchesByDate[date].push(punch);
    });

    Object.entries(punchesByDate).forEach(([date, punches]) => {
        if (punches.length > 0) {
            const inTime = formatTime(punches[0].startDateTime);
            const outTime = formatTime(punches[punches.length - 1].endDateTime || punches[punches.length - 1].startDateTime);
            const hours = calculateWorkHours(inTime, outTime);
            rows.push([date, inTime, outTime, hours.toFixed(2)]);
        }
    });

    const csvContent = rows.map(row => row.join(',')).join('\n');
    downloadCSV(csvContent, 'AtoZ_punch_history.csv');
}

function downloadCSV(csvContent, filename) {
    const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
    const link = document.createElement('a');
    const url = URL.createObjectURL(blob);
    link.setAttribute('href', url);
    link.setAttribute('download', filename);
    link.style.visibility = 'hidden';
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
}
function createCombinedPanel(punchData) {

// Adjust the main content area
const mainContent = document.querySelector('.container');
if (mainContent) {
    mainContent.classList.add('main-content');
}

const panel = document.createElement('div');
panel.className = 'combined-panel';
panel.innerHTML = `
    <div class="panel-content">
        <div class="nav-header">
            <h3>⚡ AtoZ Assistant</h3>
        </div>

        <div class="content-wrapper">
            <div class="section">
                <div style="display: flex; align-items: center; gap: 8px; margin-bottom: 10px;">
                    <h4 style="margin: 0;">🕰️ Today's Time</h4>
                    <button id="today-info-btn" style="background: #667eea; color: white; border: none; border-radius: 50%; width: 20px; height: 20px; font-size: 12px; cursor: pointer; display: flex; align-items: center; justify-content: center; font-weight: bold; transition: all 0.3s ease;">i</button>
                </div>
                <div id="today-punch-content">
                    <div class="stats-card">
                        <div style="display: flex; justify-content: space-between; align-items: center;">
                            <span style="font-weight: 400; color: #4a5568; font-size: 14px;">🟢 In</span>
                            <span id="punch-in-time" style="font-weight: 600; color: #27ae60; font-size: 14px;">--:--:--</span>
                        </div>
                    </div>
                    <div class="stats-card">
                        <div style="display: flex; justify-content: space-between; align-items: center;">
                            <span style="font-weight: 400; color: #4a5568; font-size: 14px;">⏳ To 8h</span>
                            <span id="time-to-eight" style="font-weight: 600; color: #f39c12; font-size: 14px;">--h --m <span id="to-eight-seconds" style="font-size: 13px; opacity: 0.7;">0s</span></span>
                        </div>
                    </div>
                    <div class="stats-card">
                        <div style="display: flex; justify-content: space-between; align-items: center;">
                            <span style="font-weight: 400; color: #4a5568; font-size: 14px;">⏱️ Worked</span>
                            <span id="worked-time" style="font-weight: 600; color: #f39c12; font-size: 14px;">0h 0m <span id="worked-seconds" style="font-size: 13px; opacity: 0.7;">0s</span></span>
                        </div>
                    </div>
                </div>
            </div>

            <div class="section">
                <div style="display: flex; align-items: center; gap: 8px; margin-bottom: 16px;">
                    <h4 style="margin: 0;">📈 My Work Stats</h4>
                    <button id="break-info-btn" style="background: #667eea; color: white; border: none; border-radius: 50%; width: 20px; height: 20px; font-size: 12px; cursor: pointer; display: flex; align-items: center; justify-content: center; font-weight: bold; transition: all 0.3s ease;">i</button>
                </div>
                <div id="stats-content">
                    <div class="stats-card">
                        <div style="display: flex; justify-content: space-between; align-items: center;">
                            <span style="font-weight: 500; color: #4a5568;">🗓️ This Week</span>
                            <span id="weekly-hours" style="font-weight: 700; color: #667eea; font-size: 18px;">0.00</span>
                        </div>
                    </div>
                    <div class="stats-card">
                        <div style="display: flex; justify-content: space-between; align-items: center;">
                            <span style="font-weight: 500; color: #4a5568;">📊 This Month</span>
                            <span id="monthly-hours" style="font-weight: 700; color: #667eea; font-size: 18px;">0.00</span>
                        </div>
                    </div>
                    <button id="export-punches" class="action-button">📊 Export Work Report</button>
                </div>
            </div>

            <div class="section">
                <h4>🏖️ Time Off Balance</h4>
                <div id="balance-content">
                    <div class="stats-card">
                        <div style="display: flex; justify-content: space-between; align-items: center;">
                            <span style="font-weight: 500; color: #4a5568;">🌴 Vacation Days</span>
                            <span id="vacation-balance" style="font-weight: 700; color: #27ae60; font-size: 18px;">--</span>
                        </div>
                    </div>
                    <div class="stats-card">
                        <div style="display: flex; justify-content: space-between; align-items: center;">
                            <span style="font-weight: 500; color: #4a5568;">⏰ Overtime Hours</span>
                            <span id="overtime-balance" style="font-weight: 700; color: #f39c12; font-size: 18px;">--</span>
                        </div>
                    </div>
                </div>
            </div>


        </div>
    </div>
    <div class="footer">
        <span class="creator-text">💡 Built by <a href="https://phonetool.amazon.com/users/wmehedis" target="_blank">@wmehedis</a></span>
        <a href="mailto:[email protected]?subject=Feature Request - AtoZ Work Assistant"
           class="feature-request">
           🚀 Suggest Feature
        </a>
    </div>
`;

document.body.appendChild(panel);

// Initialize dates
const now = new Date();
const startDate = new Date(now.getFullYear(), now.getMonth(), 1);
const endDate = new Date(now.getFullYear(), now.getMonth() + 1, 0);

// Initialize dates (removed date range functionality)



// Initialize work statistics
updateWorkStatistics(punchData);

// Update today's punch display
updateTodaysPunchDisplay(punchData);
startPunchTimeUpdater();

// Fetch time off balances
fetchTimeOffBalances(punchData);

// Add event listeners
document.getElementById('export-punches').onclick = () => exportToExcel(punchData);

// Add break info button handler
document.getElementById('break-info-btn').onclick = () => {
    alert('Break Time Calculation:\n\n• Less than 6 hours: No break deducted\n• 6+ hours: 30 minutes break deducted\n• 9+ hours: 45 minutes break deducted\n\nThis follows German labor law requirements.');
};

// Add today's time info button handler
document.getElementById('today-info-btn').onclick = () => {
    alert('Today\'s Time Information:\n\n• In: Your punch-in time for today\n• To 8h: Time remaining to reach 8 hours or overtime if over 8h\n• Worked: Total hours worked today with break time deducted\n\nColor coding:\n• Orange: Less than 8 hours worked\n• Green: 8-9 hours worked (optimal)\n• Red flashing: Over 9 hours worked (alert)');
};

// Fetch time off balances
fetchTimeOffBalances(punchData);

// Update font styles for consistency
updateFontStyles();


}

function updateWorkStatistics(punchData) {
    const now = new Date();
    const weekStart = new Date(now.setDate(now.getDate() - now.getDay()));
    const monthStart = new Date(now.getFullYear(), now.getMonth(), 1);

    let weeklyHours = 0;
    let monthlyHours = 0;

    punchData.punchesTimeSegments.forEach(punch => {
        const punchDate = new Date(punch.startDateTime);
        const inTime = formatTime(punch.startDateTime);
        const outTime = formatTime(punch.endDateTime || punch.startDateTime);
        const hours = calculateWorkHours(inTime, outTime);

        if (punchDate >= weekStart) {
            weeklyHours += hours;
        }
        if (punchDate >= monthStart) {
            monthlyHours += hours;
        }
    });

    document.getElementById('weekly-hours').textContent = formatHoursMinutes(weeklyHours);
    document.getElementById('monthly-hours').textContent = formatHoursMinutes(monthlyHours);
}

async function fetchTimeOffBalances(punchData) {
    try {
        const employeeId = getEmployeeIdFromPage();
        if (!employeeId) return;

        const now = new Date().toISOString();
        const url = `https://atoz-apps.amazon.work/apis/TAAPI/v1/time-away/balances?employeeId=${employeeId}&asOfDateTime=${now}&asOfDateTimeTimezone=UTC`;

        const response = await fetch(url, {
            headers: {
                'accept': '*/*',
                'x-atoz-client-id': 'ATOZ_TIMEOFF_SERVICE'
            },
            credentials: 'include'
        });

        if (response.ok) {
            const data = await response.json();
            updateBalanceDisplay(data);
        }
    } catch (error) {
        console.error('Balance fetch error:', error);
    }
}

function updateBalanceDisplay(balanceData) {
    let vacationDays = '--';
    let overtimeHours = '--';

    if (balanceData?.balances) {
        balanceData.balances.forEach(balance => {
            if (balance.balanceName.includes('VacationHours')) {
                vacationDays = balance.availableBalance.toFixed(1);
            } else if (balance.balanceName.includes('FlexDismantlingHour')) {
                overtimeHours = balance.availableBalance.toFixed(2);
            }
        });
    }

    document.getElementById('vacation-balance').textContent = vacationDays;
    document.getElementById('overtime-balance').textContent = overtimeHours === '--' ? '--' : formatHoursMinutes(parseFloat(overtimeHours));
}

function formatHoursMinutes(totalHours) {
    const hours = Math.floor(totalHours);
    const minutes = Math.round((totalHours - hours) * 60);
    return `${hours}h ${minutes}m`;
}

function updateTodaysPunchDisplay(punchData) {
    const today = new Date();
    const todayPunches = getPunchesForDate(punchData, today);

    if (todayPunches.length > 0) {
        const punchIn = new Date(todayPunches[0].startDateTime);
        const punchOut = todayPunches[todayPunches.length - 1].endDateTime ?
            new Date(todayPunches[todayPunches.length - 1].endDateTime) : null;

        document.getElementById('punch-in-time').textContent = formatTimeWithSeconds(punchIn);

        if (punchOut) {
            const hours = calculateWorkHours(formatTime(punchIn), formatTime(punchOut));
            document.getElementById('worked-time').textContent = formatHoursMinutes(hours);
            updateTimeToEight(hours, true);
        } else {
            updateTimeToEight(0, false);
        }
    }
}

function formatTimeWithSeconds(dateTime) {
    return new Date(dateTime).toLocaleTimeString([], {
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit',
        hour12: false,
        timeZone: 'Europe/Berlin'
    });
}

function updateTimeToEight(currentHours, isPunchedOut) {
    const timeToEightElement = document.getElementById('time-to-eight');

    if (currentHours >= 8) {
        const overtime = currentHours - 8;
        const overtimeFormatted = formatHoursMinutes(overtime);
        timeToEightElement.innerHTML = `<span style="font-size: 12px;">+${overtimeFormatted}</span>`;
        timeToEightElement.style.color = '#27ae60';
    } else {
        const remaining = 8 - currentHours;
        timeToEightElement.textContent = formatHoursMinutes(remaining);
        timeToEightElement.style.color = '#f39c12';
    }
}

let startTime = null;

let alertSoundPlayed = false;

function startPunchTimeUpdater() {
    setInterval(() => {
        const punchInElement = document.getElementById('punch-in-time');
        const workedElement = document.getElementById('worked-time');

        if (punchInElement && punchInElement.textContent !== '--:--:--') {
            const today = new Date();
            const todayPunches = getPunchesForDate(window.punchData, today);
            const isPunchedOut = todayPunches.length > 0 && todayPunches[todayPunches.length - 1].endDateTime;

            if (!isPunchedOut) {
                if (!startTime) {
                    const punchInTime = punchInElement.textContent;
                    const [hours, minutes, seconds] = punchInTime.split(':');
                    startTime = new Date();
                    startTime.setHours(parseInt(hours), parseInt(minutes), parseInt(seconds));
                }

                const now = new Date();
                const workedMs = now - startTime;
                const totalSeconds = Math.floor(workedMs / 1000);
                const totalHours = totalSeconds / 3600;

                // Apply break time deductions for display
                let adjustedHours = totalHours;
                if (totalHours >= 9) {
                    adjustedHours -= 0.75; // 45 min break
                } else if (totalHours >= 6) {
                    adjustedHours -= 0.5; // 30 min break
                }

                // Calculate hours and minutes from adjusted time
                const hours = Math.floor(adjustedHours);
                const minutes = Math.floor((adjustedHours - hours) * 60);
                const seconds = totalSeconds % 60;

                // Color coding and alerts based on hours worked
                let color = '#f39c12'; // Orange for <8h
                let animation = '';

                if (totalHours >= 9) {
                    color = '#e74c3c'; // Red for 9h+
                    animation = 'flash 1s infinite';

                    // Sound alert at 9h 45m
                    if (totalHours >= 9.75 && !alertSoundPlayed) {
                        playAlertSound();
                        showNotification('Work Time Alert', 'You have worked 9h 45m. Remember to punch out!');
                        alertSoundPlayed = true;
                    }
                } else if (totalHours >= 8) {
                    color = '#27ae60'; // Green for 8-9h
                }

                workedElement.innerHTML = `${hours}h ${minutes}m <span style="font-size: 13px; opacity: 0.7;">${seconds}s</span>`;
                workedElement.style.color = color;
                workedElement.style.animation = animation;

                updateTimeToEightWithSeconds(totalSeconds);
            }
        }
    }, 1000);
}

function playAlertSound() {
    const audioContext = new (window.AudioContext || window.webkitAudioContext)();
    const oscillator = audioContext.createOscillator();
    const gainNode = audioContext.createGain();

    oscillator.connect(gainNode);
    gainNode.connect(audioContext.destination);

    oscillator.frequency.setValueAtTime(800, audioContext.currentTime);
    oscillator.frequency.setValueAtTime(600, audioContext.currentTime + 0.1);
    oscillator.frequency.setValueAtTime(800, audioContext.currentTime + 0.2);

    gainNode.gain.setValueAtTime(0.3, audioContext.currentTime);
    gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.3);

    oscillator.start(audioContext.currentTime);
    oscillator.stop(audioContext.currentTime + 0.3);
}

function showNotification(title, message) {
    if ('Notification' in window) {
        if (Notification.permission === 'granted') {
            new Notification(title, { body: message, icon: 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><text y="18" font-size="18">⏰</text></svg>' });
        } else if (Notification.permission !== 'denied') {
            Notification.requestPermission().then(permission => {
                if (permission === 'granted') {
                    new Notification(title, { body: message });
                }
            });
        }
    }

    // Fallback: Browser alert
    setTimeout(() => alert(`${title}: ${message}`), 100);
}

function updateTimeToEightWithSeconds(totalWorkedSeconds) {
    const timeToEightElement = document.getElementById('time-to-eight');
    const eightHoursInSeconds = 8 * 3600;

    if (totalWorkedSeconds >= eightHoursInSeconds) {
        const overtimeSeconds = totalWorkedSeconds - eightHoursInSeconds;
        const hours = Math.floor(overtimeSeconds / 3600);
        const minutes = Math.floor((overtimeSeconds % 3600) / 60);
        const seconds = overtimeSeconds % 60;
        timeToEightElement.innerHTML = `<span style="font-size: 12px;">+${hours}h ${minutes}m <span style="font-size: 10px; opacity: 0.7; animation: pulse 0.5s ease-in-out;">${seconds}s</span></span>`;
        timeToEightElement.style.color = '#27ae60';
    } else {
        const remainingSeconds = eightHoursInSeconds - totalWorkedSeconds;
        const hours = Math.floor(remainingSeconds / 3600);
        const minutes = Math.floor((remainingSeconds % 3600) / 60);
        const seconds = remainingSeconds % 60;
        timeToEightElement.innerHTML = `${hours}h ${minutes}m <span style="font-size: 12px; opacity: 0.7; animation: pulse 0.5s ease-in-out;">${seconds}s</span>`;
        timeToEightElement.style.color = '#f39c12';
    }
}

function updateFontStyles() {
    // Update Work Stats section labels and values
    document.querySelectorAll('.stats-card').forEach(card => {
        const label = card.querySelector('span:first-child');
        const value = card.querySelector('span:last-child');

        if (label) {
            label.style.fontWeight = '400';
            label.style.fontSize = '14px';
        }

        if (value) {
            value.style.fontWeight = '600';
            value.style.fontSize = '14px';
        }
    });

    // Specific IDs
    ['weekly-hours', 'monthly-hours', 'vacation-balance', 'overtime-balance'].forEach(id => {
        const element = document.getElementById(id);
        if (element) {
            element.style.fontWeight = '600';
            element.style.fontSize = '14px';
        }
    });
}

function getEmployeeIdFromPage() {
    const urlParams = new URLSearchParams(window.location.search);
    let employeeId = urlParams.get('employeeId');

    if (!employeeId) {
        const pageContent = document.documentElement.innerHTML;
        const matches = pageContent.match(/employeeId["']?\s*:\s*["']([A-Z0-9]+)["']/i);
        if (matches && matches[1]) {
            employeeId = matches[1];
        }
    }

    return employeeId;
}






async function processTable() {
console.log('Starting processTable');
try {
// Find the table
const table = document.querySelector('table[data-test-component="StencilTable"]');
if (!table) {
console.log('Table not found');
return;
}

    // Check if punch column already exists
    if (!table.querySelector('.punch-column-header')) {
        console.log('Found table, injecting styles');
        injectStyles();

        console.log('Adding punch column header');
        addPunchColumnHeader(table);
    }

    console.log('Fetching punch data');
    const punchData = await fetchPunchData();
    if (!punchData) {
        console.error('No punch data received');
        return;
    }

    // Store punch data globally for use in OnCall sheet generation
    window.punchData = punchData;
    console.log('Punch data received and stored globally:', punchData);

    console.log('Creating combined panel');
    // Remove existing panel if it exists
    const existingPanel = document.querySelector('.combined-panel');
    if (existingPanel) {
        existingPanel.remove();
    }
    createCombinedPanel(punchData);

    console.log('Adding OnCall button');
    injectOnCallButton();

    console.log('Processing table rows');
    const rows = table.querySelectorAll('tbody tr');
    rows.forEach((row, index) => {
        try {
            const dateCell = row.querySelector('.css-1vslykb');
            const dateText = dateCell?.querySelector('.css-1kgbsl4')?.textContent;
            console.log(`Processing row ${index}, date: ${dateText}`);

            const date = parseDate(dateText);
            const cell = document.createElement('td');
            cell.className = 'punch-cell';

            if (date) {
                const punches = getPunchesForDate(punchData, date);
                console.log(`Found ${punches.length} punches for ${dateText}`);

                if (punches.length > 0) {
                    const inTime = formatTime(punches[0].startDateTime);
                    const outTime = formatTime(
                        punches[punches.length - 1].endDateTime ||
                        punches[punches.length - 1].startDateTime
                    );

                    cell.innerHTML = `
                        <span class="punch-card">
                            In: <span class="punch-in">${inTime}</span>
                        </span>
                        <span class="punch-card">
                            Out: <span class="punch-out">${outTime}</span>
                        </span>
                    `;
                } else {
                    cell.textContent = '—';
                }
            } else {
                console.log(`Invalid date for row ${index}: ${dateText}`);
                cell.textContent = 'Invalid';
            }

            // Check if cell already exists
            const existingCell = row.querySelector('.punch-cell');
            if (existingCell) {
                console.log(`Replacing existing cell for row ${index}`);
                row.replaceChild(cell, existingCell);
            } else {
                console.log(`Adding new cell for row ${index}`);
                row.appendChild(cell);
            }
        } catch (rowError) {
            console.error(`Error processing row ${index}:`, rowError);
        }
    });

    // Update work statistics
    console.log('Updating work statistics');
    try {
        updateWorkStatistics(punchData);
    } catch (statsError) {
        console.error('Error updating work statistics:', statsError);
    }

    // Add mutation observer to handle dynamic updates
    const observer = new MutationObserver((mutations) => {
        mutations.forEach((mutation) => {
            if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                const newRows = Array.from(mutation.addedNodes)
                    .filter(node => node.nodeName === 'TR');

                if (newRows.length > 0) {
                    console.log('New rows detected, updating punch data');
                    newRows.forEach((row, index) => {
                        try {
                            const dateCell = row.querySelector('.css-1vslykb');
                            const dateText = dateCell?.querySelector('.css-1kgbsl4')?.textContent;
                            if (dateText) {
                                const date = parseDate(dateText);
                                if (date) {
                                    const punches = getPunchesForDate(punchData, date);
                                    const cell = document.createElement('td');
                                    cell.className = 'punch-cell';

                                    if (punches.length > 0) {
                                        const inTime = formatTime(punches[0].startDateTime);
                                        const outTime = formatTime(
                                            punches[punches.length - 1].endDateTime ||
                                            punches[punches.length - 1].startDateTime
                                        );

                                        cell.innerHTML = `
                                            <span class="punch-card">
                                                In: <span class="punch-in">${inTime}</span>
                                            </span>
                                            <span class="punch-card">
                                                Out: <span class="punch-out">${outTime}</span>
                                            </span>
                                        `;
                                    } else {
                                        cell.textContent = '—';
                                    }
                                    row.appendChild(cell);
                                }
                            }
                        } catch (error) {
                            console.error(`Error processing new row ${index}:`, error);
                        }
                    });
                }
            }
        });
    });

    // Start observing the table body
    const tbody = table.querySelector('tbody');
    if (tbody) {
        observer.observe(tbody, {
            childList: true,
            subtree: true
        });
    }

    // Store the observer in a global variable so it can be disconnected if needed
    window.tableObserver = observer;

    console.log('Table processing complete');
} catch (error) {
    console.error('Error in processTable:', error);
}
}

// Add event listener for DOM changes
const observeDOM = (function() {
const MutationObserver = window.MutationObserver || window.WebKitMutationObserver;

return function(obj, callback) {
    if (!obj || obj.nodeType !== 1) return;

    if (MutationObserver) {
        const obs = new MutationObserver((mutations, observer) => {
            callback(mutations);
        });
        obs.observe(obj, {
            childList: true,
            subtree: true
        });
    } else if (window.addEventListener) {
        obj.addEventListener('DOMNodeInserted', callback, false);
        obj.addEventListener('DOMNodeRemoved', callback, false);
    }
};
})();

// Initialize the script with retry mechanism

function injectOnCallDialog() {
const existingDialog = document.getElementById("oncall-dialog");
if (existingDialog) return;

const dialog = document.createElement("div");
dialog.id = "oncall-dialog";
dialog.style.cssText = `
    position: fixed;
    top: 80px;
    left: 50%;
    transform: translateX(-50%);
    background: white;
    border: 1px solid #ccc;
    border-radius: 16px;
    padding: 30px;
    z-index: 99999;
    width: 850px;
    max-height: 85vh;
    overflow-y: auto;
    box-shadow: 0 20px 60px rgba(0,0,0,0.3);
    font-family: 'Inter', sans-serif;
    backdrop-filter: blur(10px);
    opacity: 0;
    transform: translateX(-50%) translateY(-20px);
    transition: all 0.3s ease;
`;

dialog.innerHTML = `
    <div style="position: sticky; top: 0; background: white; z-index: 100; display: flex; justify-content: space-between; align-items: center; margin-bottom: 25px; padding: 15px; border-radius:15px; border-bottom: 2px solid #f1f5f9; box-shadow: 0 2px 10px rgba(0,0,0,0.1);">
        <h3 style="margin: 0; font-family: 'Inter', sans-serif; font-weight: 700; color: #2d3748; font-size: 26px;">📋 My OnCall Schedule</h3>
        <button id="close-oncall-dialog" style="background: linear-gradient(135deg, #ff6b6b, #ee5a52); color: white; border: none; font-size: 18px; cursor: pointer; border-radius: 50%; width: 40px; height: 40px; display: flex; align-items: center; justify-content: center; transition: all 0.3s ease; box-shadow: 0 4px 12px rgba(255, 107, 107, 0.3);">×</button>
    </div>
    <div style="font-family: 'Inter', sans-serif; padding: 0 5px;">
        <div style="margin-bottom: 25px;">
            <label style="display: block; margin-bottom: 10px; font-weight: 600; color: #4a5568; font-size: 15px;">👤 Login ID:</label>
            <input type="text" id="oncall-loginId" placeholder="Enter your Amazon login" style="width: 100%; margin-bottom: 18px; padding: 14px; border: 2px solid #e2e8f0; border-radius: 12px; font-family: 'Inter', sans-serif; font-size: 14px; transition: all 0.3s ease;">
        </div>

        <div style="margin-bottom: 25px;">
            <label style="display: block; margin-bottom: 10px; font-weight: 600; color: #4a5568; font-size: 15px;">📆 Month:</label>
            <input type="month" id="oncall-monthSelect" style="width: 100%; margin-bottom: 18px; padding: 14px; border: 2px solid #e2e8f0; border-radius: 12px; font-family: 'Inter', sans-serif; font-size: 14px; transition: all 0.3s ease;">
        </div>

        <div style="margin: 25px 0; padding: 25px; background: linear-gradient(135deg, rgba(102, 126, 234, 0.1), rgba(118, 75, 162, 0.1)); border-radius: 16px; border: 1px solid rgba(102, 126, 234, 0.2); transition: all 0.3s ease;">
            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 18px;">
                <h4 style="margin: 0; font-weight: 600; color: #2d3748; font-size: 16px;">⚙️ Manual Time Override</h4>
                <label class="switch">
                    <input type="checkbox" id="manual-override-toggle">
                    <span class="slider round"></span>
                </label>
            </div>
            <div id="manual-override-section" style="display: none;">
                <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 25px;">
                    <div style="background: rgba(255,255,255,0.8); padding: 18px; border-radius: 12px; transition: all 0.3s ease; border: 1px solid rgba(255,255,255,0.5);">
                        <label style="display: block; margin-bottom: 10px; font-weight: 600; color: #4a5568; font-size: 14px;">🌅 Early Shift:</label>
                        <div style="display: flex; gap: 10px; margin-top: 10px;">
                            <input type="text" id="early-shift-start" placeholder="02:30" style="width: 85px; padding: 10px; border: 2px solid #e2e8f0; border-radius: 8px; font-family: 'Inter', sans-serif; transition: all 0.3s ease;" maxlength="5">
                            <input type="text" id="early-shift-end" placeholder="13:00" style="width: 85px; padding: 10px; border: 2px solid #e2e8f0; border-radius: 8px; font-family: 'Inter', sans-serif; transition: all 0.3s ease;" maxlength="5">
                        </div>
                        <small style="color: #718096; font-size: 12px; margin-top: 5px; display: block;">24hr format (e.g., 02:30)</small>
                    </div>
                    <div style="background: rgba(255,255,255,0.8); padding: 18px; border-radius: 12px; transition: all 0.3s ease; border: 1px solid rgba(255,255,255,0.5);">
                        <label style="display: block; margin-bottom: 10px; font-weight: 600; color: #4a5568; font-size: 14px;">🌙 Late Shift:</label>
                        <div style="display: flex; gap: 10px; margin-top: 10px;">
                            <input type="text" id="late-shift-start" placeholder="13:00" style="width: 85px; padding: 10px; border: 2px solid #e2e8f0; border-radius: 8px; font-family: 'Inter', sans-serif; transition: all 0.3s ease;" maxlength="5">
                            <input type="text" id="late-shift-end" placeholder="22:00" style="width: 85px; padding: 10px; border: 2px solid #e2e8f0; border-radius: 8px; font-family: 'Inter', sans-serif; transition: all 0.3s ease;" maxlength="5">
                        </div>
                        <small style="color: #718096; font-size: 12px; margin-top: 5px; display: block;">24hr format (e.g., 13:00)</small>
                    </div>
                </div>
            </div>
        </div>

        <div style="display: flex; gap: 15px; margin-top: 30px;">
            <button id="oncall-fetch" style="flex: 1; padding: 16px 24px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border: none; border-radius: 12px; font-family: 'Inter', sans-serif; font-weight: 600; cursor: pointer; transition: all 0.3s ease; box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3); font-size: 15px;">🔍 Load My Schedule</button>
            <button id="download-oncall-sheet" style="flex: 1; padding: 16px 24px; background: linear-gradient(135deg, #48bb78 0%, #38a169 100%); color: white; border: none; border-radius: 12px; font-family: 'Inter', sans-serif; font-weight: 600; cursor: pointer; transition: all 0.3s ease; box-shadow: 0 4px 15px rgba(72, 187, 120, 0.3); font-size: 15px;" disabled>💾 Export Timesheet</button>
        </div>
    </div>
    <div id="oncall-debug" style="font-size: 13px; margin-top: 25px; background: rgba(255,255,255,0.9); padding: 18px; border-radius: 12px; border: 1px solid #e2e8f0; font-family: 'Inter', sans-serif;"></div>
    <div id="oncall-results" style="margin-top: 25px;"></div>
`;

// Add CSS for the toggle switch and hover effects
const style = document.createElement('style');
style.textContent = `
    .switch {
        position: relative;
        display: inline-block;
        width: 60px;
        height: 34px;
    }
    .switch input {
        opacity: 0;
        width: 0;
        height: 0;
    }
    .slider {
        position: absolute;
        cursor: pointer;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background-color: #ccc;
        transition: .4s;
        border-radius: 34px;
    }
    .slider:before {
        position: absolute;
        content: "";
        height: 26px;
        width: 26px;
        left: 4px;
        bottom: 4px;
        background-color: white;
        transition: .4s;
        border-radius: 50%;
    }
    input:checked + .slider {
        background-color: #667eea;
    }
    input:checked + .slider:before {
        transform: translateX(26px);
    }
    #oncall-dialog input:hover {
        border-color: #667eea;
        transform: translateY(-1px);
        box-shadow: 0 4px 12px rgba(102, 126, 234, 0.15);
    }
    #oncall-dialog button:hover {
        transform: translateY(-2px);
        box-shadow: 0 8px 25px rgba(0,0,0,0.2);
    }
    #close-oncall-dialog:hover {
        transform: scale(1.1);
        box-shadow: 0 6px 20px rgba(255, 107, 107, 0.4);
    }
    .manual-override-section > div:hover {
        transform: translateY(-2px);
        box-shadow: 0 8px 25px rgba(0,0,0,0.1);
    }
`;
document.head.appendChild(style);
// Create backdrop
const backdrop = document.createElement('div');
backdrop.className = 'modal-backdrop';
backdrop.onclick = () => {
    backdrop.classList.remove('show');
    dialog.style.opacity = '0';
    dialog.style.transform = 'translateX(-50%) translateY(-20px)';
    setTimeout(() => {
        backdrop.remove();
        dialog.remove();
    }, 300);
};

document.body.appendChild(backdrop);
document.body.appendChild(dialog);

// Animate in
setTimeout(() => {
    backdrop.classList.add('show');
    dialog.style.opacity = '1';
    dialog.style.transform = 'translateX(-50%) translateY(0)';
}, 10);

// Create state tracker
const dialogState = {
    isOverrideEnabled: false
};

// Get elements
const toggleSwitch = document.getElementById("manual-override-toggle");
const overrideSection = document.getElementById("manual-override-section");

console.log("Initial elements state:", {
    toggleSwitch: toggleSwitch,
    overrideSection: overrideSection,
    toggleChecked: toggleSwitch?.checked,
    dialogState: dialogState
});

// Toggle event handler with state tracking
toggleSwitch.addEventListener('change', (event) => {
    dialogState.isOverrideEnabled = event.target.checked;

    console.log("Toggle changed:", {
        checked: event.target.checked,
        previousDisplay: overrideSection.style.display,
        dialogState: dialogState
    });

    overrideSection.style.display = event.target.checked ? "block" : "none";

    console.log("After display change:", {
        newDisplay: overrideSection.style.display,
        sectionVisible: overrideSection.offsetParent !== null,
        dialogState: dialogState
    });
});

// Add time format validation
function validateTimeInput(input) {
    input.addEventListener('input', function() {
        let value = this.value;
        if (value.length === 2 && !value.includes(':')) {
            this.value = value + ':';
        }

        const timeRegex = /^([01]?[0-9]|2[0-3]):[0-5][0-9]$/;
        if (value && !timeRegex.test(value)) {
            this.style.borderColor = 'red';
        } else {
            this.style.borderColor = '';
        }
    });
}

// Apply validation to all time inputs
['early-shift-start', 'early-shift-end', 'late-shift-start', 'late-shift-end'].forEach(id => {
    validateTimeInput(document.getElementById(id));
});

// Download button handler with state check
document.getElementById("download-oncall-sheet").addEventListener('click', () => {
    // Read toggle state directly from element
    const isOverrideEnabled = toggleSwitch.checked;

    console.log("Download button clicked, override enabled:", isOverrideEnabled);

    // Create config using actual toggle state
    const config = {
        startHour: 6,
        isOverrideEnabled: isOverrideEnabled
    };

    // If override is enabled, collect the time values
    if (isOverrideEnabled) {
        config.overrideValues = {
            earlyShift: {
                start: document.getElementById('early-shift-start').value || '02:30',
                end: document.getElementById('early-shift-end').value || '13:00'
            },
            lateShift: {
                start: document.getElementById('late-shift-start').value || '13:00',
                end: document.getElementById('late-shift-end').value || '22:00'
            }
        };
    }

    console.log("Generated config:", config);

    generateOnCallSheetFromAPI(
        window.oncallScheduleData,
        window.punchData,
        document.getElementById("oncall-monthSelect").value,
        config
    );
});

// Close dialog handler
document.getElementById("close-oncall-dialog").onclick = () => {
    backdrop.classList.remove('show');
    dialog.style.opacity = '0';
    dialog.style.transform = 'translateX(-50%) translateY(-20px)';
    setTimeout(() => {
        backdrop.remove();
        dialog.remove();
    }, 300);
};

// Add hover effects to manual override cards
const overrideCards = dialog.querySelectorAll('#manual-override-section > div > div');
overrideCards.forEach(card => {
    card.classList.add('manual-override-section');
});

// Set initial month value
document.getElementById("oncall-monthSelect").value = new Date().toISOString().slice(0, 7);

// Fetch button handler
document.getElementById("oncall-fetch").onclick = () => {
    const loginId = document.getElementById("oncall-loginId").value.trim();
    const month = document.getElementById("oncall-monthSelect").value;
    const debugDiv = document.getElementById("oncall-debug");
    const resultsDiv = document.getElementById("oncall-results");

    // Validation with animated feedback
    if (!loginId) {
        debugDiv.innerHTML = `
            <div style="display: flex; align-items: center; gap: 10px; padding: 10px; background: linear-gradient(135deg, rgba(255, 193, 7, 0.1), rgba(255, 152, 0, 0.1)); border-radius: 12px; animation: shake 0.5s;">
                <span style="font-size: 24px; animation: wiggle 1s infinite;">⚠️</span>
                <span style="font-weight: 600; color: #f39c12;">Please enter your Login ID to continue</span>
            </div>
            <style>
                @keyframes shake { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-5px); } 75% { transform: translateX(5px); } }
                @keyframes wiggle { 0%, 100% { transform: rotate(0deg); } 25% { transform: rotate(-10deg); } 75% { transform: rotate(10deg); } }
            </style>
        `;
        document.getElementById("oncall-loginId").focus();
        return;
    }

    if (!month) {
        debugDiv.innerHTML = `
            <div style="display: flex; align-items: center; gap: 10px; padding: 10px; background: linear-gradient(135deg, rgba(255, 193, 7, 0.1), rgba(255, 152, 0, 0.1)); border-radius: 12px; animation: shake 0.5s;">
                <span style="font-size: 24px; animation: wiggle 1s infinite;">📅</span>
                <span style="font-weight: 600; color: #f39c12;">Please select which month to view</span>
            </div>
        `;
        document.getElementById("oncall-monthSelect").focus();
        return;
    }

    fetchScheduleData(loginId, month, debugDiv, resultsDiv);
};
}

function generateOnCallSheetFromAPI(scheduleData, punchData, monthValue, config) {
// Set default configuration if not provided
const defaultConfig = {
date: new Date().toLocaleDateString(),
startHour: 6,
isOverrideEnabled: false,
overrideValues: 'disabled'
};

// Merge provided config with defaults
const finalConfig = { ...defaultConfig, ...config };

console.log("Processing with configuration:", finalConfig);

const [year, month] = monthValue.split('-').map(num => parseInt(num));

// Headers for the CSV
const rows = [
    ['Date', '', 'One Shift', '', 'Double Shift', '', 'Notes'],
    ['', '', 'From', 'To', 'From', 'To', ''],
    ['', '', '(00:00)', '(24:00)', '(00:00)', '(24:00)', '']
];

// Create a map of dates and their shifts
const dateShifts = new Map();
const lastDay = new Date(year, month, 0).getDate();

// Initialize all dates in the month
for (let day = 1; day <= lastDay; day++) {
    const date = new Date(year, month - 1, day);
    const dateStr = date.toLocaleDateString('en-US', {
        month: 'numeric',
        day: 'numeric',
        year: 'numeric'
    });
    dateShifts.set(dateStr, {
        oneShiftFrom: '',
        oneShiftTo: '',
        doubleShiftFrom: '',
        doubleShiftTo: '',
        notes: ''
    });
}

// Process schedule data with multi-day shift handling
scheduleData.forEach(entry => {
    if (entry.oncallShift) {
        const startDate = new Date(entry.oncallShift.startDateTime);
        const endDate = new Date(entry.oncallShift.endDateTime);
        const startHour = startDate.getHours();

        // Calculate all dates for this shift
        const dates = [];
        let currentDate = new Date(startDate);
        const endHour = endDate.getHours();
        let isMidnightCrossing = startHour >= 13 && (endHour <= 6 || endDate.getDate() !== startDate.getDate());

        // Check for manual override midnight crossing
        if (finalConfig.isOverrideEnabled && finalConfig.overrideValues && startHour >= 13) {
            const lateEndTime = finalConfig.overrideValues.lateShift.end;
            const [endH] = lateEndTime.split(':').map(Number);
            if (endH <= 6) {
                isMidnightCrossing = true;
            }
        }

        if (isMidnightCrossing && endDate.getDate() !== startDate.getDate()) {
            // For midnight crossing shifts, add both start and end dates
            if (startDate.getMonth() === month - 1) dates.push(new Date(startDate));
            if (endDate.getMonth() === month - 1) dates.push(new Date(endDate));
        } else {
            while (currentDate <= endDate) {
                if (currentDate.getMonth() === month - 1) {
                    dates.push(new Date(currentDate));
                }
                currentDate.setDate(currentDate.getDate() + 1);
            }
        }

        // Process each date in the shift
        dates.forEach((date, index) => {
            const dateStr = date.toLocaleDateString('en-US', {
                month: 'numeric',
                day: 'numeric',
                year: 'numeric'
            });

            const shiftData = dateShifts.get(dateStr);
            if (!shiftData) return;

            const isStartDate = index === 0;
            const isEndDate = index === dates.length - 1;
            const isMultiDayShift = dates.length > 1;
            // isMidnightCrossing already calculated above

            if (finalConfig.isOverrideEnabled && finalConfig.overrideValues) {
                const overrides = finalConfig.overrideValues;
                if (isMultiDayShift) {
                    if (isStartDate) {
                        // First day: use override start time or API time
                        const startTime = startHour < 13 ? overrides.earlyShift.start : overrides.lateShift.start;
                        shiftData.oneShiftFrom = startTime;
                        shiftData.oneShiftTo = '24:00:00';
                    } else if (isEndDate) {
                        // Last day: 00:00 to punch in or API end time
                        const punches = getPunchesForDate(punchData, date);
                        shiftData.oneShiftFrom = '0:00';
                        if (punches.length > 0) {
                            const punchIn = new Date(punches[0].startDateTime);
                            const apiEnd = new Date(endDate);
                            const earlierTime = punchIn < apiEnd ? punchIn : apiEnd;
                            shiftData.oneShiftTo = formatTime(earlierTime);
                        } else {
                            shiftData.oneShiftTo = formatTime(endDate);
                        }
                    } else {
                        // Middle days: 00:00 to 24:00
                        shiftData.oneShiftFrom = '0:00';
                        shiftData.oneShiftTo = '24:00:00';
                    }
                } else if (isMidnightCrossing && isStartDate) {
                    // Late shift crossing midnight with override - use punch out time
                    const punches = getPunchesForDate(punchData, startDate);
                    if (punches.length > 0) {
                        const punchOut = new Date(punches[punches.length - 1].endDateTime);
                        shiftData.doubleShiftFrom = formatTime(punchOut);
                    } else {
                        shiftData.doubleShiftFrom = '15:00';
                        shiftData.notes = 'No punch time found in AtoZ';
                    }
                    shiftData.doubleShiftTo = '24:00';

                    const nextDate = new Date(startDate);
                    nextDate.setDate(nextDate.getDate() + 1);
                    const nextDateStr = nextDate.toLocaleDateString('en-US', {
                        month: 'numeric',
                        day: 'numeric',
                        year: 'numeric'
                    });
                    const nextShiftData = dateShifts.get(nextDateStr);
                    if (nextShiftData) {
                        nextShiftData.oneShiftFrom = '00:00';
                        nextShiftData.oneShiftTo = overrides.lateShift.end;
                    }
                } else {
                    // Single day shifts with override
                    const punches = getPunchesForDate(punchData, date);

                    if (startHour < 13) {
                        // Early shift with override
                        shiftData.oneShiftFrom = overrides.earlyShift.start;
                        if (punches.length > 0) {
                            const punchIn = new Date(punches[0].startDateTime);
                            shiftData.oneShiftTo = formatTime(punchIn);
                        } else {
                            shiftData.oneShiftTo = overrides.earlyShift.end;
                            shiftData.notes = 'No punch time found in AtoZ';
                        }
                    } else {
                        // Late shift with override
                        if (punches.length > 0) {
                            const punchOut = new Date(punches[punches.length - 1].endDateTime);
                            shiftData.oneShiftFrom = formatTime(punchOut);
                        } else {
                            shiftData.oneShiftFrom = overrides.lateShift.start;
                            shiftData.notes = 'No punch time found in AtoZ';
                        }
                        shiftData.oneShiftTo = overrides.lateShift.end;
                    }
                }
            } else {
                if (isMultiDayShift) {
                    if (isStartDate) {
                        const punches = getPunchesForDate(punchData, startDate);
                        if (punches.length > 0) {
                            const punchIn = new Date(punches[0].startDateTime);
                            shiftData.oneShiftFrom = formatTime(startDate);
                            shiftData.oneShiftTo = '24:00:00';
                        } else {
                            shiftData.oneShiftFrom = formatTime(startDate);
                            shiftData.oneShiftTo = '24:00:00';
                        }
                    } else if (isEndDate) {
                        const punches = getPunchesForDate(punchData, endDate);
                        if (punches.length > 0) {
                            const punchIn = new Date(punches[0].startDateTime);
                            const oncallEnd = new Date(endDate);
                            const earlierTime = punchIn < oncallEnd ? punchIn : oncallEnd;
                            shiftData.oneShiftFrom = '0:00';
                            shiftData.oneShiftTo = formatTime(earlierTime) + ':00';
                        } else {
                            shiftData.oneShiftFrom = '0:00';
                            shiftData.oneShiftTo = formatTime(endDate) + ':00';
                        }
                    } else {
                        shiftData.oneShiftFrom = '0:00';
                        shiftData.oneShiftTo = '24:00:00';
                    }
                } else if (isMidnightCrossing && isStartDate) {
                    // Late shift crossing midnight - use punch times
                    const punches = getPunchesForDate(punchData, startDate);
                    if (punches.length > 0) {
                        const punchOut = new Date(punches[punches.length - 1].endDateTime);
                        shiftData.doubleShiftFrom = formatTime(punchOut);
                    } else {
                        shiftData.doubleShiftFrom = '15:00';
                        shiftData.notes = 'No punch time found in AtoZ';
                    }
                    shiftData.doubleShiftTo = '24:00';

                    const nextDate = new Date(startDate);
                    nextDate.setDate(nextDate.getDate() + 1);
                    const nextDateStr = nextDate.toLocaleDateString('en-US', {
                        month: 'numeric',
                        day: 'numeric',
                        year: 'numeric'
                    });
                    const nextShiftData = dateShifts.get(nextDateStr);
                    if (nextShiftData) {
                        nextShiftData.oneShiftFrom = '00:00';
                        nextShiftData.oneShiftTo = formatTime(endDate);
                    }
                } else {
                    const punches = getPunchesForDate(punchData, startDate);
                    if (startHour >= 13) {
                        if (punches.length > 0) {
                            const punchOut = new Date(punches[punches.length - 1].endDateTime);
                            shiftData.oneShiftFrom = formatTime(punchOut);
                        } else {
                            shiftData.oneShiftFrom = '15:00';
                            shiftData.notes = 'No punch time found in AtoZ';
                        }
                        shiftData.oneShiftTo = formatTime(endDate);
                    } else {
                        shiftData.oneShiftFrom = formatTime(startDate);
                        if (punches.length > 0) {
                            const punchIn = new Date(punches[0].startDateTime);
                            shiftData.oneShiftTo = formatTime(punchIn);
                        } else {
                            shiftData.oneShiftTo = formatTime(endDate);
                            shiftData.notes = 'No punch time found in AtoZ';
                        }
                    }
                }
            }
        });
    }
});

// Create rows in chronological order
const sortedDates = Array.from(dateShifts.keys()).sort((a, b) => new Date(a) - new Date(b));
sortedDates.forEach(dateStr => {
    const shiftData = dateShifts.get(dateStr);
    rows.push([
        dateStr,
        '',
        shiftData.oneShiftFrom,
        shiftData.oneShiftTo,
        shiftData.doubleShiftFrom,
        shiftData.doubleShiftTo,
        shiftData.notes
    ]);
});

// Convert to TSV and download
const tsvContent = rows.map(row => row.join('\t')).join('\n');
const blob = new Blob([tsvContent], { type: 'text/tab-separated-values;charset=utf-8' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.setAttribute('href', url);
link.setAttribute('download', `Oncall_allowance_sheet_${monthValue}.xls`);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}

async function fetchScheduleData(loginId, monthValue, debugDiv, resultsDiv) {
const loadingMessages = [
    { emoji: '🚀', text: 'Starting fetch process...', progress: 10 },
    { emoji: '📅', text: 'Setting up date range...', progress: 20 },
    { emoji: '🔍', text: 'Searching for your teams...', progress: 40 },
    { emoji: '⚡', text: 'Found teams! Fetching schedules...', progress: 60 },
    { emoji: '📊', text: 'Processing data...', progress: 80 },
    { emoji: '✨', text: 'Almost done...', progress: 95 }
];

let messageIndex = 0;
let progressInterval;
let messageTimeout;
let isProcessing = true;

const updateProgress = (targetProgress, currentMessage) => {
    if (!isProcessing) return;

    let currentProgress = messageIndex > 0 ? loadingMessages[messageIndex - 1].progress : 0;
    const increment = (targetProgress - currentProgress) / 20;

    progressInterval = setInterval(() => {
        if (!isProcessing) {
            clearInterval(progressInterval);
            return;
        }

        currentProgress += increment;
        if (currentProgress >= targetProgress) {
            currentProgress = targetProgress;
            clearInterval(progressInterval);
        }

        // Update message and emoji for each step, but preserve progress elements
        const existingProgressFill = document.getElementById('progress-fill');
        const existingProgressText = document.getElementById('progress-text');

        debugDiv.innerHTML = `
            <div style="padding: 15px; background: linear-gradient(135deg, rgba(102, 126, 234, 0.1), rgba(118, 75, 162, 0.1)); border-radius: 12px; animation: pulse 2s infinite;">
                <div style="display: flex; align-items: center; gap: 10px; margin-bottom: 10px; min-height: 40px;">
                    <span id="debug-emoji" style="font-size: 24px; animation: debugBounce 1s infinite; display: inline-block; margin: 10px 0;">${currentMessage.emoji}</span>
                    <span id="debug-text" style="font-weight: 500; color: #4a5568;">${currentMessage.text}</span>
                </div>
                <div style="background: rgba(255,255,255,0.3); border-radius: 10px; height: 8px; overflow: hidden;">
                    <div id="progress-fill" style="background: linear-gradient(90deg, #667eea, #764ba2); height: 100%; width: ${currentProgress}%; transition: width 0.3s ease; border-radius: 10px;"></div>
                </div>
                <div id="progress-text" style="text-align: center; margin-top: 5px; font-size: 12px; color: #667eea; font-weight: 600;">${Math.round(currentProgress)}%</div>
            </div>
            <style>
                @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.7; } }
                @keyframes debugBounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-8px); } }
            </style>
        `;

        // Update only progress during interval
        const progressFill = document.getElementById('progress-fill');
        const progressText = document.getElementById('progress-text');
        if (progressFill && progressText) {
            progressFill.style.width = `${currentProgress}%`;
            progressText.textContent = `${Math.round(currentProgress)}%`;
        }

        // Also animate the results div icon with separate style
        resultsDiv.innerHTML = `<div style="text-align: center; padding: 30px 20px; color: #667eea; font-weight: 500;">
            <div style="min-height: 50px; display: flex; align-items: center; justify-content: center; margin-bottom: 10px;">
                <span style="font-size: 32px; animation: loadingBounce 1s infinite; display: inline-block;">🔄</span>
            </div>
            Loading your OnCall data...
            <style>
                @keyframes loadingBounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-8px); } }
            </style>
        </div>`;
    }, 50);
};

const showNextMessage = () => {
    if (messageIndex < loadingMessages.length && isProcessing) {
        const msg = loadingMessages[messageIndex];
        updateProgress(msg.progress, msg);
        messageIndex++;
        messageTimeout = setTimeout(showNextMessage, 1000);
    }
};

showNextMessage();
resultsDiv.innerHTML = `<div style="text-align: center; padding: 30px 20px; color: #667eea; font-weight: 500;">
    <div style="min-height: 50px; display: flex; align-items: center; justify-content: center; margin-bottom: 10px;">
        <span style="font-size: 32px; animation: initialBounce 1s infinite; display: inline-block;">🔄</span>
    </div>
    Loading your OnCall data...
    <style>
        @keyframes initialBounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-8px); } }
    </style>
</div>`;

try {
    const [year, month] = monthValue.split('-').map(num => parseInt(num));
    const startDate = `${year}-${String(month).padStart(2, '0')}-01`;
    const lastDay = new Date(year, month, 0).getDate();
    const endDate = `${year}-${String(month).padStart(2, '0')}-${lastDay}`;

    const teamsResponse = await getUserTeams(loginId);

    if (!teamsResponse || teamsResponse.length === 0) {
        isProcessing = false;
        clearInterval(progressInterval);
        clearTimeout(messageTimeout);
        throw new Error('No teams found for this user');
    }

    const teamNames = teamsResponse.map(team => team.rawTeamName);
    const scheduleUrl = `https://oncall-api.corp.amazon.com/teams/${teamNames.join(',')}/schedules/detailed?memberFilterList=${loginId}&from=${startDate}&to=${endDate}&timeZone=Europe/Berlin`;

    const scheduleResponse = await fetchAPI(scheduleUrl);

    // Store schedule data and enable download button
    window.oncallScheduleData = scheduleResponse;
    const downloadButton = document.getElementById('download-oncall-sheet');
    downloadButton.disabled = false;

    let allData = {};

    scheduleResponse.forEach(entry => {
        if (entry.oncallShift && entry.shiftDetails) {
            const teamName = entry.shiftDetails.teamName;
            const shift = entry.oncallShift;

            if (shift.oncallMember && shift.oncallMember.includes(loginId)) {
                if (!allData[teamName]) {
                    allData[teamName] = [];
                }

                const isDuplicate = allData[teamName].some(existingShift =>
                    existingShift.startDateTime === shift.startDateTime &&
                    existingShift.endDateTime === shift.endDateTime
                );

                if (!isDuplicate) {
                    allData[teamName].push({
                        startDateTime: shift.startDateTime,
                        endDateTime: shift.endDateTime,
                        oncallMember: [loginId],
                        shiftType: shift.shiftType || 'regular'
                    });
                }
            }
        }
    });

    isProcessing = false;
    clearInterval(progressInterval);
    clearTimeout(messageTimeout);
    debugDiv.innerHTML = `
        <div style="padding: 15px; background: linear-gradient(135deg, rgba(39, 174, 96, 0.1), rgba(46, 125, 50, 0.1)); border-radius: 12px;">
            <div style="display: flex; align-items: center; gap: 10px; margin-bottom: 10px;">
                <span style="font-size: 24px; animation: celebration 2s infinite;">🎉</span>
                <span style="font-weight: 600; color: #27ae60;">Success! Data loaded and calendar generated!</span>
            </div>
            <div style="background: rgba(255,255,255,0.3); border-radius: 10px; height: 8px; overflow: hidden;">
                <div style="background: linear-gradient(90deg, #27ae60, #2ecc71); height: 100%; width: 100%; border-radius: 10px;"></div>
            </div>
            <div style="text-align: center; margin-top: 5px; font-size: 12px; color: #27ae60; font-weight: 600;">100% Complete! 🚀</div>
        </div>
        <style>
            @keyframes celebration { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.2); } }
        </style>
    `;

    if (Object.keys(allData).length > 0) {
        let resultsHtml = `
            <div style="font-family: Arial;">
                <div style="display: flex; gap: 20px;">
                    <div style="flex: 1;">
                        ${generateCalendarView(allData, month, year)}
                    </div>
                </div>
            </div>
        `;
        resultsDiv.innerHTML = resultsHtml;
    } else {
        resultsDiv.innerHTML = 'No shifts found for the selected user and period';
        document.getElementById('download-oncall-sheet').disabled = true;
    }
} catch (error) {
    isProcessing = false;
    clearInterval(progressInterval);
    clearTimeout(messageTimeout);

    // Determine error type and show appropriate message
    let errorEmoji = '❌';
    let errorTitle = 'Oops! Something went wrong';
    let errorSuggestion = 'Please try again or check your connection';

    if (error.message.includes('teams')) {
        errorEmoji = '👥';
        errorTitle = 'No teams found';
        errorSuggestion = 'Make sure your Login ID is correct and you\'re part of an OnCall team';
    } else if (error.message.includes('Network')) {
        errorEmoji = '🌐';
        errorTitle = 'Connection issue';
        errorSuggestion = 'Check your internet connection and try again';
    } else if (error.message.includes('API')) {
        errorEmoji = '🔧';
        errorTitle = 'Service temporarily unavailable';
        errorSuggestion = 'The OnCall API might be down. Please try again later';
    }

    debugDiv.innerHTML = `
        <div style="padding: 15px; background: linear-gradient(135deg, rgba(231, 76, 60, 0.1), rgba(192, 57, 43, 0.1)); border-radius: 12px; animation: shake 0.5s;">
            <div style="display: flex; align-items: center; gap: 10px; margin-bottom: 10px;">
                <span style="font-size: 24px; animation: wiggle 1s infinite;">${errorEmoji}</span>
                <span style="font-weight: 600; color: #e74c3c;">${errorTitle}</span>
            </div>
            <div style="background: rgba(255,255,255,0.3); border-radius: 10px; height: 8px; overflow: hidden;">
                <div style="background: linear-gradient(90deg, #e74c3c, #c0392b); height: 100%; width: 100%; border-radius: 10px;"></div>
            </div>
            <div style="text-align: center; margin-top: 8px; font-size: 12px; color: #e74c3c; font-weight: 500;">${errorSuggestion}</div>
        </div>
        <style>
            @keyframes shake { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-5px); } 75% { transform: translateX(5px); } }
            @keyframes wiggle { 0%, 100% { transform: rotate(0deg); } 25% { transform: rotate(-10deg); } 75% { transform: rotate(10deg); } }
        </style>
    `;

    resultsDiv.innerHTML = `
        <div style="text-align: center; padding: 20px; color: #e74c3c; font-weight: 500;">
            <div style="font-size: 48px; margin-bottom: 10px;">😅</div>
            <div>Don't worry, these things happen!</div>
            <small style="color: #666;">Check the info above and give it another try</small>
        </div>`;
    document.getElementById('download-oncall-sheet').disabled = true;
}
}

function injectOnCallButton() {
const panel = document.querySelector(".combined-panel .panel-content");
if (!panel || document.getElementById("oncall-show-btn")) return;
const btn = document.createElement("button");
btn.id = "oncall-show-btn";
btn.className = "action-button";
btn.textContent = "📋 View My OnCall Schedule";
btn.onclick = injectOnCallDialog;
panel.appendChild(btn);
}
// Add this at the top of your script, right after 'use strict'
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initialize);
} else {
initialize();
}
function generateCalendarView(allData, month, year) {
const firstDay = new Date(year, month - 1, 1);
const lastDay = new Date(year, month, 0);
const daysInMonth = lastDay.getDate();

    let calendarHtml = `
        <div style="margin-bottom: 30px; background: linear-gradient(135deg, rgba(255,255,255,0.9), rgba(248,250,252,0.9)); border-radius: 20px; padding: 25px; box-shadow: 0 10px 40px rgba(0,0,0,0.1); backdrop-filter: blur(10px);">
            <h4 style="text-align: center; margin-bottom: 25px; font-family: 'Inter', sans-serif; font-weight: 700; font-size: 24px; color: #2d3748;">📅 ${new Date(year, month - 1).toLocaleString('default', { month: 'long', year: 'numeric' })}</h4>
            <div style="display: grid; grid-template-columns: repeat(7, 1fr); gap: 8px; margin-bottom: 8px;">
                <div style="text-align: center; font-weight: 600; padding: 12px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border-radius: 12px; font-family: 'Inter', sans-serif;">Mon</div>
                <div style="text-align: center; font-weight: 600; padding: 12px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border-radius: 12px; font-family: 'Inter', sans-serif;">Tue</div>
                <div style="text-align: center; font-weight: 600; padding: 12px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border-radius: 12px; font-family: 'Inter', sans-serif;">Wed</div>
                <div style="text-align: center; font-weight: 600; padding: 12px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border-radius: 12px; font-family: 'Inter', sans-serif;">Thu</div>
                <div style="text-align: center; font-weight: 600; padding: 12px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border-radius: 12px; font-family: 'Inter', sans-serif;">Fri</div>
                <div style="text-align: center; font-weight: 600; padding: 12px; background: linear-gradient(135deg, #e74c3c 0%, #c0392b 100%); color: white; border-radius: 12px; font-family: 'Inter', sans-serif;">Sat</div>
                <div style="text-align: center; font-weight: 600; padding: 12px; background: linear-gradient(135deg, #e74c3c 0%, #c0392b 100%); color: white; border-radius: 12px; font-family: 'Inter', sans-serif;">Sun</div>
            </div>
            <div style="display: grid; grid-template-columns: repeat(7, 1fr); gap: 8px;">
    `;

    let firstDayOfWeek = firstDay.getDay() || 7;
    for (let i = 1; i < firstDayOfWeek; i++) {
        calendarHtml += `<div style="padding: 5px; background: #f5f5f5; min-height: 100px;"></div>`;
    }

    function formatTime(dateTimeStr) {
        return new Date(dateTimeStr).toLocaleTimeString('de-DE', {
            hour: '2-digit',
            minute: '2-digit',
            hour12: false,
            timeZone: 'Europe/Berlin'
        });
    }

    function getDateKey(date) {
        return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
    }

    let shiftsByDate = {};
    Object.entries(allData).forEach(([teamName, shifts]) => {
        shifts.forEach(shift => {
            const startDate = new Date(shift.startDateTime);
            const endDate = new Date(shift.endDateTime);

            // Calculate dates for the shift
            const dates = [];
            let currentDate = new Date(startDate);

            // Add all dates between start and end (inclusive)
            while (currentDate <= endDate) {
                if (currentDate.getMonth() === month - 1) {
                    dates.push(new Date(currentDate));
                }
                currentDate.setDate(currentDate.getDate() + 1);
            }

            // Process each date
            dates.forEach((date, index) => {
                const dateKey = getDateKey(date);
                const isWeekend = date.getDay() === 0 || date.getDay() === 6;
                const isMultiDayShift = dates.length > 1;

                // Skip single-day shifts on weekends
                if (isWeekend && !isMultiDayShift) return;

                if (!shiftsByDate[dateKey]) {
                    shiftsByDate[dateKey] = [];
                }

                let timeDisplay;
                const isStartDate = index === 0;
                const isEndDate = index === dates.length - 1;

                if (dates.length === 1) {
                    // Single day shift
                    timeDisplay = `${formatTime(startDate)} → ${formatTime(endDate)}`;
                } else if (isStartDate) {
                    // First day of multi-day shift
                    timeDisplay = `${formatTime(startDate)} → 24:00`;
                } else if (isEndDate) {
                    // Last day of multi-day shift
                    timeDisplay = `00:00 → ${formatTime(endDate)}`;
                } else {
                    // Middle days of multi-day shift
                    timeDisplay = '00:00 → 24:00';
                }

                shiftsByDate[dateKey].push({
                    ...shift,
                    teamName,
                    isMultiDay: isMultiDayShift,
                    displayTime: timeDisplay
                });
            });
        });
    });

    for (let day = 1; day <= daysInMonth; day++) {
        const date = new Date(year, month - 1, day);
        const dateKey = getDateKey(date);
        const isWeekend = date.getDay() === 0 || date.getDay() === 6;
        const shiftsForDay = shiftsByDate[dateKey] || [];

        let consolidatedShifts = {};
        shiftsForDay.forEach(shift => {
            const shiftKey = `${shift.displayTime}`;
            if (!consolidatedShifts[shiftKey]) {
                consolidatedShifts[shiftKey] = {
                    time: shift.displayTime,
                    teams: [shift.teamName],
                    isMultiDay: shift.isMultiDay
                };
            } else if (!consolidatedShifts[shiftKey].teams.includes(shift.teamName)) {
                consolidatedShifts[shiftKey].teams.push(shift.teamName);
            }
        });

        calendarHtml += `
            <div style="padding: 12px; background: ${isWeekend ? 'linear-gradient(135deg, rgba(231, 76, 60, 0.05), rgba(192, 57, 43, 0.05))' : 'rgba(255,255,255,0.8)'};
                        min-height: 120px; border-radius: 12px; border: 1px solid ${isWeekend ? 'rgba(231, 76, 60, 0.2)' : 'rgba(226, 232, 240, 0.5)'}; overflow-y: auto; transition: all 0.3s ease;">
                <div style="font-weight: 700; margin-bottom: 8px; color: ${isWeekend ? '#e74c3c' : '#2d3748'}; font-family: 'Inter', sans-serif; font-size: 16px;">
                    ${day}
                </div>
                ${Object.values(consolidatedShifts).map(shift => `
                    <div style="margin-bottom: 6px; padding: 8px;
                                background: ${shift.isMultiDay ? 'linear-gradient(135deg, rgba(102, 126, 234, 0.1), rgba(118, 75, 162, 0.1))' : (isWeekend ? 'rgba(231, 76, 60, 0.1)' : 'rgba(248, 250, 252, 0.8)')};
                                border-radius: 8px; font-size: 11px; font-family: 'Inter', sans-serif;
                                ${shift.isMultiDay ? 'border-left: 3px solid #667eea;' : 'border: 1px solid rgba(226, 232, 240, 0.5);'}
                                transition: all 0.2s ease;">
                        <div style="color: #667eea; font-weight: 600; margin-bottom: 2px;">${shift.teams.join(', ')}</div>
                        <div style="color: #4a5568; font-weight: 500;">${shift.time}</div>
                    </div>
                `).join('')}
            </div>
        `;
    }

    calendarHtml += '</div></div></div>';
    return calendarHtml;
}
function initialize() {
// Wrap the initialization code in a try-catch block
try {
let attempts = 0;
const maxAttempts = 30;

    function tryInit() {
        attempts++;
        console.log(`Initialization attempt ${attempts}`);

        const table = document.querySelector('table[data-test-component="StencilTable"]');
        if (table) {
            console.log('Table found, starting script');
            processTable();
            return;
        }

        if (attempts < maxAttempts) {
            setTimeout(tryInit, 1000);
        } else {
            console.log('Max attempts reached, trying alternative initialization...');
            const altTable = document.querySelector('table');
            if (altTable) {
                console.log('Found table with alternative selector, starting script');
                processTable();
            } else {
                console.log('Script initialization failed completely');
            }
        }
    }

    setTimeout(tryInit, 2000);
} catch (error) {
    console.error('Error during initialization:', error);
}
}

// SECOND TEST 1: Adding more comments
// SECOND TEST 2: Verifying code updates work
// SECOND TEST 3: This is the second batch
// SECOND TEST 4: File modification test
// SECOND TEST 5: End of file comments
// UPDATED: Fixed Excel output with Notes column and continuous shift handling

})();