import { Form, Input, Spin } from "antd";
import { useCallback, useState } from "react";

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

import { useFormService } from "../../../../../contexts/formService.js";
import { useI18n } from "../../../../../contexts/i18n.js";
import { FormValueDifferFromTemplateTag } from "../../../valueDifferFromTemplateTag.js";

import type { FormServiceValueProps } from "../../../../../types/formService.js";
import type { FC } from "react";

const FormServiceFieldGeneralName: FC = () => {
    const { __ } = useI18n();
    const { hasServiceByUniqueName } = useFormService();
    const [ref, setRef] = useState<HTMLParagraphElement>();
    const [hover, setHover] = useState(false);
    const [uniqueNameValidating, setUniqueNameValidating] = useState(false);

    const validateUniqueName = useCallback(
        async (slug: string, overwrite?: (uniqueName: string) => void) => {
            setUniqueNameValidating(true);

            try {
                const found = slug ? await hasServiceByUniqueName(slug) : false;
                if (found) {
                    if (!overwrite) {
                        throw __("A service with the same unique name already exists.");
                    } else {
                        // Consent Forwarding is deactivated, so we need to generate an unique name for the user
                        const matchRegexp = /^(.*)-(\d+)$/;
                        let uniqueName = slug;
                        let foundGenerated: boolean = found;
                        while (foundGenerated) {
                            uniqueName = uniqueName.match(matchRegexp)
                                ? uniqueName.replace(matchRegexp, (_, g1, g2) => `${g1}-${+g2 + 1}`)
                                : `${uniqueName}-1`;
                            foundGenerated = await hasServiceByUniqueName(uniqueName);
                        }

                        // Overwrite in form
                        overwrite(uniqueName);
                    }
                }
            } finally {
                setUniqueNameValidating(false);
            }
        },
        [hasServiceByUniqueName],
    );

    return (
        <Form.Item<FormServiceValueProps> label={__("Name")} required>
            <Form.Item<FormServiceValueProps>
                name="name"
                noStyle
                rules={[{ required: true, message: __("Please provide a name!") }]}
            >
                <Input />
            </Form.Item>
            <Spin spinning={uniqueNameValidating}>
                <div
                    onMouseEnter={() => setHover(true)}
                    onMouseLeave={() => setHover(false)}
                    style={{ marginTop: "-1px", opacity: hover ? 1 : 0.7, transition: "opacity 200ms" }}
                >
                    <Form.Item<FormServiceValueProps>
                        noStyle
                        shouldUpdate={(prevValues, nextValues) => prevValues.name !== nextValues.name}
                    >
                        {({ getFieldValue, setFieldsValue }) => {
                            const name = getFieldValue("name") as FormServiceValueProps["name"];
                            const nameSlug = slugify(name);

                            return (
                                <Form.Item
                                    name="uniqueName"
                                    noStyle
                                    validateTrigger="onBlur"
                                    rules={[
                                        {
                                            validator: async (rules, value) =>
                                                validateUniqueName(value, (uniqueName) =>
                                                    setFieldsValue({ uniqueName }),
                                                ),
                                        },
                                    ]}
                                >
                                    <Input addonBefore={__("Unique identifier")} placeholder={nameSlug} size="small" />
                                </Form.Item>
                            );
                        }}
                    </Form.Item>
                </div>
            </Spin>
            <p className="description" ref={setRef}>
                <FormValueDifferFromTemplateTag
                    form="service"
                    valueName="name"
                    widthOfRef={ref}
                    renderDiff={(value) => <Input value={value} readOnly />}
                />
                {__(
                    'Each service used should have a descriptive name that is understandable to a non-professional user. Example: "Google Analytics". In addition, each service must have a unique identifier that you use for e.g. consent forwarding or the developer API (automatically generated if empty).',
                )}
            </p>
        </Form.Item>
    );
};

export { FormServiceFieldGeneralName };
