import { Spin } from "antd";
import React, { forwardRef, useCallback, useEffect, useState } from "react";
import { hooks, mediaUtils } from "wp";

import { RouteHttpVerb } from "@devowl-wp/utils";

import { request as utilsRequest } from "../util/index.js";

let addedFilter = false;

/**
 * Some page builders (e.g. Divi) move the `mediaUtils` to the footer and/or after Real Media Library scripts.
 */
function addMediaUploadFilterLazily() {
    const { addFilter } = hooks;
    const { MediaUpload } = mediaUtils;
    if (!addedFilter) {
        addedFilter = true;

        const replaceMediaUpload = () => MediaUpload;

        addFilter(
            "editor.MediaUpload",
            "core/edit-post/components/media-upload/replace-media-upload",
            replaceMediaUpload,
        );
    }

    return MediaUpload;
}

function useMediaAttachment(id) {
    const [fetching, setFetching] = useState(false);
    const [data, setData] = useState();
    const [error, setError] = useState();
    const fetch = useCallback(async (id) => {
        setFetching(true);
        try {
            const result = await utilsRequest({
                location: {
                    path: `/media/:id`,
                    method: RouteHttpVerb.GET,
                    namespace: "wp/v2",
                },
                params: {
                    id,
                },
            });
            setData(result);
            setError(undefined);
        } catch (e) {
            setData(undefined);
            setError(e);
        } finally {
            setFetching(false);
        }
    }, []);

    useEffect(() => {
        if (id) {
            fetch(id);
        } else {
            setData(undefined);
            setError(undefined);
        }
    }, [id]);

    return { fetching, data, fetch, error };
}

const MediaLibrarySelector = forwardRef(({ attachmentId, title, allowedTypes, render, onChange }, ref) => {
    const useAttachmentId = attachmentId || undefined;
    const { data, error, fetching } = useMediaAttachment(useAttachmentId);
    const url = data?.source_url;

    useEffect(() => {
        if (error?.responseJSON?.code === "rest_post_invalid_id") {
            onChange(undefined, undefined);
        }
    }, [error]);

    const MediaUpload = addMediaUploadFilterLazily();

    return (
        <Spin spinning={fetching}>
            <MediaUpload
                ref={ref}
                onSelect={(media) => {
                    onChange?.(media?.id, media);
                }}
                title={title}
                allowedTypes={allowedTypes}
                value={useAttachmentId}
                render={({ open }) =>
                    render({
                        open,
                        reset: () => onChange(undefined, undefined),
                        attachmentId: useAttachmentId,
                        url,
                    })
                }
            />
        </Spin>
    );
});

export { MediaLibrarySelector };
