import React from 'react';
import { screen } from '@testing-library/react';
import { createIdentity, renderInAppContext } from '@theorchard/suite-testing';
import { BrowserRouter as Router } from 'react-router-dom';
import * as paymentsResponse from 'src/__fixtures__/graphql/payments-list-response.json';
import * as paymentsListQuery from 'src/apollo/queries/payment-group-payment';
import * as payoneerOutageAlert from 'src/components/shared/payoneer-service-outage-alert';
import { PaymentsList } from 'src/components/payments-list/payments-list';
import {
    USER_FEATURES,
    PAYONEER_OUTAGE_MESSAGE_TITLE,
    PAYONEER_OUTAGE_MESSAGE_CONTENT,
    PAYONEER_OUTAGE_TYPES,
} from 'src/constants';
import { createNewPayments } from 'src/urls/frontend-royalties';

describe('<PaymentsList />', () => {
    let mockUsePayoneerOutageStatus;

    beforeEach(() => {
        jest.spyOn(
            paymentsListQuery,
            'usePaymentGroupPaymentList'
        ).mockReturnValue({
            data: paymentsResponse,
            error: false,
            loading: false,
        });

        // Default mock for usePayoneerOutageStatus (no alert)
        mockUsePayoneerOutageStatus = jest
            .spyOn(payoneerOutageAlert, 'usePayoneerOutageStatus')
            .mockReturnValue({
                alert: null,
                isPayoneerOutage: false,
                isLoading: false,
                error: null,
            });
    });

    afterEach(jest.restoreAllMocks);

    const renderComponent = mockIdentity =>
        renderInAppContext(
            <Router>
                <PaymentsList />
            </Router>,
            {
                identity: createIdentity(mockIdentity),
            }
        );

    let mockIdentity = {
        features: {
            [USER_FEATURES.ABACUS_CREATE_AND_APPROVE_PAYMENTS]: true,
        },
    };

    it('displays payments table and page title', () => {
        renderComponent(mockIdentity);
        expect(screen.getAllByText('Phonofile July 2020')).toBeDefined();
        expect(screen.getByText('Payments')).toBeDefined();
    });

    it('renders a link button to create payments', () => {
        renderComponent(mockIdentity);
        const createBtn = screen.getByRole('link', { name: 'New Payments' });
        expect(createBtn.getAttribute('href')).toEqual(createNewPayments);
    });

    it('renders a "Status Details" column with data', () => {
        renderComponent(mockIdentity);
        expect(screen.getAllByTestId('no-payment-status')).toBeDefined();
        expect(screen.getByText('All Payments Successful')).toBeDefined();
        expect(screen.getByText('2 Failed with Batch')).toBeDefined();
        expect(screen.getByText('1 Canceled')).toBeDefined();
    });

    it('renders tabs (custom payments)', () => {
        renderComponent(mockIdentity);
        expect(screen.getByText('Balance Payments')).toBeDefined();
        expect(screen.getByText('Advance Payments')).toBeDefined();
        expect(screen.getByText('Custom Payments')).toBeDefined();
    });

    it('renders tabs (payment search FF disabled)', () => {
        renderComponent({
            ...mockIdentity,
            features: {
                ...mockIdentity.features,
                [USER_FEATURES.TAP_PAYMENT_SEARCH]: false,
            },
        });

        expect(screen.queryByText('Payment Search')).toBeNull();
    });

    it('renders tabs (payment search FF enabled)', () => {
        renderComponent({
            ...mockIdentity,
            features: {
                ...mockIdentity.features,
                [USER_FEATURES.TAP_PAYMENT_SEARCH]: true,
            },
        });

        expect(screen.getByText('Payment Search')).toBeDefined();

        const searchTabContainer = screen
            .getByText('Payment Search')
            .closest('.PaymentListTabs-SearchTab');
        expect(searchTabContainer).toBeDefined();
    });

    it("doesn't render a link button to create payments if FF is disabled", () => {
        mockIdentity = {
            features: {
                [USER_FEATURES.ABACUS_CREATE_AND_APPROVE_PAYMENTS]: false,
            },
        };
        renderComponent(mockIdentity);
        const createBtn = screen.queryByRole('link', { name: 'New Payments' });
        expect(createBtn).toBeNull();
    });

    describe('Payoneer Service Status Integration Tests', () => {
        const createMockAlert = type => (
            <div role="alert" data-variant="warn">
                <div>{PAYONEER_OUTAGE_MESSAGE_TITLE[type]}</div>
                <div>{PAYONEER_OUTAGE_MESSAGE_CONTENT[type]}</div>
            </div>
        );

        const mockPayoneerStatus = (alert, isOutage = false) => {
            mockUsePayoneerOutageStatus.mockReturnValue({
                alert,
                isPayoneerOutage: isOutage,
                isLoading: false,
                error: null,
            });
        };

        it('does not display alert when Payoneer service is healthy (statusCode: 200)', () => {
            mockPayoneerStatus(null, false);
            renderComponent(mockIdentity);

            expect(screen.queryByRole('alert')).toBeNull();
            expect(
                screen.queryByText(
                    PAYONEER_OUTAGE_MESSAGE_TITLE[PAYONEER_OUTAGE_TYPES.OUTAGE]
                )
            ).toBeNull();
            expect(
                screen.queryByText(
                    PAYONEER_OUTAGE_MESSAGE_TITLE[PAYONEER_OUTAGE_TYPES.UNKNOWN]
                )
            ).toBeNull();
        });

        it('displays outage alert when Payoneer service indicates outage (statusCode: 100)', () => {
            const alert = createMockAlert(PAYONEER_OUTAGE_TYPES.OUTAGE);
            mockPayoneerStatus(alert, true);
            renderComponent(mockIdentity);

            expect(screen.getByRole('alert')).toBeInTheDocument();
            expect(
                screen.getByText(
                    PAYONEER_OUTAGE_MESSAGE_TITLE[PAYONEER_OUTAGE_TYPES.OUTAGE]
                )
            ).toBeInTheDocument();
            expect(
                screen.getByText(
                    PAYONEER_OUTAGE_MESSAGE_CONTENT[
                        PAYONEER_OUTAGE_TYPES.OUTAGE
                    ]
                )
            ).toBeInTheDocument();
        });

        it('displays unknown status alert when Payoneer service status is unknown (statusCode: 99)', () => {
            const alert = createMockAlert(PAYONEER_OUTAGE_TYPES.UNKNOWN);
            mockPayoneerStatus(alert, false);
            renderComponent(mockIdentity);

            expect(screen.getByRole('alert')).toBeInTheDocument();
            expect(
                screen.getByText(
                    PAYONEER_OUTAGE_MESSAGE_TITLE[PAYONEER_OUTAGE_TYPES.UNKNOWN]
                )
            ).toBeInTheDocument();
            expect(
                screen.getByText(
                    PAYONEER_OUTAGE_MESSAGE_CONTENT[
                        PAYONEER_OUTAGE_TYPES.UNKNOWN
                    ]
                )
            ).toBeInTheDocument();
        });
    });
});
