/**
 * Address book modal — list / search / edit / delete contacts.
 * Sources: 'sent' (added on outgoing), 'received' (seeded from message senders),
 * 'manual' (added directly here), 'google' (Google Contacts sync).
 */
import { listContacts, upsertContact, deleteContact } from "../lib/api-client.js";
/** Editable card fields, in the order they appear in the edit dialog.
 *  `multiline` gets a textarea; `type` feeds the input element. */
const CONTACT_FIELDS = [
    { key: "organization", label: "Company" },
    { key: "title", label: "Job title" },
    { key: "phone", label: "Phone", type: "tel" },
    { key: "website", label: "Website", type: "url", placeholder: "https://" },
    { key: "birthday", label: "Birthday", placeholder: "YYYY-MM-DD or --MM-DD" },
    { key: "address", label: "Address", multiline: true },
    { key: "notes", label: "Notes", multiline: true },
];
let isOpen = false;
export async function openAddressBook(prefillSearch) {
    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">Address Book</span>
            <button type="button" class="mailx-modal-close" id="ab-close" title="Close (Esc)" aria-label="Close">&times;</button>
        </div>
        <div class="ab-toolbar">
            <input type="search" id="ab-search" class="mailx-modal-input" placeholder="Search name or email…" autocomplete="off">
            <button type="button" class="mailx-modal-btn mailx-modal-btn-primary" id="ab-new">+ New contact</button>
        </div>
        <div class="ab-count" id="ab-count"></div>
        <div class="ab-list" id="ab-list">Loading…</div>
        <div class="mailx-modal-buttons">
            <span class="mailx-modal-spacer"></span>
            <button type="button" class="mailx-modal-btn" data-action="close">Close</button>
        </div>`;
    backdrop.appendChild(panel);
    document.body.appendChild(backdrop);
    const searchInput = panel.querySelector("#ab-search");
    const listEl = panel.querySelector("#ab-list");
    const countEl = panel.querySelector("#ab-count");
    let editingEmail = null;
    const render = (items, total) => {
        countEl.textContent = total === items.length
            ? `${total} contact${total === 1 ? "" : "s"}`
            : `Showing ${items.length} of ${total}`;
        if (items.length === 0) {
            listEl.innerHTML = `<div class="ab-empty">No contacts match.</div>`;
            return;
        }
        const fmtDate = (ms) => {
            if (!ms)
                return "";
            const d = new Date(ms);
            const now = new Date();
            return d.getFullYear() === now.getFullYear()
                ? d.toLocaleDateString(undefined, { month: "short", day: "numeric" })
                : d.toLocaleDateString();
        };
        listEl.innerHTML = `
            <div class="ab-row ab-header">
                <span class="ab-name">Name</span>
                <span class="ab-email">Email</span>
                <span class="ab-source">Source</span>
                <span class="ab-count-cell" title="Times sent to">×</span>
                <span class="ab-last">Last</span>
                <span class="ab-actions"></span>
            </div>` + items.map(c => `
            <div class="ab-row" data-email="${escapeAttr(c.email)}">
                <span class="ab-name" title="${escapeAttr(cardSummary(c))}">${escapeHtml(c.name || "")}${cardSummary(c) ? ' <span class="ab-hascard" aria-hidden="true">•</span>' : ""}</span>
                <span class="ab-email">${escapeHtml(c.email)}</span>
                <span class="ab-source">${escapeHtml(c.source)}</span>
                <span class="ab-count-cell">${c.useCount || 0}</span>
                <span class="ab-last">${fmtDate(c.lastUsed)}</span>
                <span class="ab-actions">
                    <button type="button" class="ab-edit" title="Edit contact">✎</button>
                    <button type="button" class="ab-del" title="Delete">🗑</button>
                    <button type="button" class="ab-mail" title="Compose to">✉</button>
                </span>
            </div>`).join("");
        listEl.querySelectorAll(".ab-row[data-email]").forEach(row => {
            const email = row.dataset.email;
            const c = items.find(x => x.email === email);
            row.querySelector(".ab-edit")?.addEventListener("click", () => beginEdit(row, c));
            row.querySelector(".ab-del")?.addEventListener("click", () => doDelete(c));
            row.querySelector(".ab-mail")?.addEventListener("click", () => composeTo(c));
        });
    };
    // Edit opens the whole card, not just the name. The inline name-only input
    // this replaced was the only editor there was, which is why phone, company,
    // address and the rest had nowhere to be typed even once the store could
    // hold them (Bob 2026-08-07: "extend the contact support for all fields").
    const beginEdit = (_row, c) => {
        if (editingEmail === c.email)
            return;
        editingEmail = c.email;
        const back = document.createElement("div");
        back.className = "mailx-modal-backdrop";
        const card = document.createElement("div");
        card.className = "mailx-modal";
        card.innerHTML = `
            <div class="mailx-modal-title">
                <span class="mailx-modal-title-text">Edit contact</span>
                <button type="button" class="mailx-modal-close" data-role="x" title="Close (Esc)" aria-label="Close">&times;</button>
            </div>
            <div class="ab-card">
                <label class="ab-field"><span>Name</span>
                    <input type="text" class="mailx-modal-input" data-field="name" value="${escapeAttr(c.name || "")}"></label>
                <label class="ab-field"><span>Email</span>
                    <input type="email" class="mailx-modal-input" value="${escapeAttr(c.email)}" disabled
                           title="The address identifies the contact — delete and re-add to change it"></label>
                ${CONTACT_FIELDS.map(f => `
                <label class="ab-field"><span>${escapeHtml(f.label)}</span>
                    ${f.multiline
            ? `<textarea class="mailx-modal-input" rows="2" data-field="${f.key}">${escapeHtml(c[f.key] || "")}</textarea>`
            : `<input type="${f.type || "text"}" class="mailx-modal-input" data-field="${f.key}"
                                  value="${escapeAttr(c[f.key] || "")}"
                                  ${f.placeholder ? `placeholder="${escapeAttr(f.placeholder)}"` : ""}>`}
                </label>`).join("")}
            </div>
            <div class="mailx-modal-buttons">
                <span class="mailx-modal-spacer"></span>
                <button type="button" class="mailx-modal-btn" data-role="cancel">Cancel</button>
                <button type="button" class="mailx-modal-btn mailx-modal-btn-primary" data-role="save">Save</button>
            </div>`;
        back.appendChild(card);
        document.body.appendChild(back);
        card.querySelector('[data-field="name"]')?.focus();
        const shut = () => {
            back.remove();
            document.removeEventListener("keydown", onCardKey, true);
            editingEmail = null;
        };
        // Capture phase + stopPropagation so Escape closes THIS dialog and not
        // the address book behind it.
        const onCardKey = (e) => {
            if (e.key === "Escape") {
                e.stopPropagation();
                e.preventDefault();
                shut();
            }
        };
        document.addEventListener("keydown", onCardKey, true);
        card.querySelector('[data-role="x"]')?.addEventListener("click", shut);
        card.querySelector('[data-role="cancel"]')?.addEventListener("click", shut);
        back.addEventListener("mousedown", (e) => { if (e.target === back)
            shut(); });
        card.querySelector('[data-role="save"]')?.addEventListener("click", async () => {
            const val = (k) => card.querySelector(`[data-field="${k}"]`)?.value.trim() ?? "";
            const fields = {};
            for (const f of CONTACT_FIELDS)
                fields[f.key] = val(f.key);
            const newName = val("name");
            const bd = fields.birthday;
            if (bd && !/^(\d{4}|-)-\d{2}-\d{2}$/.test(bd)) {
                alert(`Birthday must be YYYY-MM-DD, or --MM-DD when the year is unknown. Got "${bd}".`);
                return;
            }
            try {
                await upsertContact(newName, c.email, fields);
                shut();
                await reload();
            }
            catch (e) {
                alert(`Update failed: ${e?.message || e}`);
            }
        });
    };
    const doDelete = async (c) => {
        if (!confirm(`Delete contact "${c.name || c.email}"?`))
            return;
        try {
            await deleteContact(c.email);
            await reload();
        }
        catch (e) {
            alert(`Delete failed: ${e?.message || e}`);
        }
    };
    const composeTo = (c) => {
        const init = {
            mode: "new",
            to: [{ name: c.name || "", address: c.email }],
            cc: [], bcc: [], subject: "", bodyHtml: "",
            inReplyTo: "", references: [], accounts: [],
        };
        try {
            sessionStorage.setItem("composeInit", JSON.stringify(init));
        }
        catch { /* */ }
        document.dispatchEvent(new CustomEvent("mailx-compose", { detail: { mode: "new" } }));
        close();
    };
    let reloadDebounce;
    const reload = async () => {
        try {
            const r = await listContacts(searchInput.value, 1, 200);
            render(r.items, r.total);
        }
        catch (e) {
            listEl.innerHTML = `<div class="ab-empty">Load failed: ${escapeHtml(e?.message || String(e))}</div>`;
        }
    };
    const scheduleReload = () => {
        if (reloadDebounce)
            window.clearTimeout(reloadDebounce);
        reloadDebounce = window.setTimeout(reload, 200);
    };
    panel.querySelector("#ab-new")?.addEventListener("click", async () => {
        const email = prompt("Email address:");
        if (!email)
            return;
        const name = prompt("Display name (optional):") || "";
        try {
            await upsertContact(name, email.trim());
            await reload();
        }
        catch (e) {
            alert(`Add failed: ${e?.message || e}`);
        }
    });
    searchInput.addEventListener("input", scheduleReload);
    // "Open in contacts" from the viewer's address right-click lands here with
    // the address prefilled, so the list opens already filtered to that person.
    if (prefillSearch)
        searchInput.value = prefillSearch;
    const close = () => {
        if (reloadDebounce)
            window.clearTimeout(reloadDebounce);
        backdrop.remove();
        document.removeEventListener("keydown", onKey, true);
        isOpen = false;
    };
    const onKey = (e) => {
        if (e.key === "Escape") {
            e.stopPropagation();
            e.preventDefault();
            close();
        }
    };
    document.addEventListener("keydown", onKey, true);
    panel.querySelector("#ab-close").addEventListener("click", close);
    panel.querySelector('[data-action="close"]').addEventListener("click", close);
    backdrop.addEventListener("mousedown", (e) => { if (e.target === backdrop)
        close(); });
    await reload();
}
/** One-line digest of the card fields that are filled in — the row is too
 *  narrow for seven more columns, so this rides as the name's tooltip and
 *  drives the • marker that says "there is more here than a name". */
function cardSummary(c) {
    return CONTACT_FIELDS
        .map(f => ({ label: f.label, value: (c[f.key] || "").trim() }))
        .filter(x => x.value)
        .map(x => `${x.label}: ${x.value.replace(/\s+/g, " ")}`)
        .join("\n");
}
function escapeHtml(s) {
    return s.replace(/[&<>"']/g, c => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", "\"": "&quot;", "'": "&#39;" }[c]));
}
function escapeAttr(s) { return escapeHtml(s); }
//# sourceMappingURL=address-book.js.map