<script>
    /* ------------------------------------------------------------------------
       Date-relative event generator
       The calendar populates itself with events spread across the CURRENT
       month every time the page loads. So whether someone opens this template
       in May 2026 or March 2030, the demo always shows a populated month with
       past, present, and upcoming events.
       ------------------------------------------------------------------------ */

    document.addEventListener('DOMContentLoaded', function () {
        const calendarEl = document.getElementById('calendar');
        if (!calendarEl) return;

        const events = buildEvents(new Date());
        renderDeadlineList(events);

        const calendar = new FullCalendar.Calendar(calendarEl, {
            initialView: 'dayGridMonth',
            headerToolbar: {
                left: 'prev,next today',
                center: 'title',
                right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek',
            },
            height: 'auto',
            events: events,
            eventDisplay: 'block',
            displayEventTime: true,
            dayMaxEvents: 3,
            moreLinkText: 'more',
            navLinks: true,
            nowIndicator: true,
            /* v7 generates hashed internal class names, so CoolAdmin styling
               hooks in through the public *Class options instead of guessing
               at them. These stay stable across FullCalendar patch releases. */
            dayHeaderInnerClass: 'ca-fc-day-header',
            dayCellTopInnerClass: 'ca-fc-day-number',
            eventTimeFormat: { hour: 'numeric', minute: '2-digit', meridiem: 'short' },
            eventClick: function (info) {
                info.jsEvent.preventDefault();
                const e = info.event;
                const start = e.start ? e.start.toLocaleString(undefined, {
                    weekday: 'short', month: 'short', day: 'numeric',
                    hour: 'numeric', minute: '2-digit',
                }) : '';
                const end = e.end ? e.end.toLocaleString(undefined, {
                    hour: 'numeric', minute: '2-digit',
                }) : '';
                /* Demo feedback — swap for your own detail view / modal. */
                if (window.toast) {
                    window.toast.info(end ? start + ' – ' + end : start, e.title);
                }
            },
            /* v7 removed the `windowResize` option — the calendar now tracks
               container size itself, so no manual updateSize() call is needed. */
        });
        calendar.render();
        window.calendarInstance = calendar;
    });

    /* Generate ~20 events spread across the current month — recurring weekly
       items + a few date-relative anchors so the month always looks alive. */
    function buildEvents(today) {
        const y = today.getFullYear();
        const m = today.getMonth();
        const ymd = (d) => d.getFullYear() + '-' +
            String(d.getMonth() + 1).padStart(2, '0') + '-' +
            String(d.getDate()).padStart(2, '0');
        const ymdt = (d, h, mm) => ymd(d) + 'T' +
            String(h).padStart(2, '0') + ':' +
            String(mm || 0).padStart(2, '0') + ':00';
        const at = (date, h, mm) => new Date(date.getFullYear(), date.getMonth(), date.getDate(), h, mm || 0);
        const sameMonth = (d) => d.getMonth() === m && d.getFullYear() === y;
        const offset = (n) => {
            const d = new Date(today);
            d.setDate(today.getDate() + n);
            return d;
        };
        const nthDow = (n, dow) => {
            const d = new Date(y, m, 1);
            let count = 0;
            while (d.getMonth() === m) {
                if (d.getDay() === dow) {
                    count++;
                    if (count === n) return new Date(d);
                }
                d.setDate(d.getDate() + 1);
            }
            return null;
        };
        const lastDow = (dow) => {
            const d = new Date(y, m + 1, 0);
            while (d.getDay() !== dow) d.setDate(d.getDate() - 1);
            return d;
        };

        const TAG_COLORS = {
            meeting:      { bg: '#eaf0fc', fg: '#4272d7' },  /* brand blue */
            task:         { bg: '#e0f3f1', fg: '#0d8780' },  /* teal */
            presentation: { bg: '#fff1e6', fg: '#d45f0a' },  /* warm orange */
            deadline:     { bg: '#fef2f2', fg: '#dc2626' },  /* red */
            personal:     { bg: '#fce7f3', fg: '#be185d' },  /* magenta */
        };

        /* FullCalendar 7 replaced the per-event backgroundColor/borderColor/
           textColor trio with `color` (fill) + `contrastColor` (text). */
        const e = (title, start, end, allDay, tag) => ({
            title,
            start,
            end,
            allDay,
            color: TAG_COLORS[tag].bg,
            contrastColor: TAG_COLORS[tag].fg,
            extendedProps: { type: tag },
        });

        const events = [];

        // 1. Recurring daily standup — every weekday, 9:00–9:15
        const cur = new Date(y, m, 1);
        while (cur.getMonth() === m) {
            const dow = cur.getDay();
            if (dow >= 1 && dow <= 5) {
                events.push(e('Team standup', ymdt(cur, 9, 0), ymdt(cur, 9, 15), false, 'meeting'));
            }
            cur.setDate(cur.getDate() + 1);
        }

        // 2. Sprint planning — first Monday, 10:00–11:30
        const sp = nthDow(1, 1);
        if (sp) events.push(e('Sprint planning', ymdt(sp, 10, 0), ymdt(sp, 11, 30), false, 'meeting'));

        // 3. Sprint retro — last Friday, 15:00–16:30
        const retro = lastDow(5);
        events.push(e('Sprint retro', ymdt(retro, 15, 0), ymdt(retro, 16, 30), false, 'meeting'));

        // 4. 1:1 with manager — every other Tuesday, 14:00
        const firstTue = nthDow(1, 2);
        if (firstTue) {
            for (let week = 0; week < 5; week += 2) {
                const d = new Date(firstTue);
                d.setDate(d.getDate() + week * 7);
                if (!sameMonth(d)) break;
                events.push(e('1:1 with manager', ymdt(d, 14, 0), ymdt(d, 14, 30), false, 'meeting'));
            }
        }

        // 5. Town hall — 3rd Thursday, 16:00–17:00
        const th = nthDow(3, 4);
        if (th) events.push(e('All-hands town hall', ymdt(th, 16, 0), ymdt(th, 17, 0), false, 'presentation'));

        // 6. Today (or next weekday) — Design review with stakeholders
        let t0 = new Date(today);
        if (t0.getDay() === 0) t0 = offset(1);
        if (t0.getDay() === 6) t0 = offset(2);
        if (sameMonth(t0)) {
            events.push(e('Design review with stakeholders', ymdt(t0, 11, 0), ymdt(t0, 12, 30), false, 'presentation'));
        }

        // 7. Today + 2 — Customer interviews (pricing)
        const t2 = offset(2);
        if (sameMonth(t2)) events.push(e('Customer interviews — pricing', ymdt(t2, 13, 0), ymdt(t2, 14, 0), false, 'task'));

        // 8. Today + 4 — Client demo (Acme)
        const t4 = offset(4);
        if (sameMonth(t4)) events.push(e('Client demo — Acme', ymdt(t4, 14, 0), ymdt(t4, 15, 30), false, 'presentation'));

        // 9. Today + 7 — Code freeze (all-day)
        const t7 = offset(7);
        if (sameMonth(t7)) events.push(e('Code freeze', ymd(t7), null, true, 'deadline'));

        // 10. Today + 12 — Q2 product launch (all-day)
        const t12 = offset(12);
        if (sameMonth(t12)) events.push(e('Q2 product launch', ymd(t12), null, true, 'presentation'));

        // 11. Today − 5 — Brand kickoff (past event)
        const tn5 = offset(-5);
        if (sameMonth(tn5)) events.push(e('Brand kickoff', ymdt(tn5, 10, 30), ymdt(tn5, 12, 0), false, 'meeting'));

        // 12. Today − 9 — Quarterly OKR review (past, all-day)
        const tn9 = offset(-9);
        if (sameMonth(tn9)) events.push(e('Quarterly OKR review', ymd(tn9), null, true, 'deadline'));

        // 13. Mid-month all-day team offsite (15th, or last day if month is short)
        const lastDayOfMonth = new Date(y, m + 1, 0).getDate();
        const offsiteDay = Math.min(15, lastDayOfMonth);
        const offsite = new Date(y, m, offsiteDay);
        events.push(e('Team strategy offsite', ymd(offsite), null, true, 'task'));

        // 14. Personal — gym (twice a week, Mon + Wed evenings, 18:30)
        const cursor = new Date(y, m, 1);
        while (cursor.getMonth() === m) {
            if (cursor.getDay() === 1 || cursor.getDay() === 3) {
                events.push(e('Gym', ymdt(cursor, 18, 30), ymdt(cursor, 19, 30), false, 'personal'));
            }
            cursor.setDate(cursor.getDate() + 1);
        }

        // 15. Friday afternoon coffee chat (every Friday, 16:30)
        const cof = new Date(y, m, 1);
        while (cof.getMonth() === m) {
            if (cof.getDay() === 5) {
                events.push(e('Coffee with the team', ymdt(cof, 16, 30), ymdt(cof, 17, 0), false, 'personal'));
            }
            cof.setDate(cof.getDate() + 1);
        }

        return events;
    }

    /* Populate the sidebar "Upcoming events" list with the next 6 events
       starting from today (or today onward), sorted ascending. */
    function renderDeadlineList(allEvents) {
        const container = document.querySelector('.deadline-list');
        if (!container) return;

        const todayISO = new Date();
        todayISO.setHours(0, 0, 0, 0);
        const upcoming = allEvents
            .map((ev) => ({ ev, start: new Date(ev.start) }))
            .filter((x) => x.start >= todayISO)
            .sort((a, b) => a.start - b.start)
            .slice(0, 6);

        container.innerHTML = '';
        upcoming.forEach(({ ev, start }) => {
            const day = start.getDate();
            const month = start.toLocaleDateString(undefined, { month: 'short' });
            const meta = ev.allDay ? 'All day' : start.toLocaleTimeString(undefined, {
                hour: 'numeric', minute: '2-digit', hour12: true,
            });
            const li = document.createElement('li');
            const dateBox = document.createElement('div');
            dateBox.className = 'deadline-list__date';
            dateBox.innerHTML = '<strong>' + String(day).padStart(2, '0') + '</strong><span>' + month + '</span>';
            const body = document.createElement('div');
            body.className = 'deadline-list__body';
            const title = document.createElement('p');
            title.className = 'deadline-list__title';
            title.textContent = ev.title;
            const project = document.createElement('span');
            project.className = 'deadline-list__project';
            project.textContent = meta;
            body.append(title, project);
            li.append(dateBox, body);
            container.appendChild(li);
        });

        if (upcoming.length === 0) {
            container.innerHTML = '<li style="padding:14px 0; color: var(--m-text-faint); font-size: 13px;">No upcoming events.</li>';
        }
    }

    /* "Add event" button in the page header */
    function addNewEvent() {
        const title = prompt('Event title:');
        if (!title || !window.calendarInstance) return;
        window.calendarInstance.addEvent({
            title,
            start: new Date(),
            color: '#eaf0fc',
            contrastColor: '#4272d7',
            extendedProps: { type: 'custom' },
        });
    }
    </script>
