import $ from "jquery";
import { useCallback, useLayoutEffect } from "react";

import { message } from "@devowl-wp/react-folder-tree";
import { RatingPointer } from "@devowl-wp/real-utils";

import { CLASS_NAME_APPEND } from "./usePostDraggable.js";
import { useStores } from "../../store/stores.js";
import { __, _n } from "../../utils/i18n.js";
import { request } from "../../utils/request.js";
import { locationRestPostsBulkMovePut } from "../../wp-api/postsBulkMove.put.js";

import type { usePostDraggable } from "./usePostDraggable.js";
import type {
    ParamsRoutePostsBulkMovePut,
    RequestRoutePostsBulkMovePut,
    ResponseRoutePostsBulkMovePut,
} from "../../wp-api/postsBulkMove.put.js";

/**
 * Enables / refresh the droppable nodes. If a draggable item is dropped
 * here the given posts are moved to the category. You have to provide a ReactJS
 * element to reload the tree.
 */
function usePostDroppable(id: string, makeDraggable: ReturnType<typeof usePostDraggable>) {
    const { treeStore, optionStore } = useStores();
    const {
        others: { tableCheckboxName },
    } = optionStore;

    const makeDroppable = useCallback(
        () =>
            $(`#${id} .aiot-node.aiot-droppable`).droppable({
                activeClass: "aiot-state-default",
                hoverClass: "aiot-state-hover",
                tolerance: "pointer",
                async drop(event, ui) {
                    const ids: number[] = [];
                    const to = +$(event.target).attr("data-id");
                    const removeElements: Array<JQuery<HTMLElement>> = [];
                    const isCopy = $("body").hasClass(CLASS_NAME_APPEND);
                    const taxonomy = $(event.target).parents(".aiot-tree").attr("data-tax");
                    const elementsIterate = function (cb: (obj: JQuery<HTMLElement>) => void) {
                        for (let i = 0; i < removeElements.length; i++) {
                            cb(removeElements[i]);
                        }
                    };
                    const iterateChecked = function (
                        elem: JQuery<HTMLElement>,
                        cb: (obj: JQuery<HTMLElement>) => void,
                    ) {
                        // List-mode
                        const trs = $(`input[name="${tableCheckboxName}"]:checked`);

                        // Multiselect
                        if (trs.length) {
                            trs.each(function () {
                                cb($(this).parents("tr"));
                            });
                        } else {
                            // One selected
                            cb(elem);
                        }
                    };

                    // Parse the item ids and remove them
                    iterateChecked(ui.draggable.parents("tr"), (tr) => {
                        ids.push(parseInt(tr.find(`input[name="${tableCheckboxName}"]`).attr("value"), 10));
                        removeElements.push(tr);
                    });

                    // The function to progress the move
                    elementsIterate((obj) => $(obj).fadeTo(250, 0.3));

                    const i18nProps = {
                        count: ids.length,
                        category: $(event.target).find(".aiot-node-name").html(),
                    };

                    const hide = message.loading(
                        isCopy
                            ? _n(
                                  "Copying post to %(category)s...",
                                  "Copying %(count)d posts to %(category)s...",
                                  ids.length,
                                  i18nProps,
                              )
                            : _n(
                                  "Moving post to %(category)s...",
                                  "Moving %(count)d posts to %(category)s...",
                                  ids.length,
                                  i18nProps,
                              ),
                    );
                    try {
                        await request<
                            RequestRoutePostsBulkMovePut,
                            ParamsRoutePostsBulkMovePut,
                            ResponseRoutePostsBulkMovePut
                        >({
                            location: locationRestPostsBulkMovePut,
                            request: {
                                ids,
                                isCopy,
                                taxonomy,
                                to,
                            },
                        });
                        hide();

                        // Show rating pointer
                        const { isRatable, slug } = optionStore;
                        isRatable && new RatingPointer(slug, $(event.target as HTMLElement));

                        message.success(
                            isCopy
                                ? _n(
                                      "Post successfully copied.",
                                      "%(count)d posts successfully copied.",
                                      ids.length,
                                      i18nProps,
                                  )
                                : _n(
                                      "Post successfully moved.",
                                      "%(count)d posts successfully moved.",
                                      ids.length,
                                      i18nProps,
                                  ),
                        );
                        treeStore.fetchTree();

                        // Update WP Table
                        if (isCopy) {
                            // Reload the WP List table
                            $.get(window.location.href, {}, (response) => {
                                const doc = $(response);
                                const tableRows = doc.find(".wp-list-table tbody tr");
                                if (tableRows.length) {
                                    let postId;
                                    let tableRow;
                                    elementsIterate((obj) => {
                                        postId = $(obj).attr("id");
                                        tableRow = doc.find(`#${postId}`);
                                        $(obj).replaceWith(tableRow);
                                    });

                                    // Reinit draggable
                                    makeDraggable();
                                }
                            });
                        } else {
                            // Remove items
                            elementsIterate((obj) => $(obj).remove());
                        }

                        // Add no media
                        if (!$(".wp-list-table tbody tr").length) {
                            $(".wp-list-table tbody").html(
                                `<tr class="no-items"><td class="colspanchange" colspan="6">${__(
                                    "No entries",
                                )}</td></tr></tbody>`,
                            );
                        }
                    } catch (e) {
                        console.log(e);
                        // Usually there should be no error... Silence is golden.
                    }
                },
            }),
        [id, treeStore, optionStore, tableCheckboxName],
    );

    useLayoutEffect(
        useCallback(() => {
            makeDroppable();
        }, [makeDroppable]),
    );

    return makeDroppable;
}

export { usePostDroppable };
