<?php

namespace GriffinForms\Admin\Html\Modals;

class SelectFolder extends \GriffinForms\Admin\Html\Modals\Format
{
    protected $icon_files = array();

    protected function headerText()
    {
        return __('Select Folder', 'griffinforms-form-builder');
    }

    protected function modalContent()
    {
        $default_icon = $this->getDefaultIconFile();
        $default_icon_url = $this->getFolderIconUrl($default_icon);
        $icon_list = $this->getIconFiles();

        echo '<div class="gf-folder-picker-modal" data-gf-folder-picker-modal="true">';
        echo '<div id="griffinforms-selectfolder-notice" class="gf-notice-container mb-2" aria-live="polite"></div>';

        echo '<div id="griffinforms-selectfolder-view-list" class="gf-folder-picker-view gf-folder-picker-view-list">';
        echo '<div class="gf-folder-picker-toolbar d-flex flex-column flex-lg-row align-items-lg-end gap-2 mb-2">';
        echo '<div class="gf-folder-picker-toolbar-search flex-grow-1">';
        echo '<label for="griffinforms-selectfolder-search" class="form-label small fw-semibold mb-1">' . esc_html__('Search folders', 'griffinforms-form-builder') . '</label>';
        echo '<div class="input-group input-group-sm gf-folder-picker-search-group">';
        echo '<input type="search" id="griffinforms-selectfolder-search" class="form-control" placeholder="' . esc_attr__('Search by name or description', 'griffinforms-form-builder') . '" autocomplete="off" />';
        echo '<button type="button" class="button" id="griffinforms-selectfolder-search-btn">' . esc_html__('Search', 'griffinforms-form-builder') . '</button>';
        echo '</div>';
        echo '<div class="form-text">' . esc_html__('Search begins after 3 characters.', 'griffinforms-form-builder') . '</div>';
        echo '</div>';
        echo '<div class="gf-folder-picker-toolbar-action d-flex justify-content-lg-end">';
        echo '<button type="button" class="button button-secondary" id="griffinforms-selectfolder-add-folder-btn">' . esc_html__('Add Folder', 'griffinforms-form-builder') . '</button>';
        echo '</div>';
        echo '</div>';

        echo '<div id="griffinforms-selectfolder-search-summary" class="small text-muted mb-1"></div>';
        echo '<div id="griffinforms-selectfolder-status" class="small text-muted mb-2"></div>';

        echo '<div id="griffinforms-selectfolder-list-shell" class="gf-folder-picker-list-shell rounded-3 bg-white">';
        echo '<div id="griffinforms-selectfolder-list" class="gf-folder-picker-list"></div>';
        echo '<div id="griffinforms-selectfolder-list-loader" class="gf-folder-picker-list-loader text-center p-3 d-none">';
        echo '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> ';
        echo esc_html__('Loading folders...', 'griffinforms-form-builder');
        echo '</div>';
        echo '<div id="griffinforms-selectfolder-list-empty" class="gf-folder-picker-list-empty text-center text-muted p-4 d-none">';
        echo esc_html__('No folders found.', 'griffinforms-form-builder');
        echo '</div>';
        echo '</div>';
        echo '<div id="griffinforms-selectfolder-loadmore-state" class="small text-muted mt-3 fst-italic d-none">' . esc_html__('No more folders to load.', 'griffinforms-form-builder') . '</div>';
        echo '</div>';

        echo '<div id="griffinforms-selectfolder-view-create" class="gf-folder-picker-view gf-folder-picker-view-create d-none">';
        echo '<div class="d-flex align-items-center justify-content-between gap-3 mb-3">';
        echo '<button type="button" class="components-button is-tertiary has-icon" id="griffinforms-selectfolder-back-btn"><span class="dashicons dashicons-arrow-left-alt2" style="width:16px;height:16px;font-size:16px;margin-right:2px;"></span>' . esc_html__('Back', 'griffinforms-form-builder') . '</button>';
        echo '<div class="small text-muted">' . esc_html__('Create a new folder and assign it immediately.', 'griffinforms-form-builder') . '</div>';
        echo '</div>';

        echo '<div id="griffinforms-selectfolder-create-notice" class="gf-notice gf-notice-danger mb-3 d-none" aria-live="polite"></div>';
        echo '<div class="row g-4 align-items-start">';
        echo '<div class="col-lg-5">';
        echo '<div class="border rounded-3 p-3 bg-white">';
        echo '<div class="fw-semibold mb-2">' . esc_html__('Folder Icon', 'griffinforms-form-builder') . '</div>';
        echo '<div class="text-center mb-3">';
        echo '<img id="griffinforms-selectfolder-icon-preview" src="' . esc_url($default_icon_url) . '" width="96" alt="" />';
        echo '</div>';
        echo '<input type="hidden" id="griffinforms-selectfolder-icon" value="' . esc_attr($default_icon) . '" />';
        echo '<div class="gf-folder-picker-icon-grid">';
        foreach ($icon_list as $icon_file) {
            $icon_url = $this->getFolderIconUrl($icon_file);
            $active = ($icon_file === $default_icon) ? ' is-active' : '';
            echo '<button type="button" class="gf-folder-picker-icon' . esc_attr($active) . '" data-folder-icon="' . esc_attr($icon_file) . '" data-folder-icon-url="' . esc_url($icon_url) . '">';
            echo '<img src="' . esc_url($icon_url) . '" alt="" width="28" height="28" />';
            echo '</button>';
        }
        echo '</div>';
        echo '</div>';
        echo '</div>';

        echo '<div class="col-lg-7">';
        echo '<div class="mb-3">';
        echo '<label for="griffinforms-selectfolder-name" class="form-label fw-semibold">' . esc_html__('Folder name', 'griffinforms-form-builder') . '</label>';
        echo '<input type="text" id="griffinforms-selectfolder-name" class="form-control" maxlength="255" />';
        echo '</div>';
        echo '<div class="mb-3">';
        echo '<label for="griffinforms-selectfolder-description" class="form-label fw-semibold">' . esc_html__('Folder description', 'griffinforms-form-builder') . '</label>';
        echo '<textarea id="griffinforms-selectfolder-description" class="form-control" rows="4" maxlength="2000"></textarea>';
        echo '</div>';
        echo '<div class="small text-muted">' . esc_html__('Add and Assign creates the folder and applies it to the active form or selected forms without returning to the list.', 'griffinforms-form-builder') . '</div>';
        echo '</div>';
        echo '</div>';
        echo '</div>';

        echo '<input type="hidden" id="griffinforms-selectfolder-form-id" value="0" />';
        echo '<input type="hidden" id="griffinforms-selectfolder-form-ids" value="" />';
        echo '<input type="hidden" id="griffinforms-selectfolder-current-folder-id" value="0" />';
        echo '<input type="hidden" id="griffinforms-selectfolder-selected-folder-id" value="" />';
        echo '<input type="hidden" id="griffinforms-selectfolder-selected-folder-name" value="" />';
        echo '<input type="hidden" id="griffinforms-selectfolder-default-icon-url" value="' . esc_attr($default_icon_url) . '" />';
        echo '</div>';
    }

    protected function modalFooter()
    {
        echo '<div class="modal-footer border-top-0 d-flex flex-wrap justify-content-end gap-2">';
        echo '<button type="button" class="button" id="griffinforms-selectfolder-cancel-btn" data-bs-dismiss="modal">' . esc_html__('Cancel', 'griffinforms-form-builder') . '</button>';
        echo '<button type="button" class="button button-primary" id="griffinforms-modalaction-selectfolder">' . esc_html__('Assign Folder', 'griffinforms-form-builder') . '</button>';
        echo '<button type="button" class="button button-primary d-none" id="griffinforms-modalaction-selectfolder-create">' . esc_html__('Add and Assign', 'griffinforms-form-builder') . '</button>';
        echo '</div>';
    }

    protected function getIconFiles(): array
    {
        if (!empty($this->icon_files)) {
            return $this->icon_files;
        }

        $icon_dir = $this->config->getRootPath() . 'admin/images/folder';
        if (!is_dir($icon_dir)) {
            return array();
        }

        $files = array_diff(scandir($icon_dir), array('..', '.', '.DS_Store', 'default.png'));
        $files = array_values(array_filter($files, static function ($file) {
            return is_string($file) && preg_match('/^[0-9]+\.png$/', $file);
        }));
        natsort($files);

        $this->icon_files = array_values($files);
        return $this->icon_files;
    }

    protected function getDefaultIconFile(): string
    {
        $icons = $this->getIconFiles();
        if (!empty($icons)) {
            return (string) $icons[0];
        }

        return 'default.png';
    }

    protected function getFolderIconUrl(string $icon_file): string
    {
        $icon_file = basename($icon_file);
        if ($icon_file === '') {
            $icon_file = 'default.png';
        }

        return $this->config->getRootUrl() . 'admin/images/folder/' . $icon_file;
    }

    public function modalJs()
    {
        $nonce = wp_create_nonce('griffinforms_folder_picker');
        ob_start();
        ?>
        jQuery(function($) {
            const $modal = $("#griffinforms-selectfolder-modal");
            if (!$modal.length) {
                return;
            }

            const endpoints = {
                list: "griffinforms_get_folder_picker_folders",
                assign: "griffinforms_move_form_folder",
                createAssign: "griffinforms_create_folder_and_assign"
            };

            const state = {
                formIds: [],
                currentFolderId: 0,
                selectedFolderId: null,
                search: "",
                offset: 0,
                limit: 20,
                hasMore: false,
                loading: false,
                activeView: "list",
                searchTimer: null,
                defaultIconUrl: $("#griffinforms-selectfolder-default-icon-url").val() || ""
            };

            const nonce = "<?php echo esc_js($nonce); ?>";
            const $notice = $("#griffinforms-selectfolder-notice");
            const $createNotice = $("#griffinforms-selectfolder-create-notice");
            const $listView = $("#griffinforms-selectfolder-view-list");
            const $createView = $("#griffinforms-selectfolder-view-create");
            const $search = $("#griffinforms-selectfolder-search");
            const $searchBtn = $("#griffinforms-selectfolder-search-btn");
            const $searchSummary = $("#griffinforms-selectfolder-search-summary");
            const $status = $("#griffinforms-selectfolder-status");
            const $list = $("#griffinforms-selectfolder-list");
            const $listLoader = $("#griffinforms-selectfolder-list-loader");
            const $listEmpty = $("#griffinforms-selectfolder-list-empty");
            const $loadMoreState = $("#griffinforms-selectfolder-loadmore-state");
            const $formId = $("#griffinforms-selectfolder-form-id");
            const $formIds = $("#griffinforms-selectfolder-form-ids");
            const $currentFolderId = $("#griffinforms-selectfolder-current-folder-id");
            const $folderId = $("#griffinforms-selectfolder-selected-folder-id");
            const $folderName = $("#griffinforms-selectfolder-selected-folder-name");
            const $assignBtn = $("#griffinforms-modalaction-selectfolder");
            const $createAssignBtn = $("#griffinforms-modalaction-selectfolder-create");
            const $backLinkBtn = $("#griffinforms-selectfolder-back-btn");
            const $addFolderBtn = $("#griffinforms-selectfolder-add-folder-btn");
            const $folderNameInput = $("#griffinforms-selectfolder-name");
            const $folderDescriptionInput = $("#griffinforms-selectfolder-description");
            const $iconPreview = $("#griffinforms-selectfolder-icon-preview");
            const $iconInput = $("#griffinforms-selectfolder-icon");
            const rootLabel = "<?php echo esc_js(__('Root', 'griffinforms-form-builder')); ?>";
            const noFolderLabel = "<?php echo esc_js(__('No folder', 'griffinforms-form-builder')); ?>";
            const noDescriptionLabel = "<?php echo esc_js(__('No description', 'griffinforms-form-builder')); ?>";

            function escHtml(value) {
                return String(value === null || typeof value === "undefined" ? "" : value)
                    .replace(/&/g, "&amp;")
                    .replace(/</g, "&lt;")
                    .replace(/>/g, "&gt;")
                    .replace(/"/g, "&quot;")
                    .replace(/'/g, "&#039;");
            }

            function setNotice($target, type, message) {
                const classes = "gf-notice-info gf-notice-success gf-notice-warning gf-notice-danger";
                $target.removeClass(classes).addClass("gf-notice gf-notice-" + type);
                $target.html("<div>" + message + "</div>").removeClass("d-none").show();
            }

            function clearNotice($target) {
                $target.addClass("d-none").empty().hide();
            }

            function clearSearchTimer() {
                if (state.searchTimer) {
                    clearTimeout(state.searchTimer);
                    state.searchTimer = null;
                }
            }

            function updateHiddenFields() {
                $formId.val(state.formIds.length === 1 ? String(state.formIds[0]) : "0");
                $formIds.val(JSON.stringify(state.formIds));
                $currentFolderId.val(String(state.currentFolderId || 0));
                $folderId.val(state.selectedFolderId === null ? "" : String(state.selectedFolderId));
                $folderName.val("");
            }

            function updateActionState() {
                $assignBtn.prop("disabled", !state.formIds.length || state.selectedFolderId === null);
                $createAssignBtn.prop("disabled", !state.formIds.length);
            }

            function showListView() {
                state.activeView = "list";
                $listView.removeClass("d-none");
                $createView.addClass("d-none");
                $assignBtn.removeClass("d-none");
                $createAssignBtn.addClass("d-none");
                $backLinkBtn.addClass("d-none");
                $search.trigger("focus");
            }

            function showCreateView() {
                state.activeView = "create";
                $listView.addClass("d-none");
                $createView.removeClass("d-none");
                $assignBtn.addClass("d-none");
                $createAssignBtn.removeClass("d-none");
                $backLinkBtn.removeClass("d-none");
                clearNotice($createNotice);
                $folderNameInput.trigger("focus");
            }

            function selectIcon($button) {
                if (!$button.length) {
                    return;
                }

                $(".gf-folder-picker-icon").removeClass("is-active");
                $button.addClass("is-active");
                $iconInput.val(String($button.data("folder-icon") || ""));
                $iconPreview.attr("src", String($button.data("folder-icon-url") || state.defaultIconUrl));
            }

            function resetCreateForm() {
                $folderNameInput.val("");
                $folderDescriptionInput.val("");
                clearNotice($createNotice);
                selectIcon($(".gf-folder-picker-icon").first());
            }

            function resetListState() {
                state.offset = 0;
                state.hasMore = false;
                state.loading = false;
                $list.empty();
                $listEmpty.addClass("d-none");
                $loadMoreState.addClass("d-none");
                $searchSummary.empty();
                $status.empty();
            }

            function buildContext(event) {
                const opener = event.relatedTarget ? $(event.relatedTarget) : $();
                let formIds = [];
                let currentFolderId = 0;

                if (opener.length && opener.data("gfFormId")) {
                    const formId = parseInt(opener.data("gfFormId"), 10) || 0;
                    if (formId > 0) {
                        formIds = [formId];
                    }
                    currentFolderId = parseInt(opener.data("gfCurrentFolderId"), 10) || 0;
                } else {
                    formIds = $(".griffinforms-listitem-cb:checked").map(function() {
                        return parseInt(this.value, 10) || 0;
                    }).get().filter(function(id) {
                        return id > 0;
                    });
                }

                return {
                    formIds: formIds,
                    currentFolderId: currentFolderId
                };
            }

            function setContext(context) {
                state.formIds = context.formIds || [];
                state.currentFolderId = parseInt(context.currentFolderId, 10) || 0;
                state.selectedFolderId = state.currentFolderId;
                updateHiddenFields();
                updateActionState();
            }

            function renderRootRow() {
                const selectedClass = state.selectedFolderId === 0 ? " is-selected" : "";
                const html = [
                    '<button type="button" class="gf-folder-picker-row' + selectedClass + '" data-folder-id="0" data-folder-name="' + escHtml(rootLabel) + '">',
                        '<span class="gf-folder-picker-row-icon"><img src="' + escHtml(state.defaultIconUrl) + '" alt="" width="24" height="24" /></span>',
                        '<span class="gf-folder-picker-row-name">' + escHtml(rootLabel) + '</span>',
                        '<span class="gf-folder-picker-row-description text-muted">' + escHtml(noFolderLabel) + '</span>',
                    '</button>'
                ].join("");

                $list.prepend(html);
            }

            function renderFolders(folders, append) {
                if (!append) {
                    $list.empty();
                }

                if (!append && state.search === "") {
                    renderRootRow();
                }

                if (!Array.isArray(folders) || !folders.length) {
                    if (state.search !== "" && state.offset === 0) {
                        $listEmpty.removeClass("d-none");
                    }
                    return;
                }

                folders.forEach(function(folder) {
                    const folderId = parseInt(folder.id, 10) || 0;
                    if (folderId <= 0) {
                        return;
                    }

                    const selectedClass = state.selectedFolderId === folderId ? " is-selected" : "";
                    const folderName = folder.name || "";
                    const folderDescription = folder.description || noDescriptionLabel;
                    const folderIcon = folder.icon_url || state.defaultIconUrl;

                    const html = [
                        '<button type="button" class="gf-folder-picker-row' + selectedClass + '" data-folder-id="' + folderId + '" data-folder-name="' + escHtml(folderName) + '">',
                            '<span class="gf-folder-picker-row-icon"><img src="' + escHtml(folderIcon) + '" alt="" width="24" height="24" /></span>',
                            '<span class="gf-folder-picker-row-name">' + escHtml(folderName) + '</span>',
                            '<span class="gf-folder-picker-row-description text-muted">' + escHtml(folderDescription) + '</span>',
                        '</button>'
                    ].join("");

                    $list.append(html);
                });
            }

            function normalizeResponse(response, failMessage) {
                if (typeof response !== "object") {
                    try {
                        return JSON.parse(response);
                    } catch (e) {
                        return {
                            success: false,
                            data: {
                                message: failMessage
                            }
                        };
                    }
                }

                return response;
            }

            function loadFolders(reset) {
                if (state.loading) {
                    return;
                }

                const search = (state.search || "").trim();
                if (search !== "" && search.length < 3) {
                    $status.text("<?php echo esc_js(__('Search begins after 3 characters.', 'griffinforms-form-builder')); ?>");
                    return;
                }

                state.loading = true;
                $listLoader.removeClass("d-none");
                $loadMoreState.addClass("d-none");
                $listEmpty.addClass("d-none");

                if (reset) {
                    state.offset = 0;
                    $list.empty();
                    if (search === "") {
                        renderRootRow();
                    }
                }

                $.post(ajaxurl, {
                    action: endpoints.list,
                    nonce: nonce,
                    search: search,
                    offset: state.offset,
                    limit: state.limit
                }, function(response) {
                    response = normalizeResponse(response, "<?php echo esc_js(__('Unable to load folders.', 'griffinforms-form-builder')); ?>");
                    if (!response || !response.success) {
                        const message = response && response.data && response.data.message ? response.data.message : "<?php echo esc_js(__('Unable to load folders.', 'griffinforms-form-builder')); ?>";
                        setNotice($notice, "danger", message);
                        state.loading = false;
                        $listLoader.addClass("d-none");
                        return;
                    }

                    const data = response.data || {};
                    const folders = Array.isArray(data.folders) ? data.folders : [];
                    state.hasMore = !!data.has_more;

                    renderFolders(folders, !reset);
                    state.offset += folders.length;

                    if (search !== "") {
                        $status.text(data.message || "");
                        $searchSummary.empty();
                    } else {
                        $status.text(data.message || "<?php echo esc_js(__('Select a folder for the selected forms.', 'griffinforms-form-builder')); ?>");
                        $searchSummary.empty();
                    }

                    if (state.search !== "" && state.offset === 0 && !folders.length) {
                        $listEmpty.removeClass("d-none");
                    }

                    if (!state.hasMore) {
                        $loadMoreState.removeClass("d-none");
                    }

                    if (state.selectedFolderId !== null) {
                        $list.find('.gf-folder-picker-row[data-folder-id="' + state.selectedFolderId + '"]').addClass("is-selected");
                    }

                    updateActionState();
                    state.loading = false;
                    $listLoader.addClass("d-none");
                }).fail(function() {
                    setNotice($notice, "danger", "<?php echo esc_js(__('Unable to load folders.', 'griffinforms-form-builder')); ?>");
                    state.loading = false;
                    $listLoader.addClass("d-none");
                });
            }

            function fetchNextPage() {
                if (state.loading || !state.hasMore || state.activeView !== "list") {
                    return;
                }
                loadFolders(false);
            }

            function selectFolderRow(folderId, folderName) {
                state.selectedFolderId = parseInt(folderId, 10) || 0;
                $folderId.val(String(state.selectedFolderId));
                $folderName.val(folderName || "");
                $list.find(".gf-folder-picker-row").removeClass("is-selected");
                $list.find('.gf-folder-picker-row[data-folder-id="' + state.selectedFolderId + '"]').addClass("is-selected");
                updateActionState();
            }

            function finishAndRefresh() {
                $modal.modal("hide");
                if ($("#griffinforms-app-rightsidebar").length && state.formIds.length === 1) {
                    document.dispatchEvent(new CustomEvent("form-updated"));
                    return;
                }

                setTimeout(function() {
                    location.reload();
                }, 150);
            }

            function assignFolder(folderId) {
                if (!state.formIds.length) {
                    setNotice($notice, "danger", "<?php echo esc_js(__('Please select at least one form first.', 'griffinforms-form-builder')); ?>");
                    return;
                }

                $assignBtn.prop("disabled", true);
                setNotice($notice, "info", "<?php echo esc_js(__('Updating folder...', 'griffinforms-form-builder')); ?>");

                $.post(ajaxurl, {
                    action: endpoints.assign,
                    nonce: nonce,
                    form_id: state.formIds.length === 1 ? state.formIds[0] : 0,
                    form_ids: state.formIds,
                    folder_id: folderId
                }, function(response) {
                    response = normalizeResponse(response, "<?php echo esc_js(__('Unable to update folder.', 'griffinforms-form-builder')); ?>");
                    if (response && response.success) {
                        finishAndRefresh();
                        return;
                    }

                    const message = response && response.data && response.data.message ? response.data.message : "<?php echo esc_js(__('Unable to update folder.', 'griffinforms-form-builder')); ?>";
                    setNotice($notice, "danger", message);
                    $assignBtn.prop("disabled", false);
                }).fail(function() {
                    setNotice($notice, "danger", "<?php echo esc_js(__('Unable to update folder.', 'griffinforms-form-builder')); ?>");
                    $assignBtn.prop("disabled", false);
                });
            }

            function createAndAssignFolder() {
                if (!state.formIds.length) {
                    setNotice($createNotice, "danger", "<?php echo esc_js(__('Please select at least one form first.', 'griffinforms-form-builder')); ?>");
                    return;
                }

                const name = ($folderNameInput.val() || "").trim();
                const description = ($folderDescriptionInput.val() || "").trim();
                const icon = ($iconInput.val() || "").trim() || "1";

                if (!name) {
                    setNotice($createNotice, "danger", "<?php echo esc_js(__('Please enter folder name.', 'griffinforms-form-builder')); ?>");
                    return;
                }

                $createAssignBtn.prop("disabled", true);
                setNotice($createNotice, "info", "<?php echo esc_js(__('Creating folder...', 'griffinforms-form-builder')); ?>");

                $.post(ajaxurl, {
                    action: endpoints.createAssign,
                    nonce: nonce,
                    name: name,
                    description: description,
                    icon: icon,
                    form_id: state.formIds.length === 1 ? state.formIds[0] : 0,
                    form_ids: state.formIds
                }, function(response) {
                    response = normalizeResponse(response, "<?php echo esc_js(__('Unable to create folder.', 'griffinforms-form-builder')); ?>");
                    if (response && response.success) {
                        finishAndRefresh();
                        return;
                    }

                    const message = response && response.data && response.data.message ? response.data.message : "<?php echo esc_js(__('Unable to create folder.', 'griffinforms-form-builder')); ?>";
                    setNotice($createNotice, "danger", message);
                    $createAssignBtn.prop("disabled", false);
                }).fail(function() {
                    setNotice($createNotice, "danger", "<?php echo esc_js(__('Unable to create folder.', 'griffinforms-form-builder')); ?>");
                    $createAssignBtn.prop("disabled", false);
                });
            }

            $modal.on("show.bs.modal", function(event) {
                clearNotice($notice);
                clearNotice($createNotice);
                clearSearchTimer();
                state.search = "";
                state.selectedFolderId = null;
                state.currentFolderId = 0;
                setContext(buildContext(event));
                $search.val("");
                resetCreateForm();
                resetListState();

                if (!state.formIds.length) {
                    setNotice($notice, "danger", "<?php echo esc_js(__('Please select at least one form first.', 'griffinforms-form-builder')); ?>");
                    showListView();
                    updateActionState();
                    return;
                }

                showListView();
                loadFolders(true);
            });

            $modal.on("hidden.bs.modal", function() {
                clearNotice($notice);
                clearNotice($createNotice);
                clearSearchTimer();
                state.formIds = [];
                state.currentFolderId = 0;
                state.selectedFolderId = null;
                state.search = "";
                state.offset = 0;
                state.hasMore = false;
                state.loading = false;
                state.activeView = "list";
                $search.val("");
                $searchSummary.empty();
                $status.empty();
                $list.empty();
                $listEmpty.addClass("d-none");
                $loadMoreState.addClass("d-none");
                $assignBtn.prop("disabled", true).removeClass("d-none");
                $createAssignBtn.prop("disabled", false).addClass("d-none");
                $backLinkBtn.addClass("d-none");
                $createView.addClass("d-none");
                $listView.removeClass("d-none");
                resetCreateForm();
                updateHiddenFields();
            });

            $modal.on("click", ".gf-folder-picker-row", function() {
                const folderId = parseInt($(this).data("folder-id"), 10) || 0;
                selectFolderRow(folderId, String($(this).data("folder-name") || ""));
            });

            $modal.on("click", ".gf-folder-picker-icon", function() {
                selectIcon($(this));
            });

            $list.on("scroll", function() {
                if (this.scrollTop + this.clientHeight >= this.scrollHeight - 24) {
                    fetchNextPage();
                }
            });

            $search.on("input", function() {
                clearSearchTimer();
                state.searchTimer = setTimeout(function() {
                    state.search = ($search.val() || "").trim();
                    resetListState();

                    if (state.search === "") {
                        loadFolders(true);
                        return;
                    }

                    if (state.search.length < 3) {
                        $status.text("<?php echo esc_js(__('Search begins after 3 characters.', 'griffinforms-form-builder')); ?>");
                        return;
                    }

                    loadFolders(true);
                }, 300);
            });

            $searchBtn.on("click", function() {
                $search.trigger("input");
            });

            $addFolderBtn.on("click", function() {
                clearNotice($createNotice);
                showCreateView();
            });

            $backLinkBtn.on("click", function() {
                resetCreateForm();
                showListView();
            });

            $assignBtn.on("click", function() {
                assignFolder(state.selectedFolderId === null ? 0 : state.selectedFolderId);
            });

            $createAssignBtn.on("click", function() {
                createAndAssignFolder();
            });
        });
        <?php
        wp_add_inline_script('griffinforms-global-js', ob_get_clean());
    }
}
