async function copyText(kind, value, openUrl = "") {
    if (!value) {
        showToast(`No ${kind.toLowerCase()} yet.`, "warning");
        return;
    }
    try {
        await navigator.clipboard.writeText(value);
        showToast(`${kind} copied to clipboard.`);
        setStatus(`Copied ${kind.toLowerCase()}`);
    } catch (_) {
        showCopyFallback(kind, value, openUrl);
    }
}

function showCopyFallback(kind, value, openUrl) {
    const openLink = openUrl ? `<a class="win98-button" href="${htmlEscape(openUrl)}" target="_blank" rel="noreferrer">Open</a>` : "";
    showTemplatePopup(`${kind} copy failed`, "copy-failed", {
        value: htmlEscape(value),
        openLink,
    });
}

function quotaWarningHtml(message) {
    const tooLarge = oversizedFiles();
    const parts = [];
    if (tooLarge.length) {
        parts.push("<p class=\"quota-dialog-summary\"><strong>Single-file limit exceeded.</strong> Remove these files before uploading.</p>");
        parts.push(`<ol class="quota-dialog-list">${tooLarge.map((item) => `<li><strong>${htmlEscape(item.displayName)}</strong> <span>${formatBytes(item.file.size)} / max ${formatBytes(maxFileBytes)}</span></li>`).join("")}</ol>`);
    }
    if (isOverBoxQuota()) {
        parts.push(`<p class="quota-dialog-summary"><strong>Box quota exceeded.</strong> Current total is ${formatBytes(totalBytes())}. The limit is ${formatBytes(maxBoxBytes)}. Remove ${formatBytes(totalBytes() - maxBoxBytes)} or more.</p>`);
    }
    if (!parts.length) parts.push(`<p>${htmlEscape(message)}</p>`);
    return parts.join("");
}

function showWarningDialog(title, message) {
    showTemplatePopup(title, "warning", {
        title: htmlEscape(title),
        content: quotaWarningHtml(message),
    });
}

function openPopup(title, html, about = false) {
    window.WarpBoxUI.openPopup(title, html, {
        about,
        popup: el.docPopup,
        title: el.docPopupTitle,
        body: el.docPopupBody,
        backdrop: el.modalBackdrop,
    });
}

function closeDoc() {
    window.WarpBoxUI.closePopup({ popup: el.docPopup, backdrop: el.modalBackdrop });
}

async function showTemplatePopup(title, templateName, data = {}, about = false) {
    try {
        const html = await window.WBPopups.renderTemplate(templateName, data);
        openPopup(title, html, about);
    } catch (error) {
        showToast(error.message || `Could not load ${title}.`, "error");
    }
}

function popupTemplateData(name) {
    const data = { origin: window.location.origin };
    if (name !== "dailyQuota") return data;
    return {
        ...data,
        boxLimit: maxBoxBytes ? formatBytes(maxBoxBytes) : "No configured limit",
        boxPercent: maxBoxBytes ? Math.min(100, Math.round((totalBytes() / maxBoxBytes) * 100)) : 0,
        fileLimit: maxFileBytes ? formatBytes(maxFileBytes) : "No configured limit",
        filePercent: oversizedFiles().length ? 100 : 0,
    };
}

async function openDoc(name) {
    try {
        const doc = await window.WBPopups.renderDoc(name, popupTemplateData(name));
        if (!doc) return;
        openPopup(doc.title, doc.html, doc.about);
        setStatus(`${doc.title} opened`);
    } catch (error) {
        showToast(error.message || "Could not load help window.", "error");
    }
}
