import { Form, Image, Modal, Skeleton, Spin } from "antd";
import { observer } from "mobx-react";
import { useCallback, useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";

import type { FormContentBlockerValueProps } from "@devowl-wp/react-cookie-banner-admin";
import {
    FormContentBlocker,
    FormContentBlockerLayout,
    useFormContentBlockerHandler,
    useFormContentBlockerProvider,
} from "@devowl-wp/react-cookie-banner-admin";
import { scrollTo } from "@devowl-wp/react-utils";

import { BlockerFormNoticeNoneExistingCookies } from "./noticeNoneExistingCookies.js";
import { BlockerFormNoticeNoneExistingTcfVendors } from "./noticeNoneExistingTcfVendors.js";
import { useRouteBlocker } from "../../../hooks/useRouteBlocker.js";
import { BlockerModel } from "../../../models/blockerModel.js";
import { useStores } from "../../../store/stores.js";
import { __ } from "../../../utils/i18n.js";
import { MediaLibrarySelector } from "../../mediaLibrarySelector.js";
import { PostTypeSelect } from "../../postTypeSelect.js";
import { ConfigContent } from "../content.js";
import { CookieEditForm } from "../cookies/form.js";

import type { TcfVendorConfigurationModel } from "../../../models/tcfVendorConfigurationModel.js";
import type { ComponentProps, FC } from "react";

const BlockerEditForm: FC<{
    template?: { identifier: string; version: number };
    overwriteAttributes?: Parameters<typeof useFormContentBlockerHandler>["0"]["attributes"];
    navigateAfterCreation?: boolean | string;
    comingFromServiceCreation?: boolean;
}> = observer(({ template, overwriteAttributes, navigateAfterCreation = true, comingFromServiceCreation = false }) => {
    const { blocker, id, queried, fetched, link } = useRouteBlocker();
    const navigate = useNavigate();
    const [isCreatingNewCookie, setIsCreatingNewCookie] = useState(false);
    const {
        cookieStore,
        tcfStore,
        optionStore: {
            isTcf,
            others: { isPro },
        },
    } = useStores();
    const templateModel = blocker?.templateModel || cookieStore.templatesBlocker.get(template?.identifier);
    const { declarations } = tcfStore;

    const {
        prompt,
        form,
        isBusy,
        defaultValues,
        nonExistingServices,
        nonExistingTcfVendors,
        onFinish,
        onFinishFailed,
        onValuesChange,
        contextValue,
    } = useFormContentBlockerHandler({
        attributes: overwriteAttributes,
        isTcf,
        isEdit: fetched,
        entityTemplateVersion: blocker?.data?.meta?.presetVersion,
        template: templateModel?.use,
        initialHasChanges: comingFromServiceCreation,
        handleSave: async (values) => {
            try {
                const { name, status, description, succeessorDeletionCheck, ...meta } = values;
                const newMeta = {
                    ...meta,
                    visualMediaThumbnail: meta.visualMediaThumbnail || 0,
                    criteria: meta.criteria,
                    tcfVendors: meta.tcfVendors?.join(",") || "",
                    tcfPurposes: meta.tcfPurposes?.join(",") || "",
                    services: meta.services?.join(",") || "",
                    isVisual: meta.criteria === "services" ? meta.isVisual : false,
                    presetId: templateModel?.data.identifier,
                    presetVersion: templateModel?.data.version,
                };

                delete newMeta.templateCheck;

                if (queried) {
                    blocker.setName(name);
                    blocker.setStatus(status);
                    blocker.setDescription(description);
                    blocker.setMeta(newMeta);
                    await blocker.patch();
                } else {
                    const draft = new BlockerModel(blockers, {
                        title: {
                            raw: name,
                        },
                        content: {
                            raw: description,
                            protected: false,
                        },
                        status,
                        meta: newMeta,
                    });
                    await draft.persist();

                    // Delete successor-relevant services
                    if (succeessorDeletionCheck) {
                        const successorOfIds = templateModel.data.consumerData.successorOf.map(({ id }) => id);
                        const allBlockerModels = [...cookieStore.blockers.entries.values()];

                        const deleteModels = successorOfIds.map(
                            (id) =>
                                allBlockerModels.find(({ key }) => key === id) ||
                                new BlockerModel(cookieStore.blockers, { id }),
                        );

                        await Promise.allSettled(deleteModels.map((m) => m.delete()));
                    }
                }

                return () =>
                    navigateAfterCreation &&
                    (typeof navigateAfterCreation === "string"
                        ? (window.location.href = navigateAfterCreation)
                        : navigate(link.slice(1)));
            } catch (e) {
                throw (e as any).responseJSON.message;
            }
        },
    });
    const notReady = (queried && !fetched) || (templateModel && !templateModel.use);
    const [FormContentBlockerProvider, formContentBlockerContextValue] = useFormContentBlockerProvider(
        {
            ...contextValue,
            tcfPurposes: Object.values(declarations?.purposes || []),
        },
        {},
        { deps: [notReady] },
    );

    const { blockers, essentialGroup } = cookieStore;

    const initialValues: FormContentBlockerValueProps = fetched
        ? {
              name: blocker.data.title.raw,
              status: blocker.data.status as FormContentBlockerValueProps["status"],
              description: blocker.data.content.raw,
              criteria: blocker.data.meta.criteria as BlockerModel["data"]["meta"]["criteria"],
              rules: blocker.data.meta.rules,
              tcfVendors: blocker.tcfVendors,
              tcfPurposes: blocker.tcfPurposes,
              services: blocker.services,
              isVisual: blocker.data.meta.isVisual,
              visualType: isPro ? blocker.data.meta.visualType : "default",
              visualMediaThumbnail: blocker.data.meta.visualMediaThumbnail,
              visualContentType: blocker.data.meta.visualContentType,
              isVisualDarkMode: blocker.data.meta.isVisualDarkMode,
              visualBlur: blocker.data.meta.visualBlur,
              visualDownloadThumbnail: blocker.data.meta.visualDownloadThumbnail,
              visualHeroButtonText: blocker.data.meta.visualHeroButtonText,
              shouldForceToShowVisual: blocker.data.meta.shouldForceToShowVisual,
              templateCheck: undefined,
              succeessorDeletionCheck: undefined,
          }
        : defaultValues;

    // Automatically add created items to the dropdown
    const handleCreatedService: ComponentProps<typeof BlockerFormNoticeNoneExistingCookies>["onCreated"] = useCallback(
        (model) => {
            form.setFieldsValue({
                services: [...form.getFieldValue("services"), model.key],
            });
        },
        [form],
    );

    // Automatically add created items to the dropdown
    const handleCreatedTcfVendor: ComponentProps<typeof BlockerFormNoticeNoneExistingTcfVendors>["onCreated"] =
        useCallback(
            (model) => {
                form.setFieldsValue({
                    tcfVendors: [...form.getFieldValue("tcfVendors"), model.key],
                });
            },
            [form],
        );

    // Initially load the blocker if not yet done
    useEffect(() => {
        if (queried && !fetched) {
            blockers.getSingle({
                params: {
                    id,
                    context: "edit",
                },
            });
        }
    }, [queried, fetched]);

    useEffect(() => {
        if (templateModel && !templateModel.use && !templateModel.busy) {
            templateModel.fetchUse();
        }
    }, [templateModel]);

    // Scroll to top when opening the form
    useEffect(() => {
        scrollTo(0);

        // Ensure the groups are loaded
        if (!essentialGroup) {
            cookieStore.fetchGroups();
        }
    }, []);

    useEffect(() => {
        // Ensure the TCF declarations are loaded
        if (!declarations && isTcf) {
            tcfStore.fetchDeclarations();
        }
    }, [isTcf, declarations]);

    if (notReady) {
        return (
            <ConfigContent maxWidth="fixed">
                <Skeleton active paragraph={{ rows: 8 }} />
            </ConfigContent>
        );
    }

    return (
        <ConfigContent maxWidth="fixed">
            <FormContentBlockerProvider value={formContentBlockerContextValue}>
                <Spin spinning={isBusy || templateModel?.busy || false}>
                    {prompt}
                    <Form
                        name={`blocker-${id}`}
                        form={form}
                        {...FormContentBlockerLayout}
                        initialValues={initialValues}
                        onFinish={onFinish}
                        onFinishFailed={onFinishFailed}
                        onValuesChange={onValuesChange}
                        scrollToFirstError={{ behavior: "smooth", block: "center" }}
                        labelWrap
                    >
                        <FormContentBlocker
                            technicalProps={{
                                servicesFieldProps: {
                                    dropdown: (
                                        <PostTypeSelect
                                            postType={["rcb-cookie"]}
                                            multiple
                                            filter={(d) => (d as any)["rcb-cookie-group"][0] !== essentialGroup?.key}
                                        />
                                    ),
                                    children: (
                                        <>
                                            <button
                                                type="button"
                                                className="button"
                                                onClick={() => setIsCreatingNewCookie(true)}
                                            >
                                                {__("Create new service")}
                                            </button>
                                            <Modal
                                                key={id}
                                                open={isCreatingNewCookie}
                                                title={__("Add service")}
                                                width="calc(100% - 50px)"
                                                bodyStyle={{ paddingBottom: 0 }}
                                                footer={null}
                                                onCancel={() => setIsCreatingNewCookie(false)}
                                            >
                                                <CookieEditForm
                                                    navigateAfterCreation={false}
                                                    scrollToTop={false}
                                                    onCreated={(model) => {
                                                        setIsCreatingNewCookie(false);
                                                        handleCreatedService(model);
                                                    }}
                                                />
                                            </Modal>
                                            <BlockerFormNoticeNoneExistingCookies
                                                nonExistingServices={nonExistingServices}
                                                onCreated={handleCreatedService}
                                            />
                                        </>
                                    ),
                                },
                                tcfVendorsFieldProps: {
                                    dropdownVendors: (
                                        <PostTypeSelect
                                            postType={["rcb-tcf-vendor-conf"]}
                                            multiple
                                            titleRender={
                                                (({ vendor: { name } }: TcfVendorConfigurationModel["data"]) =>
                                                    name) as any
                                            }
                                        />
                                    ),
                                    children: (
                                        <BlockerFormNoticeNoneExistingTcfVendors
                                            nonExistingTcfVendors={nonExistingTcfVendors}
                                            onCreated={handleCreatedTcfVendor}
                                        />
                                    ),
                                },
                            }}
                            visualProps={{
                                visualMediaThumbnailPicker: (
                                    <MediaLibrarySelector
                                        title={__("Select preview image")}
                                        allowedTypes={["image"]}
                                        render={({ open, reset, attachmentId, url }) => (
                                            <>
                                                <p style={{ marginTop: 0 }}>
                                                    <a className="button" onClick={open}>
                                                        {attachmentId
                                                            ? __("Replace image")
                                                            : __("Select from media library")}
                                                    </a>
                                                    &nbsp;
                                                    {attachmentId && (
                                                        <a className="button" onClick={reset}>
                                                            {__("Remove image")}
                                                        </a>
                                                    )}
                                                </p>
                                                {url && <Image width={272} src={url} />}
                                            </>
                                        )}
                                    />
                                ),
                            }}
                        />
                    </Form>
                </Spin>
            </FormContentBlockerProvider>
        </ConfigContent>
    );
});

export { BlockerEditForm };
