import { Form, Tag } from "antd";
import { useCallback, useEffect, useLayoutEffect, useState } from "react";

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

import { FormServiceLayout } from "./layout.js";
import { FORM_VALUE_DIFFER_FROM_PRESET_TAG_APPLY_EVENT } from "./valueDifferFromTemplateTag.js";
import { useFormContentBlocker } from "../../contexts/formContentBlocker.js";
import { useFormService } from "../../contexts/formService.js";
import { useI18n } from "../../contexts/i18n.js";
import { Notices } from "../common/notices.js";

import type { FC, MutableRefObject } from "react";

const FORM_VALUE_DIFFER_FROM_PRESET_NOTICE_PSEUDO_ELEMENT_CLASS_NAME = "rcb-value-differ-from-template-pseudo";

const FormValueDifferFromTemplateNotice: FC<{
    containerRef: MutableRefObject<HTMLElement>;
    /**
     * If given, this button will always be displayed independent of current template version
     * to reset the form to latest template values. You need to `display:none` the link to avoid
     * flickering as the link gets automatically shown through this component.
     */
    resetButton?: MutableRefObject<HTMLAnchorElement>;
    /**
     * The event name which should be listened to instead of `click`. This allows you to wrap your
     * link with a `Popconfirm`.
     *
     * Default: `click`.
     */
    resetButtonEvent?: string;
    form: "service" | "blocker";
}> = ({ containerRef, resetButton, resetButtonEvent = "click", form }) => {
    const { __, _i } = useI18n();
    const { isTemplateUpdate } = form === "service" ? useFormService() : useFormContentBlocker();
    const [pseudoElements, setPseudoElements] = useState<HTMLSpanElement[]>([]);
    const [applied, setApplied] = useState(false);

    const updatePseudoElements = useCallback(() => {
        if (containerRef.current) {
            const p = [
                ...(containerRef.current.querySelectorAll(
                    `.${FORM_VALUE_DIFFER_FROM_PRESET_NOTICE_PSEUDO_ELEMENT_CLASS_NAME}`,
                ) as unknown as HTMLSpanElement[]),
            ];
            setPseudoElements(p);
            return p;
        }
        return [];
    }, [applied]);

    useLayoutEffect(() => {
        const interval = setInterval(updatePseudoElements, 800);
        waitObject(() => containerRef.current, 100).then(updatePseudoElements);

        document.addEventListener(FORM_VALUE_DIFFER_FROM_PRESET_TAG_APPLY_EVENT, updatePseudoElements);

        return () => {
            clearInterval(interval);
            document.removeEventListener(FORM_VALUE_DIFFER_FROM_PRESET_TAG_APPLY_EVENT, updatePseudoElements);
        };
    }, []);

    const handleApply = () => {
        const p = updatePseudoElements();
        p.forEach((p) => p.click());
        setPseudoElements([]);
        setApplied(true);

        if (p.length > 0) {
            // Run again as some fields can have conditional differences (e.g. dataProcessingInCountriesSpecialTreatments)
            setTimeout(handleApply, 0);
        }
    };

    useEffect(() => {
        if (resetButton?.current) {
            const { current: resetButtonElement } = resetButton;

            if (pseudoElements.length > 0) {
                resetButtonElement.style.removeProperty("display");
            } else {
                resetButtonElement.style.display = "none";
            }

            resetButtonElement.addEventListener(resetButtonEvent, handleApply);

            return () => resetButtonElement.removeEventListener(resetButtonEvent, handleApply);
        }

        return () => {
            // Silence is golden.
        };
    }, [resetButton, resetButtonEvent, pseudoElements.length]);

    return isTemplateUpdate && (pseudoElements.length > 0 || applied) ? (
        <Form.Item
            wrapperCol={{ offset: FormServiceLayout.labelCol.span, span: FormServiceLayout.wrapperCol.span }}
            style={{ marginBottom: 0 }}
        >
            <Notices
                notices={[
                    {
                        severity: "info",
                        message: (
                            <>
                                {_i(
                                    __(
                                        "The template has been updated to provide current legal and technical information. Fields with outdated values or values you manually adjusted are marked with {{tag/}}. You can apply all changes with one click!",
                                    ),
                                    { tag: <Tag color="blue">{__("Differing from template")}</Tag> },
                                )}
                                <br />
                                <a
                                    className={`button ${
                                        pseudoElements.length === 0 && applied ? "button-disabled" : ""
                                    }`}
                                    onClick={handleApply}
                                    style={{ marginTop: 5 }}
                                >
                                    {pseudoElements.length === 0 && applied ? __("Applied!") : __("Use default values")}
                                </a>
                            </>
                        ),
                    },
                ]}
            />
        </Form.Item>
    ) : null;
};

export { FORM_VALUE_DIFFER_FROM_PRESET_NOTICE_PSEUDO_ELEMENT_CLASS_NAME, FormValueDifferFromTemplateNotice };
