<?php

namespace GriffinForms\Admin\Html\Modals;

/**
 * Modal for listing, searching, and selecting items like messages or templates.
 * Supports AJAX-powered loading, searching, and item mapping workflows.
 */
class SelectItem extends \GriffinForms\Admin\Html\Modals\Format
{
    protected $meta;
    protected $name;
    protected $item_type;
    protected $id;
    protected $ids;
    
    protected function setName()
    {
        if (!isset($this->data['name'])) {
            wp_die('Property name not set for selectitem modal.');
        }

        $this->name = $this->data['name'];
    }
    
    protected function setItemType()
    {
        if (!isset($this->data['item_type'])) {
            wp_die('Item type not set for selectitem modal.');
        }
        
        $this->item_type = $this->data['item_type'];
    }
    
    protected function setId()
    {
        $this->id = 'griffinforms-select' . $this->name . '-modal';
    }
    
    protected function setIds()
    {
        $pre = 'griffinforms-' . strtolower($this->meta) . '-';
        
        $this->ids = array(
            'noitem' => $pre . 'no' . $this->name . '-wrap',
            'items' => $pre . 'available' . $this->name . '-wrap',
            'create_btn' => $pre . 'create' . $this->name . '-btn',
            'save_btn' => 'griffinforms-modalaction-create' . $this->name,
            'open_btn' => 'griffinforms-current-' . $this->name . '-name',
            'search_input' => $pre . 'search' . $this->name . '-input',
            'search_btn' => $pre . 'search' . $this->name . '-btn',
            'item_list' => $pre . $this->name . 'list-wrap',
            'items_loader' => $pre . $this->name . '-itemsloader',
            'load_more' => $pre . 'loadmore' . $this->name . '-wrap',
            'waiting' => $pre . 'waiting' . $this->name . '-wrap',
            'list_wrap' => $pre . $this->name . 'list-wrap'
        );
    }
        
    protected function headerText()
    {
        $text = $this->lang->getText('select_' . $this->name);
        return $text;
    }
    
    protected function modalContent()
    {
        echo '<div class="container my-4" id="' . esc_attr($this->ids['items']) . '">';
        $this->searchItems();
        $this->itemsList();
        $this->loadMoreItems();
        echo '</div>';
        
    }
    
    protected function searchItems()
    {
        echo '<div class="row mb-3">';
        $this->addItem();
        echo '<div class="col griffinforms-modal-itemsearch-wrap">';
        echo '<div class="input-group mb-3">';
        echo '<input type="text" class="form-control border" id="' . esc_attr($this->ids['search_input']) . '">';
        echo '<button class="button" type="button" id="' . esc_attr($this->ids['search_btn']) . '">';
        $this->mIcon('search');
        echo '</button>';
        echo '</div>';
        echo '</div>';
        echo '</div>';
        
    }
    
    protected function addItem()
    {
        echo '<div class="col">';
        $this->buttons->wpBtn([
            'id' => $this->ids['create_btn'],
            'class' => 'button',
            'label' => $this->lang->getText('create_' . $this->name),
            'data' => [
                'data-bs-toggle=modal',
                'data-bs-dismiss=modal',
                'data-bs-target=#griffinforms-create' . esc_attr($this->item_type) . '-modal'
            ],
        ]);
        echo '</div>';
    }
    
    protected function itemsList()
    {
        echo '<div class="row position-relative">';
        echo '<div class="col-md-12 mb-3 border rounded position-relative top-0 start-0" id="' . esc_attr($this->ids['item_list']) . '" style="height: 396px; overflow-y: scroll;">';
        echo '</div>';
        $this->itemsLoader();
        echo '</div>';
        
    }
    
    protected function itemsLoader()
    {
        echo '<div class="col-md-12 mb-3 border rounded position-absolute top-0 start-0 d-flex justify-content-center align-items-center" id="' . esc_attr($this->ids['items_loader']) . '" style="height: 396px; overflow-y: none; visibility: hidden">';
        echo '<div class="spinner-border spinner-border-sm text-primary" role="status">';
        echo '<span class="visually-hidden">Loading...</span>';
        echo '</div>';
        echo '</div>';
    }
    
    protected function loadMoreItems()
    {
        echo '<div class="row griffinforms-modal-loadmore-wrap">';
        echo '<div class="col-md-12 text-center">';
        echo '<button type="button" class="button button-primary" id="' . esc_attr($this->ids['load_more']) . '" style="visibility: hidden">' . esc_js($this->lang->getText('load_more_' . $this->item_type)) . '</button>';        
        echo '</div>';
        echo '</div>';
        
    }
    
    protected function modalFooter()
    {
    }
    
    /**
     * Injects JavaScript to handle:
     * - Modal opening logic
     * - AJAX loading of items
     * - Searching and pagination
     * - Item selection and mapping workflows
     */
    public function modalJs()
    {
        $nonce_data = wp_create_nonce('items_data');
        $nonce_count = wp_create_nonce('item_count');
        $nonce_search = wp_create_nonce('item_search');

        ob_start();
        ?>
        jQuery(document).ready(function($) {
            // Utility function to get currently loaded item count in the modal
            function loadedItemCount() {
                return $("#<?php echo esc_attr($this->ids['item_list']); ?>").find(".griffinforms-modalitemlist-item").length;
            }
            
            var selectionModal = document.getElementById("<?php echo esc_attr($this->id); ?>");
            
            // Event listener to load items when the modal is shown
            selectionModal.addEventListener("show.bs.modal", function(event) {
                // Clear existing list and reset search on modal open
                $("#<?php echo esc_attr($this->ids['item_list']); ?>").html("");
                resetSearch();

                const caller = event.relatedTarget || null;
                if (caller) {
                    if (
                        $(caller).attr("id") === "<?php echo esc_attr($this->ids['open_btn']); ?>" ||
                        $(caller).data("gf-trigger") === "map_email_message" ||
                        $(caller).data("gf-trigger") === "map_alert_email_message"
                    ) {
                        getItemsForModal(0, "list_empty", caller);
                    }
                } else if ($(this).data('triggeredFrom') === 'newItem') {
                    $("#<?php echo esc_attr($this->ids['items_loader']); ?>").css("visibility", "visible");
                    setTimeout(function() {
                        getItemsForModal(loadedItemCount(), "new_item", null);
                    }, 500);
                    $(this).removeData('triggeredFrom');
                } else {
                    // Fallback to always load the item list if no caller or trigger context is provided
                    getItemsForModal(0, "list_empty", null);
                }
            });

            // Load more items when "Load More" button is clicked
            $("#<?php echo esc_attr($this->ids['load_more']); ?>").click(function() {
                getItemsForModal(loadedItemCount(), "load_more", null);
                $("#<?php echo esc_attr($this->ids['load_more']); ?>").css("visibility", "hidden");
            });

            // AJAX request to fetch items based on context (list, new item, load more)
            function getItemsForModal(offset = 0, context, caller = null) {
                // Set visibility for loading state based on context
                if (context === "load_more") {
                    $("#<?php echo esc_attr($this->ids['item_list']); ?>").css("visibility", "visible");
                    $("#<?php echo esc_attr($this->ids['items_loader']); ?>").css("visibility", "hidden");
                } else {
                    $("#<?php echo esc_attr($this->ids['item_list']); ?>").css("visibility", "hidden");
                    $("#<?php echo esc_attr($this->ids['items_loader']); ?>").css("visibility", "visible");
                }

                // Request the list of items via AJAX based on offset and context
                var data = {
                    "action": "sendItemsToModal",
                    "item_type": "<?php echo esc_js($this->item_type); ?>",
                    "name": "<?php echo esc_js($this->name); ?>",
                    "offset": offset,
                    "nonce": "<?php echo esc_js($nonce_data); ?>"
                };
                
                $.post(ajaxurl, data, function(response) {
                    if (context === "list_empty") {
                        $("#<?php echo esc_attr($this->ids['item_list']); ?>").html(response);
                    } else if (context === "new_item") {
                        $("#<?php echo esc_attr($this->ids['item_list']); ?>").html(response);
                        highlightNewItem();
                    } else {
                        $("#<?php echo esc_attr($this->ids['item_list']); ?>").append(response);
                        scrollToBottom();
                    }

                    // Ensure item rows can reopen the parent modal after selection
                    assignParentModalIdToItems(caller);

                    $("#<?php echo esc_attr($this->ids['item_list']); ?>").css("visibility", "visible");
                    $("#<?php echo esc_attr($this->ids['items_loader']); ?>").css("visibility", "hidden");
                    showLoadMoreItems();
                });
            }

            // Assign data-bs-toggle and data-bs-target to item rows for modal reopening
            function assignParentModalIdToItems(caller) {
                const parentModalId = $(caller).attr("data-gf-parentmodalid");
                if (!parentModalId) return;

                $("#<?php echo esc_attr($this->ids['item_list']); ?>")
                    .find(".griffinforms-modalitemlist-item")
                    .attr("data-bs-toggle", "modal")
                    .attr("data-bs-target", parentModalId);
            }
            
            // Show or hide the "Load More" button based on remaining items
            function showLoadMoreItems() {
                var data = {
                    "action": "sendItemCount",
                    "item_type": "<?php echo esc_js($this->item_type); ?>",
                    "nonce": "<?php echo esc_js($nonce_count); ?>"
                };
                
                $.post(ajaxurl, data, function(response) {
                    if (response == loadedItemCount()) {
                        $("#<?php echo esc_attr($this->ids['load_more']); ?>").css("visibility", "hidden");
                    } else {
                        $("#<?php echo esc_attr($this->ids['load_more']); ?>").css("visibility", "visible");
                    }
                });
            }

            // Save the mapping of selected message to a specific email field
            function saveEmailFieldMapping(fieldId, itemId, itemName, itemHeading) {
                window.griffinformsEmailFieldMappings = window.griffinformsEmailFieldMappings || {};
                window.griffinformsEmailFieldMappings[String(fieldId)] = {
                    message_id: itemId,
                    message_name: itemName,
                    message_heading: itemHeading
                };

                var serializedMappings = JSON.stringify(window.griffinformsEmailFieldMappings);
                $("#griffinforms-emailfield-mappings").val(serializedMappings);
            }

            // Sync the current mappings to the hidden input for form submission
            function syncMappingsToHiddenField() {
                // This function syncs the email field mappings to the hidden input field.
                if (window.griffinformsEmailFieldMappings) {
                    var serializedMappings = JSON.stringify(window.griffinformsEmailFieldMappings);
                    $("#griffinforms-emailfield-mappings").val(serializedMappings);
                }
            }
            
            // Handles mapping and reopens the parent modal with updated data
            function handleEmailFieldMessageMapping(itemId, itemName, itemHeading) {
                var selectionModal = $("#<?php echo esc_attr($this->id); ?>");
                if (selectionModal.data("gf-trigger") !== "map_email_message") {
                    return;
                }
                var fieldId = selectionModal.data("gf-email-field-id");
                var parentModalId = selectionModal.data("gf-parentmodalid");

                if (fieldId) {
                    saveEmailFieldMapping(fieldId, itemId, itemName, itemHeading);
                    syncMappingsToHiddenField();

                    if (parentModalId) {
                        var $parentModal = $(parentModalId);
                        $parentModal.modal("show");
                        $parentModal.trigger("show.bs.modal");
                    }
                }
            }

            // Handle mapping for admin alert email rows (no parent modal).
            function handleAlertEmailMessageMapping(itemId, itemName, itemHeading) {
                var selectionModal = $("#<?php echo esc_attr($this->id); ?>");
                if (selectionModal.data("gf-trigger") !== "map_alert_email_message") {
                    return;
                }
                var rowId = selectionModal.data("gf-alert-row-id");
                if (!rowId) {
                    return;
                }

                if (typeof window.griffinformsSaveAlertEmailMapping === "function") {
                    window.griffinformsSaveAlertEmailMapping(rowId, itemId, itemName, itemHeading);
                }

                selectionModal.modal("hide");
            }

            // Handle selection of an item in the modal list using event delegation
            $(document).on("click", "#<?php echo esc_attr($this->ids['item_list']); ?> .griffinforms-modalitemlist-item", function() {
                var itemId, itemName, itemHeading, itemIcon;
                
                itemId = $(this).attr("data-item-id");
                itemName = $(this).attr("data-item-name") || $(this).find(".griffinforms-modalitemlist-itemname").text();
                itemHeading = $(this).attr("data-item-heading") || itemName;

                handleEmailFieldMessageMapping(itemId, itemName, itemHeading);
                handleAlertEmailMessageMapping(itemId, itemName, itemHeading);

                itemIcon = $(this).find(".griffinforms-modalitemlist-icon").attr("src");

                $("#griffinforms-current-<?php echo esc_attr($this->name); ?>-name").text(itemName);
                $("#griffinforms-current-<?php echo esc_attr($this->name); ?>-name").attr("data-item-id", itemId);
                $("#griffinforms-current-<?php echo esc_attr($this->name); ?>-icon").attr("src", itemIcon);

                // Trigger global event with selection data
                $(document).trigger('griffinforms:itemSelectionChanged', {
                    itemType: '<?php echo esc_js($this->item_type); ?>',
                    itemId: itemId,
                    itemName: itemName,
                    itemHeading: itemHeading
                });
            });
            
            $("#<?php echo esc_attr($this->ids['search_btn']); ?>").click(performSearch);
            $("#<?php echo esc_attr($this->ids['search_input']); ?>").keypress(function(e) {
                if (e.which == 13) {
                    performSearch();
                }
            });
            
            // Handle search submission and reload item list
            function performSearch() {
                var searchValue = getSearchValue();

                if (searchValue === false) {
                    return;
                }

                $("#<?php echo esc_attr($this->ids['load_more']); ?>").css("visibility", "hidden");
                $("#<?php echo esc_attr($this->ids['item_list']); ?>").css("visibility", "hidden");
                $("#<?php echo esc_attr($this->ids['items_loader']); ?>").css("visibility", "visible");
                
                var data = {
                    "action": "sendFoundItems",
                    "name": "<?php echo esc_js($this->name); ?>",
                    "item_type": "<?php echo esc_js($this->item_type); ?>",
                    "search_value": searchValue,
                    "nonce": "<?php echo esc_js($nonce_search); ?>"
                };
                
                $.post(ajaxurl, data, function(response) {
                    $("#<?php echo esc_attr($this->ids['item_list']); ?>").html(response);
                    $("#<?php echo esc_attr($this->ids['item_list']); ?>").css("visibility", "visible");
                    $("#<?php echo esc_attr($this->ids['items_loader']); ?>").css("visibility", "hidden");
                });
            }
            
            $("#<?php echo esc_attr($this->ids['item_list']); ?>").on("click", "#griffinforms-modal-reset<?php echo esc_attr($this->item_type); ?>search", function() {
                resetSearch();
                getItemsForModal(0, "list_empty");
            });
            
            // Retrieves the trimmed value of the search input
            function getSearchValue() {
                var searchValue = $("#<?php echo esc_attr($this->ids['search_input']); ?>").val().trim();
                return searchValue === "" ? false : searchValue;
            }
            
            // Resets the search input field
            function resetSearch() {
                $("#<?php echo esc_attr($this->ids['search_input']); ?>").val("");
            }

            // Highlights the newly added item briefly for visibility
            function highlightNewItem() {
                var newItem = $("#<?php echo esc_attr($this->ids['list_wrap']) ?>").find('.griffinforms-modalitemlist-item').first();
                newItem.addClass('griffinforms-new-item-highlight');
                setTimeout(function() {
                    newItem.removeClass('griffinforms-new-item-highlight');
                }, 3000);
            }

            // Smoothly scrolls the item list to the bottom
            function scrollToBottom() {
                var listWrap = $("#<?php echo esc_attr($this->ids['list_wrap']) ?>"); 
                listWrap.animate({ scrollTop: listWrap[0].scrollHeight }, 600);
            }

            // Truncate a string to 40 chars, with type check
            function truncate(text) {
                if (typeof text !== "string") {
                    return "";
                }
                return text.length > 40 ? text.substring(0, 37) + "..." : text;
            }
        });
        <?php
        $inline_js = ob_get_clean();
        wp_add_inline_script('griffinforms-global-js', $inline_js);
    }
}
