import React from 'react';
import { render, screen } from '@testing-library/react';
import {
    mockTerritories,
    mockStores,
    mockStoreTerritoryGroups,
} from 'src/components/deliveryRestrictionsContext/__tests__/mockDeliveryRestrictions';
import * as features from 'src/utils/features';
import DigitalAudioRestrictions from '../digitalAudioRestrictions';

// Mock the useDeliveryRestrictionsContext hook
const mockUseDeliveryRestrictionsContext = jest.fn();
jest.mock(
    'src/components/deliveryRestrictionsContext/useDeliveryRestrictionsContext',
    () => ({
        DeliveryRestrictionsProvider: ({
            children,
        }: {
            children: React.ReactNode;
        }) => <div data-testid="deliveryRestrictions-provider">{children}</div>,
        useDeliveryRestrictionsContext: () =>
            mockUseDeliveryRestrictionsContext(),
    })
);

describe('<DigitalAudioRestrictions>', () => {
    const defaultDeliveryRestrictionsData = {
        stores: mockStores,
        territories: mockTerritories,
        storeTerritories: mockStoreTerritoryGroups,
        storesLoading: false,
        territoriesLoading: false,
        storeTerritoriesLoading: false,
    };

    beforeEach(() => {
        jest.spyOn(features, 'useRestrictFurtherFF').mockReturnValue(true);
        mockUseDeliveryRestrictionsContext.mockReturnValue(
            defaultDeliveryRestrictionsData
        );
    });

    afterEach(() => {
        jest.clearAllMocks();
    });

    const renderComponent = () => {
        return render(<DigitalAudioRestrictions />);
    };

    it('renders without errors', () => {
        const { getByText, getByTestId } = renderComponent();
        expect(getByTestId('DigitalAudioRestrictions')).toBeInTheDocument();
        expect(getByTestId('service-restrictions-section')).toBeInTheDocument();
        expect(getByTestId('country-restrictions-section')).toBeInTheDocument();
        expect(getByText('Digital Audio Restrictions')).toBeVisible();
        expect(getByText('Service Restrictions')).toBeVisible();
        expect(getByText('Country Restrictions')).toBeVisible();
        expect(
            getByText(
                'This is for restricting delivery to services that support digital audio'
            )
        ).toBeVisible();
        expect(
            getByText(
                'This is for restricting delivery to countries that support digital audio'
            )
        ).toBeVisible();
    });

    it('filters stores correctly between delivering and not delivering', () => {
        const { getAllByTestId } = renderComponent();

        // Delivering stores
        const deliveringSection = getAllByTestId('DeliveringTable')[0];
        const deliveringCells = deliveringSection.querySelectorAll(
            '.cell-deliveryRestriction-label'
        );
        expect(deliveringCells.length).toBe(2);
        expect(deliveringCells[0]).toHaveTextContent('Spotify');
        expect(deliveringCells[1]).toHaveTextContent('Amazon');

        // Not delivering stores
        const notDeliveringSection =
            screen.getAllByTestId('NotDeliveringTable')[0];
        const notDeliveringCells = notDeliveringSection.querySelectorAll(
            '.cell-deliveryRestriction'
        );
        expect(notDeliveringCells.length).toBe(1);
        expect(notDeliveringCells[0]).toHaveTextContent('Apple Music');
    });

    it('filters territories correctly between delivering and not delivering', () => {
        const { getAllByTestId } = renderComponent();

        // Delivering territories
        const deliveringSection = getAllByTestId('DeliveringTable')[1];
        const deliveringCells = deliveringSection.querySelectorAll(
            '.cell-deliveryRestriction'
        );
        expect(deliveringCells.length).toBe(2);
        expect(deliveringCells[0]).toHaveTextContent('United States');
        expect(deliveringCells[1]).toHaveTextContent('United Kingdom');

        // Not delivering territories
        const notDeliveringSection =
            screen.getAllByTestId('NotDeliveringTable')[1];
        const notDeliveringCells = notDeliveringSection.querySelectorAll(
            '.cell-deliveryRestriction-label'
        );
        expect(notDeliveringCells.length).toBe(1);
        expect(notDeliveringCells[0]).toHaveTextContent('Canada');
    });

    it('handles loading state - empty data table', () => {
        mockUseDeliveryRestrictionsContext.mockReturnValue({
            stores: [],
            territories: [],
            storeTerritories: [],
            storesLoading: true,
            territoriesLoading: true,
            storeTerritoriesLoading: true,
        });

        const { getAllByTestId } = renderComponent();

        expect(screen.getByText('Service Restrictions')).toBeVisible();
        expect(screen.getByText('Country Restrictions')).toBeVisible();
        expect(getAllByTestId('DeliveringTable')).toHaveLength(2);
        expect(getAllByTestId('NotDeliveringTable')).toHaveLength(2);

        // Check that tables have loading state
        const deliveringTables = getAllByTestId('DeliveringTable');
        const notDeliveringTables = getAllByTestId('NotDeliveringTable');

        deliveringTables.forEach(table => {
            const loaders = table.querySelectorAll('.SkeletonLoader');
            expect(loaders.length).toBeGreaterThan(0);
        });

        notDeliveringTables.forEach(table => {
            const loaders = table.querySelectorAll('.SkeletonLoader');
            expect(loaders.length).toBeGreaterThan(0);
        });
    });

    it('calls useDeliveryRestrictionsContext hook', () => {
        const { getByTestId } = renderComponent();
        expect(getByTestId('DigitalAudioRestrictions')).toBeInTheDocument();
        expect(mockUseDeliveryRestrictionsContext).toHaveBeenCalled();
    });

    it('renders correct table structure with proper test IDs', () => {
        const { getAllByTestId } = renderComponent();

        // Should have exactly 2 delivering tables (stores and territories)
        const deliveringTables = getAllByTestId('DeliveringTable');
        expect(deliveringTables).toHaveLength(2);

        // Should have exactly 2 not delivering tables (stores and territories)
        const notDeliveringTables = getAllByTestId('NotDeliveringTable');
        expect(notDeliveringTables).toHaveLength(2);
    });
});
