/**
 * Calendar pane — Thunderbird Lightning "Today Pane" style.
 *
 * Phase-1 scope (this commit): a usable mini-month + upcoming-events list
 * sourced from a local-only event store. Google Calendar sync is a separate
 * step (oauthsupport scope is already wired; the dispatcher branch + provider
 * are owed). UI lands first so the data layer can be slotted in without
 * UX rework.
 */

interface CalEvent {
    id: string;
    title: string;
    start: number;        // ms since epoch
    end: number;
    allDay?: boolean;
    location?: string;
    notes?: string;
    source?: "local" | "google";
}

const LOCAL_STORE_KEY = "mailx-cal-events-v1";
let isOpen = false;

function loadEvents(): CalEvent[] {
    try {
        const raw = localStorage.getItem(LOCAL_STORE_KEY);
        if (!raw) return [];
        const arr = JSON.parse(raw);
        return Array.isArray(arr) ? arr : [];
    } catch { return []; }
}
function saveEvents(events: CalEvent[]): void {
    try { localStorage.setItem(LOCAL_STORE_KEY, JSON.stringify(events)); } catch { /* */ }
}

export async function openCalendar(): Promise<void> {
    if (isOpen) return;
    isOpen = true;

    const backdrop = document.createElement("div");
    backdrop.className = "mailx-modal-backdrop";
    const panel = document.createElement("div");
    panel.className = "mailx-modal mailx-modal-wide";
    panel.innerHTML = `
        <div class="mailx-modal-title">
            <span class="mailx-modal-title-text">Calendar</span>
            <button type="button" class="mailx-modal-close" id="cal-close" title="Close (Esc)" aria-label="Close">&times;</button>
        </div>
        <div class="cal-grid">
            <div class="cal-month" id="cal-month"></div>
            <div class="cal-upcoming">
                <div class="cal-section-title">Upcoming</div>
                <div id="cal-events"></div>
                <button type="button" class="mailx-modal-btn mailx-modal-btn-primary" id="cal-new" style="margin-top:12px;">+ New event</button>
            </div>
        </div>
        <div class="mailx-modal-buttons">
            <span class="mailx-modal-spacer"></span>
            <span class="cal-source-note">Local-only · Google Calendar sync pending</span>
            <button type="button" class="mailx-modal-btn" data-action="close">Close</button>
        </div>`;
    backdrop.appendChild(panel);
    document.body.appendChild(backdrop);

    const monthEl = panel.querySelector<HTMLElement>("#cal-month")!;
    const eventsEl = panel.querySelector<HTMLElement>("#cal-events")!;

    let viewYear = new Date().getFullYear();
    let viewMonth = new Date().getMonth();
    let selectedDay = new Date();
    let events = loadEvents();

    const renderMonth = () => {
        const first = new Date(viewYear, viewMonth, 1);
        const lastDay = new Date(viewYear, viewMonth + 1, 0).getDate();
        const firstWeekday = first.getDay();
        const monthName = first.toLocaleDateString(undefined, { month: "long", year: "numeric" });
        const today = new Date();
        const isToday = (y: number, m: number, d: number) =>
            y === today.getFullYear() && m === today.getMonth() && d === today.getDate();
        const eventsByDay = new Map<string, CalEvent[]>();
        for (const e of events) {
            const d = new Date(e.start);
            const k = `${d.getFullYear()}-${d.getMonth()}-${d.getDate()}`;
            const arr = eventsByDay.get(k) || [];
            arr.push(e);
            eventsByDay.set(k, arr);
        }
        let html = `
            <div class="cal-nav">
                <button type="button" class="cal-nav-btn" data-nav="prev">‹</button>
                <span class="cal-nav-title">${monthName}</span>
                <button type="button" class="cal-nav-btn" data-nav="today">Today</button>
                <button type="button" class="cal-nav-btn" data-nav="next">›</button>
            </div>
            <div class="cal-month-grid">
                ${["S","M","T","W","T","F","S"].map(d => `<span class="cal-dow">${d}</span>`).join("")}`;
        for (let i = 0; i < firstWeekday; i++) html += `<span class="cal-day cal-day-blank"></span>`;
        for (let d = 1; d <= lastDay; d++) {
            const k = `${viewYear}-${viewMonth}-${d}`;
            const hasEv = eventsByDay.has(k);
            const sel = selectedDay.getFullYear() === viewYear && selectedDay.getMonth() === viewMonth && selectedDay.getDate() === d;
            const cls = ["cal-day"];
            if (isToday(viewYear, viewMonth, d)) cls.push("cal-day-today");
            if (sel) cls.push("cal-day-selected");
            if (hasEv) cls.push("cal-day-has-event");
            html += `<button type="button" class="${cls.join(" ")}" data-day="${d}">${d}</button>`;
        }
        html += `</div>`;
        monthEl.innerHTML = html;
        monthEl.querySelectorAll<HTMLButtonElement>("[data-day]").forEach(b => {
            b.addEventListener("click", () => {
                selectedDay = new Date(viewYear, viewMonth, +b.dataset.day!);
                renderMonth();
                renderEvents();
            });
        });
        monthEl.querySelectorAll<HTMLButtonElement>(".cal-nav-btn").forEach(b => {
            b.addEventListener("click", () => {
                const nav = b.dataset.nav;
                if (nav === "prev") {
                    if (--viewMonth < 0) { viewMonth = 11; viewYear--; }
                } else if (nav === "next") {
                    if (++viewMonth > 11) { viewMonth = 0; viewYear++; }
                } else if (nav === "today") {
                    const t = new Date();
                    viewYear = t.getFullYear(); viewMonth = t.getMonth(); selectedDay = t;
                }
                renderMonth();
                renderEvents();
            });
        });
    };

    const renderEvents = () => {
        const dayStart = new Date(selectedDay.getFullYear(), selectedDay.getMonth(), selectedDay.getDate()).getTime();
        const horizon = dayStart + 30 * 86400_000;
        const upcoming = events
            .filter(e => e.start >= dayStart && e.start < horizon)
            .sort((a, b) => a.start - b.start);
        if (upcoming.length === 0) {
            eventsEl.innerHTML = `<div class="cal-empty">No events in the next 30 days from ${selectedDay.toLocaleDateString()}.</div>`;
            return;
        }
        const fmt = (e: CalEvent) => {
            const d = new Date(e.start);
            const date = d.toLocaleDateString(undefined, { weekday: "short", month: "short", day: "numeric" });
            const time = e.allDay ? "all day" : d.toLocaleTimeString(undefined, { hour: "numeric", minute: "2-digit" });
            return `${date} · ${time}`;
        };
        eventsEl.innerHTML = upcoming.map(e => `
            <div class="cal-event" data-id="${e.id}">
                <div class="cal-event-time">${fmt(e)}</div>
                <div class="cal-event-title">${escapeHtml(e.title)}</div>
                ${e.location ? `<div class="cal-event-loc">${escapeHtml(e.location)}</div>` : ""}
                <button type="button" class="cal-event-del" title="Delete">×</button>
            </div>`).join("");
        eventsEl.querySelectorAll<HTMLElement>(".cal-event").forEach(row => {
            row.querySelector(".cal-event-del")?.addEventListener("click", () => {
                const id = row.dataset.id!;
                events = events.filter(e => e.id !== id);
                saveEvents(events);
                renderEvents();
                renderMonth();
            });
        });
    };

    panel.querySelector<HTMLButtonElement>("#cal-new")?.addEventListener("click", () => {
        const title = prompt("Event title:");
        if (!title) return;
        const dateStr = prompt(
            "Date and time (YYYY-MM-DD HH:MM, or YYYY-MM-DD for all-day):",
            selectedDay.toISOString().slice(0, 10) + " 09:00"
        );
        if (!dateStr) return;
        const allDay = !/\d{1,2}:\d{2}/.test(dateStr);
        const start = Date.parse(dateStr.replace(" ", "T"));
        if (isNaN(start)) { alert("Couldn't parse that date."); return; }
        const ev: CalEvent = {
            id: `cal-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
            title, start, end: start + (allDay ? 86400_000 : 3600_000),
            allDay, source: "local",
        };
        events.push(ev);
        saveEvents(events);
        renderMonth();
        renderEvents();
    });

    const close = () => {
        backdrop.remove();
        document.removeEventListener("keydown", onKey, true);
        isOpen = false;
    };
    const onKey = (e: KeyboardEvent) => {
        if (e.key === "Escape") { e.stopPropagation(); e.preventDefault(); close(); }
    };
    document.addEventListener("keydown", onKey, true);
    panel.querySelector<HTMLButtonElement>("#cal-close")!.addEventListener("click", close);
    panel.querySelector<HTMLButtonElement>('[data-action="close"]')!.addEventListener("click", close);
    backdrop.addEventListener("mousedown", (e) => { if (e.target === backdrop) close(); });

    renderMonth();
    renderEvents();
}

function escapeHtml(s: string): string {
    return s.replace(/[&<>"']/g, c => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", "\"": "&quot;", "'": "&#39;" }[c]!));
}
