import React from 'react';
import { InMemoryCache } from '@apollo/client';
import { MockedProvider } from '@apollo/client/testing';
import { renderHook } from '@testing-library/react';
import { BRAND_AWAL, BRAND_KNR, BRAND_ORCHARD } from '@theorchard/constants';
import { PAYMENT_ENTITIES_CONFIG } from '../../constants/paymentEntity';
import { writePaymentEntityToCache } from '../../test-utils/writePaymentEntityToCache';
import { useReferencePaymentEntity } from '../useReferencePaymentEntity';

describe('useReferencePaymentEntity (Integration)', () => {
    const renderReferenceHook = (
        id: string | null,
        cache: InMemoryCache,
        useConfigOnly = false
    ) => {
        return renderHook(() => useReferencePaymentEntity(id, useConfigOnly), {
            wrapper: ({ children }) => (
                <MockedProvider cache={cache} addTypename={true}>
                    {children}
                </MockedProvider>
            ),
        });
    };

    it('returns all false flags and null values when no entity is detected', () => {
        const cache = new InMemoryCache();

        const { result } = renderReferenceHook('3', cache);

        expect(result.current).toEqual({
            entityName: null,
            entityFullName: null,
            isAWAL: false,
            isKNR: false,
            isSME: false,
            isOrchard: false,
            hasEntity: false,
        });
    });

    it('identifies AWAL entity', () => {
        const cache = new InMemoryCache();

        writePaymentEntityToCache(
            cache,
            PAYMENT_ENTITIES_CONFIG.AWAL_US.id,
            PAYMENT_ENTITIES_CONFIG.AWAL_US.fullName
        );

        const { result } = renderReferenceHook(PAYMENT_ENTITIES_CONFIG.AWAL_US.id, cache);

        expect(result.current).toMatchObject({
            entityName: BRAND_AWAL,
            entityFullName: PAYMENT_ENTITIES_CONFIG.AWAL_US.fullName,
            isAWAL: true,
            hasEntity: true,
        });
    });

    it('identifies KNR entity', () => {
        const cache = new InMemoryCache();

        writePaymentEntityToCache(
            cache,
            PAYMENT_ENTITIES_CONFIG.KNR_NL.id,
            PAYMENT_ENTITIES_CONFIG.KNR_NL.fullName
        );

        const { result } = renderReferenceHook(PAYMENT_ENTITIES_CONFIG.KNR_NL.id, cache);

        expect(result.current).toMatchObject({ isKNR: true, hasEntity: true });
    });

    it('identifies SME entity', () => {
        const cache = new InMemoryCache();

        writePaymentEntityToCache(cache, '100001', 'SME-Core');

        const { result } = renderReferenceHook('100001', cache);

        expect(result.current).toMatchObject({ isSME: true, hasEntity: true });
    });

    it('identifies Orchard entity', () => {
        const cache = new InMemoryCache();

        writePaymentEntityToCache(
            cache,
            PAYMENT_ENTITIES_CONFIG.ORCHARD_ES.id,
            PAYMENT_ENTITIES_CONFIG.ORCHARD_ES.fullName
        );

        const { result } = renderReferenceHook(PAYMENT_ENTITIES_CONFIG.ORCHARD_ES.id, cache);

        expect(result.current).toMatchObject({ isOrchard: true, hasEntity: true });
    });

    it('handles null paymentEntityId gracefully', () => {
        const cache = new InMemoryCache();
        const { result } = renderReferenceHook(null, cache);

        expect(result.current).toEqual({
            entityName: null,
            entityFullName: null,
            isAWAL: false,
            isKNR: false,
            isSME: false,
            isOrchard: false,
            hasEntity: false,
        });
    });

    describe('config only', () => {
        const cache = new InMemoryCache();

        it.each([
            ['1', BRAND_AWAL, { isAWAL: true }],
            ['4', BRAND_KNR, { isKNR: true }],
            ['6', BRAND_ORCHARD, { isOrchard: true }],
        ])('correctly detects "%s" as %s from config', (id, expectedBrand, flags) => {
            const { result } = renderReferenceHook(id, cache, true);

            expect(result.current.entityName).toBe(expectedBrand);
            expect(result.current.hasEntity).toBe(true);

            Object.entries(flags).forEach(([flag, value]) => {
                // eslint-disable-next-line @typescript-eslint/no-explicit-any
                expect((result.current as any)[flag]).toBe(value);
            });
        });

        it('returns all false flags and null values when no entity is detected in config', () => {
            const { result } = renderReferenceHook('not-exist', cache, true);

            expect(result.current).toEqual({
                entityName: null,
                entityFullName: null,
                isAWAL: false,
                isKNR: false,
                isSME: false,
                isOrchard: false,
                hasEntity: false,
            });
        });

        it('handles null paymentEntityId gracefully in config mode', () => {
            const { result } = renderReferenceHook(null, cache, true);

            expect(result.current).toEqual({
                entityName: null,
                entityFullName: null,
                isAWAL: false,
                isKNR: false,
                isSME: false,
                isOrchard: false,
                hasEntity: false,
            });
        });
    });
});
