/**
 * END-TO-END TEST: Widget Lifecycle
 * 
 * Tests complete user journeys from widget mount to close,
 * simulating real-world scenarios that companies would encounter.
 * 
 * Strategy: Minimal mocking, test full integration flow
 */

import React from 'react';
import { render, waitFor, fireEvent } from '@testing-library/react-native';
import { SoluCXWidgetView as SoluCXWidget } from '../../SoluCXWidgetView';
import type { WidgetCallbacks } from '../../domain';

// Mock storage
const mockStorage: Record<string, string> = {};
jest.mock('@react-native-async-storage/async-storage', () => ({
    __esModule: true,
    default: {
        getItem: jest.fn((key: string) => Promise.resolve(mockStorage[key] || null)),
        setItem: jest.fn((key: string, value: string) => {
            mockStorage[key] = value;
            return Promise.resolve();
        }),
        removeItem: jest.fn((key: string) => {
            delete mockStorage[key];
            return Promise.resolve();
        }),
        clear: jest.fn(() => {
            Object.keys(mockStorage).forEach(key => delete mockStorage[key]);
            return Promise.resolve();
        }),
    },
}));

// Mock only what we absolutely must
jest.mock('react-native-webview', () => {
    const React = require('react');
    const { View, Text } = require('react-native');
    return {
        __esModule: true,
        WebView: React.forwardRef((props: any, ref: any) => {
            React.useImperativeHandle(ref, () => ({
                injectJavaScript: jest.fn(),
            }));
            
            return (
                <View testID="webview" {...props}>
                    <Text>WebView Content</Text>
                </View>
            );
        }),
    };
});

jest.mock('../../services/WidgetBootstrapService', () => ({
    requestWidgetUrl: jest.fn().mockResolvedValue({ available: true, url: 'https://widget.solucx.com/survey/456' }),
}));

jest.mock('../../services/WidgetValidationService', () => ({
    WidgetValidationService: jest.fn().mockImplementation(() => ({
        shouldDisplayForTransaction: jest.fn().mockResolvedValue({ canDisplay: true }),
        shouldDisplayForTransactionAlreadyAnswered: jest.fn().mockResolvedValue({ canDisplay: true }),
        shouldDisplayWidget: jest.fn().mockResolvedValue({ canDisplay: true }),
    })),
}));

describe('E2E: Widget Lifecycle', () => {
    beforeEach(async () => {
        jest.clearAllMocks();
        Object.keys(mockStorage).forEach(key => delete mockStorage[key]);
    });

    describe('E-commerce Post-Purchase Survey Flow', () => {
        it('should complete full flow: mount → display → interact → complete → close', async () => {
            const analytics = {
                track: jest.fn(),
            };

            const callbacks: WidgetCallbacks = {
                onOpened: (userId) => analytics.track('widget_shown', { userId }),
                onQuestionAnswered: () => analytics.track('question_answered'),
                onCompleted: (userId) => {
                    analytics.track('survey_completed', { userId });
                },
                onClosed: () => analytics.track('widget_closed'),
            };

            // 1. Mount widget after purchase
            const { getByTestId } = render(
                <SoluCXWidget
                    soluCXKey="ecommerce-post-purchase"
                    type="modal"
                    data={{
                        form_id: 'post-purchase-123',
                        customer_id: 'cust-789',
                        transaction_id: 'order-456',
                        amount: 199.99,
                    }}
                    options={{ height: 500 }}
                    callbacks={callbacks}
                />
            );

            // 2. Widget should render
            await waitFor(() => {
                expect(getByTestId('webview')).toBeTruthy();
            }, { timeout: 10000 });

            const webview = getByTestId('webview');

            // 3. First page loads, customer sees question
            // (WebView automatically expands as content loads)
            fireEvent(webview, 'message', {
                nativeEvent: { data: 'FORM_RESIZE-400' },
            });

            // 4. Customer answers first question
            fireEvent(webview, 'message', {
                nativeEvent: { data: 'QUESTION_ANSWERED' },
            });

            await waitFor(() => {
                expect(analytics.track).toHaveBeenCalledWith('question_answered');
            });

            // Reset counter after first question to track only upcoming interactions
            analytics.track.mockClear();

            // 5. Customer goes to next page
            fireEvent(webview, 'message', {
                nativeEvent: { data: 'FORM_PAGECHANGED-2' },
            });

            // 6. Customer answers second question
            fireEvent(webview, 'message', {
                nativeEvent: { data: 'QUESTION_ANSWERED' },
            });

            await waitFor(() => {
                expect(analytics.track).toHaveBeenCalledWith('question_answered');
                expect(analytics.track).toHaveBeenCalledTimes(1); // Called once after reset
            });

            // 7. Customer submits survey
            fireEvent(webview, 'message', {
                nativeEvent: { data: 'FORM_COMPLETED' },
            });

            await waitFor(() => {
                expect(analytics.track).toHaveBeenCalledWith('survey_completed', {
                    userId: expect.any(String),
                });
            });

            // 8. Customer closes widget
            fireEvent(webview, 'message', {
                nativeEvent: { data: 'FORM_CLOSE' },
            });

            await waitFor(() => {
                expect(analytics.track).toHaveBeenCalledWith('widget_closed');
            });

            // Verify complete tracking flow after reset (question_answered + survey_completed + widget_closed)
            expect(analytics.track).toHaveBeenCalledTimes(3);
        }, 15000);
    });

    describe('SaaS NPS Survey Flow with Error Recovery', () => {
        it('should handle network error gracefully when error occurs', async () => {
            const errorHandler = jest.fn();

            const callbacks: WidgetCallbacks = {
                onError: errorHandler,
            };

            const { getByTestId } = render(
                <SoluCXWidget
                    soluCXKey="saas-nps"
                    type="bottom"
                    data={{
                        form_id: 'nps-survey',
                        customer_id: 'user-123',
                        param_plan: 'premium',
                    }}
                    options={{ height: 300 }}
                    callbacks={callbacks}
                />
            );

            await waitFor(() => {
                expect(getByTestId('webview')).toBeTruthy();
            }, { timeout: 10000 });

            const webview = getByTestId('webview');

            // User rates NPS
            fireEvent(webview, 'message', {
                nativeEvent: { data: 'FORM_PAGECHANGED-1' },
            });

            // Network error occurs during submission
            fireEvent(webview, 'message', {
                nativeEvent: { data: 'FORM_ERROR-Network timeout occurred' },
            });

            await waitFor(() => {
                expect(errorHandler).toHaveBeenCalledWith('Network timeout occurred');
            }, { timeout: 10000 });
        }, 15000);
    });

    describe('Banking Compliance Survey with Dynamic Resizing', () => {
        it('should handle multiple resize events as form expands', async () => {
            const resizeHandler = jest.fn();

            const { getByTestId } = render(
                <SoluCXWidget
                    soluCXKey="banking-compliance"
                    type="inline"
                    data={{
                        form_id: 'compliance-check',
                        customer_id: 'bank-cust-456',
                    }}
                    options={{ height: 400 }}
                    callbacks={{ onResize: resizeHandler }}
                />
            );

            await waitFor(() => {
                expect(getByTestId('webview')).toBeTruthy();
            });

            const webview = getByTestId('webview');

            // Form starts small
            fireEvent(webview, 'message', {
                nativeEvent: { data: 'FORM_RESIZE-300' },
            });

            // User expands section, form grows
            fireEvent(webview, 'message', {
                nativeEvent: { data: 'FORM_RESIZE-500' },
            });

            // User expands another section
            fireEvent(webview, 'message', {
                nativeEvent: { data: 'FORM_RESIZE-700' },
            });

            // User collapses section
            fireEvent(webview, 'message', {
                nativeEvent: { data: 'FORM_RESIZE-600' },
            });

            await waitFor(() => {
                expect(resizeHandler).toHaveBeenCalledTimes(4);
            });

            // Verify resize values
            expect(resizeHandler).toHaveBeenNthCalledWith(1, '300');
            expect(resizeHandler).toHaveBeenNthCalledWith(2, '500');
            expect(resizeHandler).toHaveBeenNthCalledWith(3, '700');
            expect(resizeHandler).toHaveBeenNthCalledWith(4, '600');
        });
    });

    describe('Multi-Step Survey with Page Tracking', () => {
        it('should track progress through multi-step survey', async () => {
            const pageChangeHandler = jest.fn();
            const questionHandler = jest.fn();
            const completionHandler = jest.fn();

            const { getByTestId } = render(
                <SoluCXWidget
                    soluCXKey="multi-step-survey"
                    type="modal"
                    data={{
                        form_id: 'multi-step',
                        customer_id: 'user-999',
                    }}
                    options={{ height: 450 }}
                    callbacks={{
                        onPageChanged: pageChangeHandler,
                        onQuestionAnswered: questionHandler,
                        onCompleted: completionHandler,
                    }}
                />
            );

            await waitFor(() => {
                expect(getByTestId('webview')).toBeTruthy();
            });

            const webview = getByTestId('webview');

            // Page 1: Answer question
            fireEvent(webview, 'message', {
                nativeEvent: { data: 'QUESTION_ANSWERED' },
            });

            // Go to page 2
            fireEvent(webview, 'message', {
                nativeEvent: { data: 'FORM_PAGECHANGED-2' },
            });

            // Page 2: Answer question
            fireEvent(webview, 'message', {
                nativeEvent: { data: 'QUESTION_ANSWERED' },
            });

            // Go to page 3
            fireEvent(webview, 'message', {
                nativeEvent: { data: 'FORM_PAGECHANGED-3' },
            });

            // Page 3: Answer final question
            fireEvent(webview, 'message', {
                nativeEvent: { data: 'QUESTION_ANSWERED' },
            });

            // Complete survey
            fireEvent(webview, 'message', {
                nativeEvent: { data: 'FORM_COMPLETED' },
            });

            await waitFor(() => {
                expect(pageChangeHandler).toHaveBeenCalledTimes(2);
                expect(questionHandler).toHaveBeenCalledTimes(3);
                expect(completionHandler).toHaveBeenCalledTimes(1);
            });

            // Verify page progression
            expect(pageChangeHandler).toHaveBeenNthCalledWith(1, '2');
            expect(pageChangeHandler).toHaveBeenNthCalledWith(2, '3');
        });
    });
});
