import { useMutation, useQueryClient } from "@tanstack/react-query";
import { AxiosError } from "axios";
import {
    AttributeSchema,
    CreateAttributeSchema,
    HttpValidationError,
    ModuleSchemaOutput,
    UpdateAttributeSchema,
} from "@/lib/client";
import {
    addAttributeToModuleMutation,
    createAttributeMutation,
    deleteAttributeMutation,
    removeAttributeFromModuleMutation,
    updateAttributeLabelMutation,
    updateAttributeMutation,
} from "@/lib/client/@tanstack/react-query.gen";
import { notifications } from "@/lib/notifications";

type Props = {
    module?: ModuleSchemaOutput;
    refetchModule?: () => void;
    refetchAttributes: () => void;
};

type AttributesCrud = {
    onToggleAttributeInModule: (
        attribute: AttributeSchema,
        isAdding: boolean
    ) => void;
    onUpdateLabel: (attributeId: number, name: string) => void;
    onCreate: (attribute: CreateAttributeSchema) => void;
    onUpdate: (attributeId: number, values: UpdateAttributeSchema) => void;
    onDelete: (attributeId: number) => void;
};

const useAttributesCrud = ({
    module,
    refetchModule,
    refetchAttributes,
}: Props): AttributesCrud => {
    const queryClient = useQueryClient();

    const onError = (error: AxiosError<HttpValidationError>) => {
        console.error(error);
        notifications.error({
            message: error.response?.data?.detail as string | undefined,
        });
    };

    const addAttrToModuleMutation = useMutation({
        ...addAttributeToModuleMutation(),
        onError,
    });

    const removeAttrFromModuleMutation = useMutation({
        ...removeAttributeFromModuleMutation(),
        onError,
    });

    const removeGetDealModuleAttrQuery = () => {
        if (!module) return;

        queryClient.removeQueries({
            predicate: query => {
                const key = query.queryKey[0] as {
                    _id?: string;
                    path?: { moduleId?: number };
                };
                return (
                    key?._id === "getDealModuleAttributes" &&
                    key?.path?.moduleId === module.id
                );
            },
        });
    };

    const onToggleAttributeInModule = (
        attribute: AttributeSchema,
        isAdding: boolean
    ) => {
        if (!module) return;
        const mutation = isAdding
            ? addAttrToModuleMutation
            : removeAttrFromModuleMutation;

        mutation.mutate(
            {
                path: {
                    moduleId: module.id,
                    attributeId: attribute.id,
                },
            },
            {
                onSuccess: ({ message }) => {
                    notifications.success({ message });
                    refetchModule && refetchModule();
                    refetchAttributes();
                    removeGetDealModuleAttrQuery();
                },
            }
        );
    };

    const updateAttrLabelMutation = useMutation({
        ...updateAttributeLabelMutation(),
        onError,
        onSuccess: refetchModule,
    });

    const onUpdateLabel = (attributeId: number, name: string) => {
        if (!module) return;

        updateAttrLabelMutation.mutate({
            body: {
                moduleId: module.id,
                attributeId,
                label: name,
            },
        });
    };

    const createAttrMutation = useMutation({
        ...createAttributeMutation(),
        onError,
        onSuccess: refetchAttributes,
    });

    const onCreate = (values: CreateAttributeSchema) => {
        createAttrMutation.mutate({
            body: {
                entity: values,
            },
        });
    };

    const updateAttrMutation = useMutation({
        ...updateAttributeMutation(),
        onError,
        onSuccess: () => {
            refetchModule && refetchModule();
            refetchAttributes();
        },
    });

    const onUpdate = (attributeId: number, values: UpdateAttributeSchema) => {
        updateAttrMutation.mutate({
            path: {
                pk: attributeId,
            },
            body: {
                entity: values,
            },
        });
    };

    const deleteAttrMutation = useMutation({
        ...deleteAttributeMutation(),
        onError,
        onSuccess: () => {
            refetchModule && refetchModule();
            refetchAttributes();
        },
    });

    const onDelete = (attributeId: number) =>
        deleteAttrMutation.mutate({ path: { pk: attributeId } });

    return {
        onToggleAttributeInModule,
        onUpdateLabel,
        onCreate,
        onUpdate,
        onDelete,
    };
};

export default useAttributesCrud;
