///////////////////////////////////////////////////////////////////////////////
// domainActions.js
// Handles footer action buttons for the domain portfolio tool.
// Dependencies (globals): API_BASE_URL, DataTableView, _categories,
//                         _domainMembershipMap
///////////////////////////////////////////////////////////////////////////////

(function () {

    ///////////////////////////////////////////////////////////////////////////
    // Category name placeholders
    ///////////////////////////////////////////////////////////////////////////

    function getSoldCategoryName()    { return "Sold Domains";    }
    function getIgnoredCategoryName() { return "Ignored Domains"; }

    ///////////////////////////////////////////////////////////////////////////
    // Constants
    ///////////////////////////////////////////////////////////////////////////

    const ATG_PANEL_ID   = "atg-sidebar";
    const ATG_OVERLAY_ID = "atg-overlay";
    const ATG_OPEN_CLS   = "cp-open"; // reuse column panel open class

    // cid <= 1 is "All Domains" — cannot remove from it
    const ALL_DOMAINS_CID = 1;

    ///////////////////////////////////////////////////////////////////////////
    // State
    ///////////////////////////////////////////////////////////////////////////

    let _soldCid    = null;
    let _ignoredCid = null;

    ///////////////////////////////////////////////////////////////////////////
    // Public init — called from portfolio.js initApp()
    ///////////////////////////////////////////////////////////////////////////

    window.initDomainActions = function () {
        _buildAddToGroupPanel();
        _wireButtons();
        _attachEscapeKey();
    };

    ///////////////////////////////////////////////////////////////////////////
    // Called from portfolio.js after categories are loaded
    ///////////////////////////////////////////////////////////////////////////

    window.initDomainActionCategories = function (categories) {
        const soldName    = getSoldCategoryName().toLowerCase();
        const ignoredName = getIgnoredCategoryName().toLowerCase();

        categories.forEach(cat => {
            const name = (cat.name || "").toLowerCase();
            if (name === soldName)    _soldCid    = cat.id;
            if (name === ignoredName) _ignoredCid = cat.id;
        });

        _setButtonVisible("btn-mark-sold",  _soldCid    !== null);
        _setButtonVisible("btn-add-ignore", _ignoredCid !== null);
    };

    ///////////////////////////////////////////////////////////////////////////
    // Build Add To Group sidebar panel DOM — runs once
    ///////////////////////////////////////////////////////////////////////////

    function _buildAddToGroupPanel() {
        // Overlay
        const overlay = document.createElement("div");
        overlay.id = ATG_OVERLAY_ID;
        overlay.addEventListener("click", _closeAddToGroupPanel);
        document.body.appendChild(overlay);

        // Panel — reuses cp-* classes so it inherits column panel styles
        const panel = document.createElement("div");
        panel.id = ATG_PANEL_ID;
        panel.innerHTML = `
            <div class="cp-header">
                <span class="cp-title">Add To Group</span>
                <button class="cp-close-btn" title="Close" aria-label="Close panel">&#x2715;</button>
            </div>
            <div class="cp-subheader">
                Select one or more categories to add the selected domains to
            </div>
            <div class="atg-domain-summary" id="atg-domain-summary"></div>
            <div class="cp-list-wrap">
                <ul class="cp-list" id="atg-list"></ul>
            </div>
            <div class="cp-footer">
                <button class="cp-btn cp-btn-cancel" id="atg-cancel">Cancel</button>
                <button class="cp-btn cp-btn-apply" id="atg-apply">Apply</button>
            </div>
        `;
        document.body.appendChild(panel);

        panel.querySelector(".cp-close-btn").addEventListener("click", _closeAddToGroupPanel);
        panel.querySelector("#atg-cancel").addEventListener("click", _closeAddToGroupPanel);
        panel.querySelector("#atg-apply").addEventListener("click", _applyAddToGroup);
    }

    ///////////////////////////////////////////////////////////////////////////
    // Open Add To Group panel
    ///////////////////////////////////////////////////////////////////////////

    async function _openAddToGroupPanel() {
        const ids = _getSelectedIds();
        if (!ids.length) return;

        // Use _domainMembershipMap as primary; re-fetch if map has no data
        // for any of the selected domains
        let membershipMap = _domainMembershipMap;
        const mapHasData  = ids.some(id => membershipMap.has(String(id)));

        if (!mapHasData) {
            membershipMap = await _fetchMembershipMap(ids);
        }

        // Build set of cids that ALL selected domains belong to
        // Only exclude a category if every selected domain is already in it
        const cidMemberCount = {};
        ids.forEach(id => {
            const cids = membershipMap.get(String(id)) || [];
            cids.forEach(cid => {
                cidMemberCount[String(cid)] = (cidMemberCount[String(cid)] || 0) + 1;
            });
        });

        // A category is excluded only if ALL selected domains are already in it
        const excludedCids = new Set(
            Object.entries(cidMemberCount)
                .filter(([, count]) => count === ids.length)
                .map(([cid]) => cid)
        );

        // Filter available categories — exclude already-member categories and All Domains
        const cats      = window._categories || [];
        const available = cats.filter(cat =>
            !excludedCids.has(String(cat.id)) &&
            parseInt(cat.id, 10) > ALL_DOMAINS_CID
        );

        _renderAddToGroupList(available);
        _renderDomainSummary(ids);

        document.getElementById(ATG_OVERLAY_ID).classList.add(ATG_OPEN_CLS);
        document.getElementById(ATG_PANEL_ID).classList.add(ATG_OPEN_CLS);
    }

    ///////////////////////////////////////////////////////////////////////////
    // Render domain summary in Add To Group panel
    ///////////////////////////////////////////////////////////////////////////

    function _renderDomainSummary(ids) {
        const el = document.getElementById("atg-domain-summary");
        if (!el) return;

        const summary = _getSelectedDomainSummary(ids);
        el.innerHTML  = `
            <div class="atg-summary-count">
                This will affect <strong>${ids.length}</strong> domain(s):
            </div>
            <div class="atg-summary-names">${_escHtml(summary)}</div>
        `;
    }

    ///////////////////////////////////////////////////////////////////////////
    // Render category list
    ///////////////////////////////////////////////////////////////////////////

    function _renderAddToGroupList(categories) {
        const ul = document.getElementById("atg-list");
        ul.innerHTML = "";

        if (!categories.length) {
            ul.innerHTML = '<li class="atg-empty">All selected domains are already in every category.</li>';
            return;
        }

        categories.forEach(cat => {
            const li = document.createElement("li");
            li.className     = "cp-item atg-cat-item";
            li.dataset.catId = cat.id;

            const iconHtml = cat.caticon
                ? `<img class="atg-cat-icon" src="lib/layouts/images/icons/categories/light/${cat.caticon}" alt="">`
                : `<span class="atg-cat-icon-placeholder"></span>`;

            li.innerHTML = `
                <label class="cp-item-label">
                    <input type="checkbox" class="cp-checkbox atg-checkbox">
                    ${iconHtml}
                    <span class="cp-col-names">
                        <span class="cp-col-label">${_escHtml(cat.name || "")}</span>
                    </span>
                </label>
            `;

            ul.appendChild(li);
        });
    }

    ///////////////////////////////////////////////////////////////////////////
    // Close Add To Group panel
    ///////////////////////////////////////////////////////////////////////////

    function _closeAddToGroupPanel() {
        const overlay = document.getElementById(ATG_OVERLAY_ID);
        const panel   = document.getElementById(ATG_PANEL_ID);
        if (overlay) overlay.classList.remove(ATG_OPEN_CLS);
        if (panel)   panel.classList.remove(ATG_OPEN_CLS);
    }

    ///////////////////////////////////////////////////////////////////////////
    // Apply Add To Group
    ///////////////////////////////////////////////////////////////////////////

    async function _applyAddToGroup() {
        const ids = _getSelectedIds();
        if (!ids.length) {
            alert("No domains selected.");
            return;
        }

        const checkedCids = Array.from(
            document.querySelectorAll("#atg-list .atg-checkbox:checked")
        ).map(cb => cb.closest(".atg-cat-item").dataset.catId);

        if (!checkedCids.length) {
            alert("Please select at least one category.");
            return;
        }

        const catNames = checkedCids.map(cid => {
            const cat = (window._categories || []).find(c => String(c.id) === String(cid));
            return cat ? cat.name : cid;
        }).join(", ");

        const confirmed = confirm(
            `Add To Group\n\n` +
            `This will affect ${ids.length} domain(s):\n` +
            `${_getSelectedDomainSummary(ids)}\n\n` +
            `Categories: ${catNames}\n\n` +
            `Are you sure?`
        );
        if (!confirmed) return;

        try {
            const params = new URLSearchParams({
                c    : "set",
                t    : "category",
                oper : "addto",
                cid  : checkedCids.join(","),
                id   : ids.join(",")
            });

            const response = await fetch(API_BASE_URL, {
                method     : "POST",
                credentials: "same-origin",
                headers    : { "Content-Type": "application/x-www-form-urlencoded" },
                body       : params.toString()
            });

            const json = await response.json();

            if (json.status === "ok") {
                console.log(`[domainActions] Add To Group: ${json.added ?? ids.length} domain(s) added.`);
                _closeAddToGroupPanel();
                _reloadTable();
            } else {
                console.error("[domainActions] Add To Group failed:", json.error);
                alert(`Action failed: ${json.error || "Unknown error"}`);
            }

        } catch (err) {
            console.error("[domainActions] Add To Group error:", err);
            alert("An error occurred. Please try again.");
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // Remove From Group
    ///////////////////////////////////////////////////////////////////////////

    async function _handleRemoveFromGroup() {
        const ids = _getSelectedIds();
        if (!ids.length) return;

        const activeBtn  = document.querySelector(".btn-cat-selector.btn-active");
        const cid        = activeBtn ? parseInt(activeBtn.getAttribute("data-cid"), 10) : 0;
        const activeName = activeBtn ? activeBtn.textContent.trim() : "this category";
        if (!cid || cid <= ALL_DOMAINS_CID) return;

        const confirmed = confirm(
            `Remove From "${activeName}"\n\n` +
            `This will affect ${ids.length} domain(s):\n` +
            `${_getSelectedDomainSummary(ids)}\n\n` +
            `Are you sure?`
        );
        if (!confirmed) return;

        try {
            const params = new URLSearchParams({
                c    : "set",
                t    : "category",
                oper : "delfrom",
                cid  : cid,
                id   : ids.join(",")
            });

            const response = await fetch(API_BASE_URL, {
                method     : "POST",
                credentials: "same-origin",
                headers    : { "Content-Type": "application/x-www-form-urlencoded" },
                body       : params.toString()
            });

            const json = await response.json();

            if (json.status === "ok") {
                console.log("[domainActions] Remove From Group: done.");
                _reloadTable();
            } else {
                console.error("[domainActions] Remove From Group failed:", json.error);
                alert(`Action failed: ${json.error || "Unknown error"}`);
            }

        } catch (err) {
            console.error("[domainActions] Remove From Group error:", err);
            alert("An error occurred. Please try again.");
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // Shared handler for sold / ignore actions
    ///////////////////////////////////////////////////////////////////////////

    async function _handleCategoryAction(cid, actionLabel) {
        const ids = _getSelectedIds();
        if (!ids.length) {
            alert("No domains selected.");
            return;
        }

        const confirmed = confirm(
            `${actionLabel}\n\n` +
            `This will affect ${ids.length} domain(s):\n` +
            `${_getSelectedDomainSummary(ids)}\n\n` +
            `Are you sure?`
        );
        if (!confirmed) return;

        try {
            const params = new URLSearchParams({
                c    : "set",
                t    : "category",
                oper : "addto",
                cid  : cid,
                id   : ids.join(",")
            });

            const response = await fetch(API_BASE_URL, {
                method     : "POST",
                credentials: "same-origin",
                headers    : { "Content-Type": "application/x-www-form-urlencoded" },
                body       : params.toString()
            });

            const json = await response.json();

            if (json.status === "ok") {
                console.log(`[domainActions] ${actionLabel}: ${json.added ?? ids.length} domain(s) added.`);
                _reloadTable();
            } else {
                console.error(`[domainActions] ${actionLabel} failed:`, json.error);
                alert(`Action failed: ${json.error || "Unknown error"}`);
            }

        } catch (err) {
            console.error(`[domainActions] ${actionLabel} error:`, err);
            alert("An error occurred. Please try again.");
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // Fetch membership map from API (fallback)
    ///////////////////////////////////////////////////////////////////////////

    async function _fetchMembershipMap(ids) {
        const map = new Map();
        try {
            const params = new URLSearchParams({
                c   : "get",
                t   : "domain",
                oper: "catmap",
                id  : ids.join(",")
            });

            const res  = await fetch(API_BASE_URL + "?" + params.toString(), {
                credentials: "same-origin"
            });
            const json = await res.json();

            if (json.status === "ok" && json.data) {
                Object.entries(json.data).forEach(([domainId, cids]) => {
                    map.set(String(domainId), cids);
                });
            }
        } catch (err) {
            console.error("[domainActions] Failed to fetch membership map:", err);
        }
        return map;
    }

    ///////////////////////////////////////////////////////////////////////////
    // Wire button click handlers
    ///////////////////////////////////////////////////////////////////////////

    function _wireButtons() {
        const btnAddGroup    = document.getElementById("btn-add-group");
        const btnRemoveGroup = document.getElementById("btn-remove-group");
        const btnSold        = document.getElementById("btn-mark-sold");
        const btnIgnore      = document.getElementById("btn-add-ignore");

        if (btnAddGroup)    btnAddGroup.addEventListener("click",    () => _openAddToGroupPanel());
        if (btnRemoveGroup) btnRemoveGroup.addEventListener("click", () => _handleRemoveFromGroup());
        if (btnSold)        btnSold.addEventListener("click",        () => _handleCategoryAction(_soldCid,    `Mark as Sold (${getSoldCategoryName()})`));
        if (btnIgnore)      btnIgnore.addEventListener("click",      () => _handleCategoryAction(_ignoredCid, `Add to Ignore List (${getIgnoredCategoryName()})`));

        const btnDelete = document.getElementById("btn-delete-permanent");
        if (btnDelete)  btnDelete.addEventListener("click", () => _handleDeletePermanent());
    }

    ///////////////////////////////////////////////////////////////////////////
    // Delete permanently
    ///////////////////////////////////////////////////////////////////////////

    async function _handleDeletePermanent() {
        const ids = _getSelectedIds();
        if (!ids.length) return;

        const confirmed = confirm(
            `Delete Permanently\n\n` +
            `⚠️ This cannot be undone.\n\n` +
            `This will permanently delete ${ids.length} domain(s):\n` +
            `${_getSelectedDomainSummary(ids)}\n\n` +
            `Are you sure?`
        );
        if (!confirmed) return;

        try {
            const params = new URLSearchParams({
                c    : "grid",
                t    : "domain",
                oper : "del",
                id   : ids.join(",")
            });

            const response = await fetch(API_BASE_URL, {
                method     : "POST",
                credentials: "same-origin",
                headers    : { "Content-Type": "application/x-www-form-urlencoded" },
                body       : params.toString()
            });

            const json = await response.json();

            if (json.status === "ok") {
                console.log(`[domainActions] Deleted ${ids.length} domain(s) permanently.`);
                _reloadTable();
            } else {
                console.error("[domainActions] Delete failed:", json.error);
                alert(`Delete failed: ${json.error || "Unknown error"}`);
            }

        } catch (err) {
            console.error("[domainActions] Delete error:", err);
            alert("An error occurred. Please try again.");
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // Selection + button state polling
    ///////////////////////////////////////////////////////////////////////////

    function _updateButtonStates() {
        const ids          = _getSelectedIds();
        const hasSelection = ids.length > 0;
        const noSelTip     = "Select at least one domain first";

        _setButtonEnabled("btn-add-group",       hasSelection, noSelTip);
        _setButtonEnabled("btn-mark-sold",       hasSelection, noSelTip);
        _setButtonEnabled("btn-add-ignore",      hasSelection, noSelTip);
        _setButtonEnabled("btn-delete-permanent", hasSelection, noSelTip);

        // Remove From Group — also disabled when active category is All Domains
        const activeBtn  = document.querySelector(".btn-cat-selector.btn-active");
        const activeCid  = activeBtn ? parseInt(activeBtn.getAttribute("data-cid"), 10) : 0;
        const activeName = activeBtn ? activeBtn.textContent.trim() : "";
        const canRemove  = hasSelection && activeCid > ALL_DOMAINS_CID;

        // Update button label to always reflect which category will be affected
        const btnRemove = document.getElementById("btn-remove-group");
        if (btnRemove) {
            btnRemove.textContent = (activeCid > ALL_DOMAINS_CID && activeName)
                ? `Remove From "${activeName}"`
                : "Remove From Group";
            btnRemove.style.cursor = canRemove ? "" : "not-allowed";
        }

        _setButtonEnabled("btn-remove-group", canRemove,
            !hasSelection ? noSelTip : "Cannot remove from this category");
    }

    ///////////////////////////////////////////////////////////////////////////
    // Escape key — close Add To Group panel if open
    ///////////////////////////////////////////////////////////////////////////

    function _attachEscapeKey() {
        document.addEventListener("keydown", function (e) {
            if (e.key === "Escape") {
                const panel = document.getElementById(ATG_PANEL_ID);
                if (panel && panel.classList.contains(ATG_OPEN_CLS)) {
                    _closeAddToGroupPanel();
                }
            }
        });
    }

    ///////////////////////////////////////////////////////////////////////////
    // Utilities
    ///////////////////////////////////////////////////////////////////////////

    function _getSelectedIds() {
        const dt = DataTableView.getTable("dp-table");
        if (!dt) return [];
        return dt.getSelectedIds();
    }

    // Returns a human-readable summary of selected domains for confirm dialogs
    // e.g. "example.com, foo.com, bar.com and 12 more"
    function _getSelectedDomainSummary(ids, maxShown = 5) {
        const dt = DataTableView.getTable("dp-table");
        if (!dt || !dt.options.data) return `${ids.length} domain(s)`;

        const names = [];
        ids.forEach(id => {
            const row = dt.options.data.find(r => String(r.id) === String(id));
            if (row) {
                const name = row["d.domain"] || row["domain"] || null;
                if (name) names.push(name);
            }
        });

        if (!names.length) return `${ids.length} domain(s)`;

        const shown    = names.slice(0, maxShown);
        const remaining = names.length - shown.length;
        let summary    = shown.join(", ");
        if (remaining > 0) summary += ` and ${remaining} more`;
        return summary;
    }

    function _reloadTable() {
        const dt = DataTableView.getTable("dp-table");
        if (dt) dt.reload();
    }

    function _setButtonVisible(id, visible) {
        const btn = document.getElementById(id);
        if (!btn) return;
        btn.style.display = visible ? "" : "none";
    }

    function _setButtonEnabled(id, enabled, tooltip) {
        const btn = document.getElementById(id);
        if (!btn) return;
        btn.disabled = !enabled;
        btn.title    = enabled ? "" : (tooltip || "");
    }

    function _escHtml(str) {
        return String(str)
            .replace(/&/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;")
            .replace(/"/g, "&quot;");
    }

    setInterval(_updateButtonStates, 500);

})();