<?php

namespace GriffinForms\Admin\App\Html\Modals\FormNotifications;

trait Scripts
{
    protected function renderScripts(): void
    {
        $form_id   = (int) $this->utility->getFormId();
        $action_id = 'griffinforms-builder-modal-formnotifications-action-btn';
        $nonce     = wp_create_nonce('wp_rest');
        $check_fields_nonce = wp_create_nonce('check_form_fields');

        echo '
(function($) {

    // Guard: bind handlers only once even if this script is re-evaluated on subsequent modal opens
    if (window.gfNotifInitDone) { return; }
    window.gfNotifInitDone = true;

    var gfNotifFormId    = ' . $form_id . ';
    var gfNotifNonce     = ' . wp_json_encode($nonce) . ';
    var gfNotifCheckNonce = ' . wp_json_encode($check_fields_nonce) . ';
    var $modal = $("#griffinforms-builder-modal-formnotifications");

    // ── Spinner ──────────────────────────────────────────────────────────────

    function gfNotifSpinner(show) {
        var $s = $modal.find(".griffinforms-modal-spinner");
        if (show) { $s.removeClass("d-none"); } else { $s.addClass("d-none"); }
    }

    // ── Tab switching (mirrors Form Options exactly) ──────────────────────────

    function gfNotifMoveIndicator($btn) {
        var $nav = $btn.closest(".gf-formoptions-sidenav");
        var $ind = $nav.find(".gf-formoptions-tab-indicator");
        if (!$ind.length) { return; }
        $ind.css({ top: $btn[0].offsetTop + "px", height: $btn[0].offsetHeight + "px" });
    }

    (function() {
        var $active = $modal.find(".gf-formoptions-tab-btn--active").first();
        if ($active.length) {
            var $ind = $active.closest(".gf-formoptions-sidenav").find(".gf-formoptions-tab-indicator");
            $ind.css({ transition: "none", top: $active[0].offsetTop + "px", height: $active[0].offsetHeight + "px" });
            setTimeout(function() { $ind.css("transition", ""); }, 0);
        }
    })();

    $modal.on("click", ".gf-formoptions-tab-btn", function() {
        var $btn   = $(this);
        var target = $btn.attr("data-bs-target");

        $modal.find(".gf-formoptions-tab-btn")
            .removeClass("gf-formoptions-tab-btn--active")
            .attr("aria-selected", "false");
        $btn.addClass("gf-formoptions-tab-btn--active").attr("aria-selected", "true");
        gfNotifMoveIndicator($btn);

        $modal.find(".gf-formoptions-panel").removeClass("gf-formoptions-panel--active");
        $modal.find(target).addClass("gf-formoptions-panel--active");
    });

    // ── Card collapse / expand ────────────────────────────────────────────────

    $modal.on("click", ".gf-notif-card-toggle", function() {
        var $card     = $(this).closest(".gf-notif-card");
        var $body     = $card.find(".gf-notif-card-body");
        var expanded  = $(this).attr("aria-expanded") === "true";

        // Close all other open cards
        $modal.find(".gf-notif-card-toggle[aria-expanded=true]").not(this).each(function() {
            $(this).attr("aria-expanded", "false");
            $(this).closest(".gf-notif-card").find(".gf-notif-card-body").slideUp(150);
            $(this).closest(".gf-notif-card").find(".gf-notif-card-chevron").css("transform", "");
        });

        if (expanded) {
            $body.slideUp(150);
            $(this).attr("aria-expanded", "false");
            $card.find(".gf-notif-card-chevron").css("transform", "");
        } else {
            $body.slideDown(150);
            $(this).attr("aria-expanded", "true");
            $card.find(".gf-notif-card-chevron").css("transform", "rotate(180deg)");

            // Lazy-load any field pickers not yet populated
            $card.find(".gf-notif-recipient-value-field").each(function() {
                var $select   = $(this);
                var fieldType = $select.data("field-type") || null;
                var selected  = $select.data("selected") || "";
                if (fieldType && gfNotifFormId) {
                    gfNotifLoadFieldOptions($select, fieldType, selected, gfNotifFormId);
                }
            });
        }
    });

    // ── Card delete ───────────────────────────────────────────────────────────

    $modal.on("click", ".gf-notif-card-delete", function() {
        var $card = $(this).closest(".gf-notif-card");
        var $list = $card.closest(".gf-notif-card-list");
        $card.remove();
        gfNotifCheckEmptyState($list);
    });

    function gfNotifCheckEmptyState($list) {
        if ($list.find(".gf-notif-card").length === 0) {
            if (!$list.find(".gf-notif-empty-state").length) {
                $list.append(
                    "<p class=\"text-muted small gf-notif-empty-state\">" +
                    ' . wp_json_encode(__('No notifications configured. Click Add to create one.', 'griffinforms-form-builder')) . ' +
                    "</p>"
                );
            }
        } else {
            $list.find(".gf-notif-empty-state").remove();
        }
    }

    // ── Card add ──────────────────────────────────────────────────────────────

    $modal.on("click", ".gf-notif-card-add", function() {
        var eventId    = $(this).data("event-id");
        var subEventId = $(this).data("subevent-id");
        var $list      = $modal.find(
            ".gf-notif-card-list[data-event-id=\"" + eventId + "\"][data-subevent-id=\"" + subEventId + "\"]"
        );

        var tmpl = document.getElementById("gf-notif-card-template");
        if (!tmpl) { return; }

        var uuid  = (typeof crypto !== "undefined" && crypto.randomUUID)
            ? crypto.randomUUID()
            : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
                var r = Math.random() * 16 | 0, v = c === "x" ? r : (r & 0x3 | 0x8);
                return v.toString(16);
              });

        // Clone template content and replace UUID token
        var html = tmpl.innerHTML.replace(/__UUID__/g, uuid);
        var $card = $(html);

        $list.find(".gf-notif-empty-state").remove();
        $list.append($card);

        // Auto-open new card
        $card.find(".gf-notif-card-body").show();
        $card.find(".gf-notif-card-toggle").attr("aria-expanded", "true");
        $card.find(".gf-notif-card-chevron").css("transform", "rotate(180deg)");

        // Re-init sortable on this list
        gfNotifInitSortable($list);
    });

    // ── jQuery UI Sortable ────────────────────────────────────────────────────

    function gfNotifInitSortable($list) {
        if (typeof $.fn.sortable === "undefined") { return; }
        if ($list.hasClass("ui-sortable")) {
            $list.sortable("refresh");
            return;
        }
        $list.sortable({
            handle: ".gf-notif-card-handle",
            items:  ".gf-notif-card",
            axis:   "y",
            tolerance: "pointer",
            placeholder: "gf-notif-card-placeholder"
        });
    }

    // ── Channel change handler ────────────────────────────────────────────────

    $modal.on("change", ".gf-notif-card-channel", function() {
        var $select   = $(this);
        var $card     = $select.closest(".gf-notif-card");
        var newChanId = $select.val();
        var $opt      = $select.find("option:selected");
        var fieldType = $opt.data("field-type") || null;

        // Update badge
        var label = newChanId ? $select.find("option:selected").text() : ' . wp_json_encode(__('No channel', 'griffinforms-form-builder')) . ';
        $card.find(".gf-notif-card-channel-badge").text(label);

        // Enable/disable message select based on channel selection
        $card.find(".gf-notif-card-message").prop("disabled", newChanId === "");

        // Clear recipients
        var $recipients = $card.find(".gf-notif-recipients");
        $recipients.find(".gf-notif-recipient-row").remove();
        $recipients.find(".gf-notif-recipients-empty").remove();
        $recipients.append(
            "<p class=\"text-muted small gf-notif-recipients-empty\">" +
            ' . wp_json_encode(__('No recipients added.', 'griffinforms-form-builder')) . ' +
            "</p>"
        );

        // Store field-type on the add button for new rows to reference
        $card.find(".gf-notif-add-recipient").data("field-type", fieldType).toggle(newChanId !== "");
    });

    // ── Recipient: add row ────────────────────────────────────────────────────

    $modal.on("click", ".gf-notif-add-recipient", function() {
        var $btn      = $(this);
        var $card     = $btn.closest(".gf-notif-card");
        var fieldType = $btn.data("field-type") || null;
        var $container = $card.find(".gf-notif-recipients");

        $container.find(".gf-notif-recipients-empty").remove();

        // Default to "field" if channel supports fields, else "static"
        var defaultType = fieldType ? "field" : "static";

        var $row = gfNotifBuildRecipientRow(defaultType, "", fieldType);
        $container.append($row);

        if (defaultType === "field") {
            gfNotifLoadFieldOptions($row.find(".gf-notif-recipient-value-field"), fieldType, "", gfNotifFormId);
        } else {
            $row.find(".gf-notif-recipient-value-static").trigger("focus");
        }
    });

    // ── Recipient: type change (Field ↔ Custom) ───────────────────────────────

    $modal.on("change", ".gf-notif-recipient-type", function() {
        var $typeSelect = $(this);
        var $row        = $typeSelect.closest(".gf-notif-recipient-row");
        var type        = $typeSelect.val();
        var $card       = $typeSelect.closest(".gf-notif-card");
        var fieldType   = $card.find(".gf-notif-add-recipient").data("field-type") || null;

        // Replace right-hand control
        $row.find(".gf-notif-recipient-value-field, .gf-notif-recipient-value-static").remove();

        var $del = $row.find(".gf-notif-remove-recipient");

        if (type === "field") {
            var $fs = $("<select>").addClass("form-select gf-app-control-input gf-notif-recipient-value-field")
                .data("field-type", fieldType);
            $fs.append($("<option>").val("").text(' . wp_json_encode(__('Loading…', 'griffinforms-form-builder')) . '));
            $del.before($fs);
            if (fieldType) {
                gfNotifLoadFieldOptions($fs, fieldType, "", gfNotifFormId);
            }
        } else {
            var $inp = $("<input>").attr({
                type:        "text",
                placeholder: ' . wp_json_encode(__('e.g. admin@example.com', 'griffinforms-form-builder')) . '
            }).addClass("form-control gf-app-control-input gf-notif-recipient-value-static");
            $del.before($inp);
            $inp.trigger("focus");
        }
    });

    // ── Recipient row builder ─────────────────────────────────────────────────

    function gfNotifBuildRecipientRow(type, value, fieldType) {
        var $row = $("<div>").addClass("gf-notif-recipient-row input-group mb-2");

        var $typeSelect = $("<select>").addClass("form-select gf-app-control-input gf-notif-recipient-type flex-grow-0 w-auto");
        if (fieldType) {
            $typeSelect.append($("<option>").val("field").text(' . wp_json_encode(__('Field', 'griffinforms-form-builder')) . ').prop("selected", type === "field"));
        }
        $typeSelect.append($("<option>").val("static").text(' . wp_json_encode(__('Custom', 'griffinforms-form-builder')) . ').prop("selected", type === "static"));

        var $del = $("<button>").attr("type", "button")
            .addClass("gf-btn-light btn griffinforms-app-fe-btn gf-text-danger gf-notif-remove-recipient")
            .text(' . wp_json_encode(__('Delete', 'griffinforms-form-builder')) . ');

        $row.append($typeSelect);

        if (type === "field") {
            var $fs = $("<select>").addClass("form-select gf-app-control-input gf-notif-recipient-value-field")
                .data("field-type", fieldType).data("selected", value || "");
            $fs.append($("<option>").val(value || "").text(' . wp_json_encode(__('Loading…', 'griffinforms-form-builder')) . '));
            $row.append($fs);
        } else {
            var $inp = $("<input>").attr({
                type:        "text",
                placeholder: ' . wp_json_encode(__('e.g. admin@example.com', 'griffinforms-form-builder')) . '
            }).addClass("form-control gf-app-control-input gf-notif-recipient-value-static").val(value || "");
            $row.append($inp);
        }

        $row.append($del);
        return $row;
    }

    // ── Recipient: remove ─────────────────────────────────────────────────────

    $modal.on("click", ".gf-notif-remove-recipient", function() {
        var $container = $(this).closest(".gf-notif-recipients");
        $(this).closest(".gf-notif-recipient-row").remove();
        if ($container.find(".gf-notif-recipient-row").length === 0) {
            $container.append(
                "<p class=\"text-muted small gf-notif-recipients-empty\">" +
                ' . wp_json_encode(__('No recipients added.', 'griffinforms-form-builder')) . ' +
                "</p>"
            );
        }
    });

    // ── Field picker: load options via AJAX ───────────────────────────────────

    var gfNotifFieldCache   = {}; // cacheKey -> fields array once resolved
    var gfNotifFieldPending = {}; // cacheKey -> array of {$select, selectedValue} waiting on in-flight request

    function gfNotifLoadFieldOptions($select, fieldType, selectedValue, formId) {
        var cacheKey = fieldType + ":" + formId;

        // Already resolved — populate immediately
        if (gfNotifFieldCache[cacheKey]) {
            gfNotifPopulateFieldSelect($select, gfNotifFieldCache[cacheKey], selectedValue);
            return;
        }

        // In-flight — queue this select to be populated when the request completes
        if (gfNotifFieldPending[cacheKey]) {
            gfNotifFieldPending[cacheKey].push({ $select: $select, selectedValue: selectedValue });
            return;
        }

        // First request for this key — start AJAX and open the queue
        gfNotifFieldPending[cacheKey] = [{ $select: $select, selectedValue: selectedValue }];

        $.ajax({
            url: ajaxurl,
            method: "POST",
            dataType: "json",
            data: {
                action:     "checkFormFields",
                nonce:      gfNotifCheckNonce,
                form_id:    formId,
                field_type: fieldType
            },
            success: function(res) {
                var fields = (res && res.success && Array.isArray(res.fields)) ? res.fields : [];
                gfNotifFieldCache[cacheKey] = fields;
                var queue = gfNotifFieldPending[cacheKey] || [];
                delete gfNotifFieldPending[cacheKey];
                queue.forEach(function(item) {
                    if (fields.length) {
                        gfNotifPopulateFieldSelect(item.$select, fields, item.selectedValue);
                    } else {
                        item.$select.empty().append(
                            $("<option>").val("").text(' . wp_json_encode(__('No fields found', 'griffinforms-form-builder')) . ')
                        );
                    }
                });
            },
            error: function() {
                var queue = gfNotifFieldPending[cacheKey] || [];
                delete gfNotifFieldPending[cacheKey];
                queue.forEach(function(item) {
                    item.$select.empty().append(
                        $("<option>").val("").text(' . wp_json_encode(__('Error loading fields', 'griffinforms-form-builder')) . ')
                    );
                });
            }
        });
    }

    function gfNotifPopulateFieldSelect($select, fields, selectedValue) {
        // Already populated — just re-apply the selected value, do not rebuild
        if ($select.find("option").length > 1) {
            if (selectedValue !== "" && selectedValue !== null && selectedValue !== undefined) {
                $select.val(String(selectedValue));
                gfNotifCheckOrphanedField($select, selectedValue);
            }
            return;
        }
        $select.empty();
        $select.append($("<option>").val("").text(' . wp_json_encode(__('— Select a field —', 'griffinforms-form-builder')) . '));
        fields.forEach(function(f) {
            var label = f.heading || f.name || ("Field #" + f.id);
            $select.append($("<option>").val(String(f.id)).text(label));
        });
        if (selectedValue !== "" && selectedValue !== null && selectedValue !== undefined) {
            $select.val(String(selectedValue));
            gfNotifCheckOrphanedField($select, selectedValue);
        }
    }

    function gfNotifCheckOrphanedField($select, selectedValue) {
        if (selectedValue === "" || selectedValue === null || selectedValue === undefined) { return; }
        var $card = $select.closest(".gf-notif-card");
        if (!$card.length) { return; }
        var resolved = $select.val();
        if (resolved === "" || resolved === null || String(resolved) !== String(selectedValue)) {
            $card.find(".gf-notif-card-body").show();
            $card.find(".gf-notif-card-toggle").attr("aria-expanded", "true");
            $card.find(".gf-notif-card-chevron").css("transform", "rotate(180deg)");
            if (!$card.find(".gf-notif-orphaned-field-error").length) {
                $card.find(".gf-notif-card-body").prepend(
                    "<div class=\"gf-notice gf-notice-danger mb-3 gf-notif-orphaned-field-error\">" +
                    ' . wp_json_encode(__('A recipient field was deleted from this form. Please choose a replacement or remove this recipient.', 'griffinforms-form-builder')) . ' +
                    "</div>"
                );
            }
        }
    }

    // ── Payload assembler ─────────────────────────────────────────────────────

    function gfGetFormNotificationsData() {
        var payload = {};

        $modal.find(".gf-notif-subevent").each(function() {
            var eventId    = $(this).data("event-id");
            var subEventId = $(this).data("subevent-id");

            if (!payload[eventId]) { payload[eventId] = {}; }
            payload[eventId][subEventId] = [];

            $(this).find(".gf-notif-card-list .gf-notif-card").each(function(idx) {
                var $card     = $(this);
                var notifId   = $card.data("notification-id") || "";
                var enabled   = $card.find(".gf-notif-card-enabled").is(":checked");
                var channelId = $card.find(".gf-notif-card-channel").val() || "";
                var messageId = parseInt($card.find(".gf-notif-card-message").val(), 10) || 0;
                var recipients = [];

                $card.find(".gf-notif-recipient-row").each(function() {
                    var type  = $(this).find(".gf-notif-recipient-type").val() || "static";
                    var value = "";
                    if (type === "field") {
                        value = $(this).find(".gf-notif-recipient-value-field").val() || "";
                    } else {
                        value = $(this).find(".gf-notif-recipient-value-static").val().trim();
                    }
                    if (value !== "") {
                        recipients.push({ type: type, value: value });
                    }
                });

                payload[eventId][subEventId].push({
                    id:         notifId,
                    order:      idx + 1,
                    enabled:    enabled,
                    channel:    channelId,
                    message_id: messageId,
                    recipients: recipients
                });
            });
        });

        return payload;
    }

    // ── Validation ────────────────────────────────────────────────────────────

    function gfNotifValidate() {
        var valid = true;

        $modal.find(".gf-notif-card").each(function() {
            var $card     = $(this);
            var channelId = $card.find(".gf-notif-card-channel").val();
            var messageId = parseInt($card.find(".gf-notif-card-message").val(), 10) || 0;
            var enabled   = $card.find(".gf-notif-card-enabled").is(":checked");

            if (!enabled) { return; } // skip disabled cards

            if (!channelId) {
                gfNotifCardError($card, ' . wp_json_encode(__('Please select a channel.', 'griffinforms-form-builder')) . ');
                valid = false;
                return;
            }
            if (messageId < 1) {
                gfNotifCardError($card, ' . wp_json_encode(__('Please select a message.', 'griffinforms-form-builder')) . ');
                valid = false;
                return;
            }

            // Recipient validation
            var seenFieldIds = [];
            $card.find(".gf-notif-recipient-row").each(function() {
                if (!valid) { return; }
                var $row  = $(this);
                var type  = $row.find(".gf-notif-recipient-type").val();
                if (type === "static") {
                    var val = $.trim($row.find(".gf-notif-recipient-value-static").val());
                    if (!val) {
                        gfNotifCardError($card, ' . wp_json_encode(__('Please enter a value for all custom recipients.', 'griffinforms-form-builder')) . ');
                        valid = false;
                    }
                } else {
                    var fieldId = $row.find(".gf-notif-recipient-value-field").val();
                    if (!fieldId || fieldId === "0" || fieldId === "") {
                        gfNotifCardError($card, ' . wp_json_encode(__('Please select a field for all field recipients.', 'griffinforms-form-builder')) . ');
                        valid = false;
                        return;
                    }
                    if (seenFieldIds.indexOf(fieldId) !== -1) {
                        gfNotifCardError($card, ' . wp_json_encode(__('Duplicate field selected. Each field can only be used once per notification.', 'griffinforms-form-builder')) . ');
                        valid = false;
                        return;
                    }
                    seenFieldIds.push(fieldId);
                }
            });
        });

        return valid;
    }

    function gfNotifCardError($card, msg) {
        $card.find(".gf-notif-card-body").show();
        $card.find(".gf-notif-card-toggle").attr("aria-expanded", "true");
        $card.find(".gf-notif-card-chevron").css("transform", "rotate(180deg)");
        if (!$card.find(".gf-notif-card-error").length) {
            $card.find(".gf-notif-card-body").prepend(
                "<div class=\"gf-notice gf-notice-danger mb-3 gf-notif-card-error\">" + msg + "</div>"
            );
        }
    }

    function gfNotifClearErrors() {
        $modal.find(".gf-notif-card-error").remove();
    }

    // ── Save flow ─────────────────────────────────────────────────────────────

    function gfSaveFormNotifications() {
        gfNotifClearErrors();

        if (!gfNotifValidate()) { return; }
        if (!gfNotifFormId)     { return; }

        gfNotifSpinner(true);

        wp.apiFetch({
            path:    "/griffinforms/v1/forms/" + gfNotifFormId + "/notifications",
            method:  "POST",
            headers: { "X-WP-Nonce": gfNotifNonce },
            data:    { item_data: JSON.stringify(gfGetFormNotificationsData()) }
        }).then(function() {
            gfNotifSpinner(false);
            statusbarMsg("success", ' . wp_json_encode(__('Notifications saved.', 'griffinforms-form-builder')) . ');
            setTimeout(function() {
                var modalEl = document.getElementById("griffinforms-builder-modal-formnotifications");
                if (modalEl) { bootstrap.Modal.getOrCreateInstance(modalEl).hide(); }
            }, 1200);
        }).catch(function(err) {
            gfNotifSpinner(false);
            var msg = (err && err.message) ? err.message : ' . wp_json_encode(__('Save failed. Please try again.', 'griffinforms-form-builder')) . ';
            statusbarMsg("failure", msg);
        });
    }

    $(document).on("click", "#' . esc_js($action_id) . '", function() {
        gfSaveFormNotifications();
    });

    // ── On modal open ─────────────────────────────────────────────────────────

    function gfNotifInitModal() {
        // Init tab indicator
        var $active = $modal.find(".gf-formoptions-tab-btn--active").first();
        if ($active.length) { gfNotifMoveIndicator($active); }

        // Init sortable on all card lists
        $modal.find(".gf-notif-card-list").each(function() {
            gfNotifInitSortable($(this));
        });

        // Load field pickers for existing field-type recipients
        $modal.find(".gf-notif-recipient-value-field").each(function() {
            var $select   = $(this);
            var selected  = $select.data("selected") || "";
            var fieldType = $select.data("field-type") || null;
            if (fieldType && gfNotifFormId) {
                gfNotifLoadFieldOptions($select, fieldType, selected, gfNotifFormId);
            }
        });
    }

    $modal.off("show.bs.modal.gfNotif").on("show.bs.modal.gfNotif", function() {
        var $body = $modal.find(".gf-formoptions-body");
        $body.css("opacity", 0.4);

        $.post(ajaxurl, {
            action:  "gf_get_notifications_html",
            nonce:   gfNotifNonce,
            form_id: gfNotifFormId
        }, function(res) {
            if (res && res.success && res.data && res.data.html) {
                $body.replaceWith(res.data.html);
                gfNotifFieldCache   = {};
                gfNotifFieldPending = {};
                gfNotifInitModal();
            }
        }).always(function() {
            $modal.find(".gf-formoptions-body").css("opacity", "");
        });
    });

    $modal.off("shown.bs.modal.gfNotif").on("shown.bs.modal.gfNotif", function() {
        gfNotifInitModal();
    });

})(jQuery);
        ';
    }
}
