import React from 'react';
import { MockedProvider } from '@apollo/client/testing';
import { renderHook, act } from '@testing-library/react-hooks';
import approveMutation from '../ApproveMutation.gql';
import {
    useApproveProductMutation,
    useApproveProductMutationV2,
} from '../approveProductReview';

describe('useApproveProductMutation', () => {
    it('should trigger the approve mutation with trimmed note and call the onSubmitCallback', async () => {
        const onSubmitCallback = jest.fn();
        const mocks = [
            {
                request: {
                    query: approveMutation,
                    variables: {
                        reviewQueueId: 99,
                        note: 'test note',
                        cannedResponseId: '1',
                        cannedResponseIds: ['1'],
                        tracks: [],
                    },
                },
                result: {
                    data: {
                        approve: {
                            status: 'ok',
                        },
                    },
                },
            },
        ];

        const { result, waitForNextUpdate } = renderHook(
            () =>
                useApproveProductMutation(
                    99,
                    ' test note\n ',
                    '1',
                    ['1'],
                    [],
                    onSubmitCallback
                ),
            {
                wrapper: ({ children }: { children: React.ReactNode }) => (
                    <MockedProvider mocks={mocks} addTypename={false}>
                        {children}
                    </MockedProvider>
                ),
            }
        );

        void act(() => {
            void result.current();
        });

        await waitForNextUpdate();

        expect(onSubmitCallback).toHaveBeenCalledWith('ok', 'Approval');
    });

    it('should call the onSubmitCallback with "error" when the mutation returns an error', async () => {
        const onSubmitCallback = jest.fn();
        const mocks = [
            {
                request: {
                    query: approveMutation,
                    variables: {
                        reviewQueueId: 99,
                        note: 'test note',
                        cannedResponseId: '1',
                    },
                },
                error: new Error('An error occurred'),
            },
        ];

        const { result, waitForNextUpdate } = renderHook(
            () =>
                useApproveProductMutation(
                    99,
                    'test note',
                    '1',
                    ['1'],
                    [],
                    onSubmitCallback
                ),
            {
                wrapper: ({ children }: { children: React.ReactNode }) => (
                    <MockedProvider mocks={mocks} addTypename={false}>
                        {children}
                    </MockedProvider>
                ),
            }
        );

        void act(() => {
            void result.current();
        });

        await waitForNextUpdate();

        expect(onSubmitCallback).toHaveBeenCalledWith('error', 'Approval');
    });

    it('should remove whitespace and set note as undefined when note.trim() is an empty string', async () => {
        const onSubmitCallback = jest.fn();
        const mocks = [
            {
                request: {
                    query: approveMutation,
                    variables: {
                        reviewQueueId: 99,
                        note: undefined,
                        cannedResponseId: undefined,
                        tracks: [],
                    },
                },
                result: {
                    data: {
                        approve: {
                            status: 'ok',
                        },
                    },
                },
            },
        ];

        const { result, waitForNextUpdate } = renderHook(
            () =>
                useApproveProductMutation(
                    99,
                    ' \n  ',
                    undefined,
                    undefined,
                    [],
                    onSubmitCallback
                ),
            {
                wrapper: ({ children }: { children: React.ReactNode }) => (
                    <MockedProvider mocks={mocks} addTypename={false}>
                        {children}
                    </MockedProvider>
                ),
            }
        );

        void act(() => {
            void result.current();
        });

        await waitForNextUpdate();

        expect(onSubmitCallback).toHaveBeenCalledWith('ok', 'Approval');
    });
});

describe('useApproveProductMutationV2', () => {
    it('triggers approve mutation with trimmed note and calls onSubmitCallback on success', async () => {
        const onSubmitCallback = jest.fn();
        const mocks = [
            {
                request: {
                    query: approveMutation,
                    variables: {
                        reviewQueueId: 99,
                        note: 'test note',
                        cannedResponseId: '1',
                        cannedResponseIds: ['1'],
                        tracks: [],
                    },
                },
                result: {
                    data: {
                        approve: {
                            status: 'ok',
                        },
                    },
                },
            },
        ];

        const { result, waitForNextUpdate } = renderHook(
            () => useApproveProductMutationV2(onSubmitCallback),
            {
                wrapper: ({ children }: { children: React.ReactNode }) => (
                    <MockedProvider mocks={mocks} addTypename={false}>
                        {children}
                    </MockedProvider>
                ),
            }
        );

        void act(() => {
            void result.current({
                reviewQueueId: 99,
                note: ' test note\n ',
                cannedResponseId: '1',
                cannedResponseIds: ['1'],
                tracks: [],
            });
        });

        await waitForNextUpdate();

        expect(onSubmitCallback).toHaveBeenCalledWith('ok', 'Approval');
    });

    it('calls onSubmitCallback with "error" when the mutation returns an error', async () => {
        const onSubmitCallback = jest.fn();
        const mocks = [
            {
                request: {
                    query: approveMutation,
                    variables: {
                        reviewQueueId: 99,
                        note: 'test note',
                        cannedResponseId: '1',
                        cannedResponseIds: ['1'],
                        tracks: [],
                    },
                },
                error: new Error('An error occurred'),
            },
        ];

        const { result, waitForNextUpdate } = renderHook(
            () => useApproveProductMutationV2(onSubmitCallback),
            {
                wrapper: ({ children }: { children: React.ReactNode }) => (
                    <MockedProvider mocks={mocks} addTypename={false}>
                        {children}
                    </MockedProvider>
                ),
            }
        );

        void act(() => {
            void result.current({
                reviewQueueId: 99,
                note: 'test note',
                cannedResponseId: '1',
                cannedResponseIds: ['1'],
                tracks: [],
            });
        });

        await waitForNextUpdate();

        expect(onSubmitCallback).toHaveBeenCalledWith('error', 'Approval');
    });

    it('removes whitespace and sets note as undefined when note.trim() is an empty string', async () => {
        const onSubmitCallback = jest.fn();
        const mocks = [
            {
                request: {
                    query: approveMutation,
                    variables: {
                        reviewQueueId: 99,
                        note: undefined,
                        cannedResponseId: undefined,
                        cannedResponseIds: undefined,
                        tracks: [],
                    },
                },
                result: {
                    data: {
                        approve: {
                            status: 'ok',
                        },
                    },
                },
            },
        ];

        const { result, waitForNextUpdate } = renderHook(
            () => useApproveProductMutationV2(onSubmitCallback),
            {
                wrapper: ({ children }: { children: React.ReactNode }) => (
                    <MockedProvider mocks={mocks} addTypename={false}>
                        {children}
                    </MockedProvider>
                ),
            }
        );

        void act(() => {
            void result.current({
                reviewQueueId: 99,
                note: ' \n  ',
                cannedResponseId: undefined,
                cannedResponseIds: undefined,
                tracks: [],
            });
        });

        await waitForNextUpdate();

        expect(onSubmitCallback).toHaveBeenCalledWith('ok', 'Approval');
    });
});
