import React from "react";
import { render, waitFor, fireEvent } from "@testing-library/react-native";
import { SoluCXWidgetView as SoluCXWidget } from "../SoluCXWidgetView";
import { WidgetData, WidgetOptions } from "../domain";
import { requestWidgetOptions, requestWidgetUrl } from "../services/WidgetBootstrapService";

jest.mock("react-native-webview", () => {
    const { forwardRef } = require("react");
    const { View } = require("react-native");
    return {
        __esModule: true,
        WebView: forwardRef((props: any, ref: any) => <View testID="webview" {...props} ref={ref} />),
    };
});

const mockClose = jest.fn();
const mockHide = jest.fn();
const mockOpen = jest.fn();
const mockShouldDisplayWidget = jest.fn();
const mockShouldDisplayForTransaction = jest.fn();

const mockStateManager = {
    getLogs: jest.fn().mockResolvedValue({ lastFirstAccess: 0, lastDisplay: 0 }),
    updateTimestamp: jest.fn().mockResolvedValue(undefined),
    incrementAttempt: jest.fn().mockResolvedValue(undefined),
    hasAnsweredTransaction: jest.fn().mockResolvedValue(false),
    markTransactionAnswered: jest.fn().mockResolvedValue(undefined),
    resetAttempts: jest.fn().mockResolvedValue(undefined),
};

jest.mock("../hooks/useWidget", () => ({
    useWidget: () => ({
        widgetHeight: 400,
        isWidgetVisible: true,
        hide: mockHide,
        resize: jest.fn(),
        open: mockOpen,
        close: mockClose,
        userId: "test-user-123",
        stateManager: mockStateManager,
    }),
}));

jest.mock("../services/WidgetEventService", () => ({
    WidgetEventService: jest.fn().mockImplementation(() => ({
        handleMessage: jest.fn(),
    })),
}));

jest.mock("../services/WidgetValidationService", () => ({
    WidgetValidationService: jest.fn().mockImplementation(() => ({
        shouldDisplayForTransaction: mockShouldDisplayForTransaction,
        shouldDisplayForTransactionAlreadyAnswered: mockShouldDisplayForTransaction,
        shouldDisplayWidget: mockShouldDisplayWidget,
    })),
}));

jest.mock("../services/WidgetBootstrapService", () => ({
    requestWidgetOptions: jest.fn(),
    requestWidgetUrl: jest.fn(),
}));

jest.mock("../constants/Constants", () => ({
    SDK_NAME: "rn-widget-sdk",
    SDK_VERSION: "0.1.16",
}));

jest.mock("../hooks/useClientVersionCollector", () => ({
    getClientVersion: jest.fn(() => "1.0.0"),
}));

jest.mock("../hooks/useDeviceInfoCollector", () => ({
    getDeviceInfo: jest.fn(() => ({
        platform: "ios",
        osVersion: "16.0",
        screenWidth: 390,
        screenHeight: 844,
        windowWidth: 390,
        windowHeight: 844,
        scale: 3,
        fontScale: 1,
        deviceType: "phone",
        model: "iPhone 14 Pro",
    })),
}));

const mockRequestWidgetUrl = requestWidgetUrl as jest.MockedFunction<typeof requestWidgetUrl>;
const mockRequestWidgetOptions = requestWidgetOptions as jest.MockedFunction<typeof requestWidgetOptions>;
const bootstrappedWidgetUrl = "https://widgets.solucx.com/widget/bootstrap-result";

const baseProps = {
    soluCXKey: "test-key-abc",
    data: {
        customer_id: "cust-001",
        transaction_id: "txn-999",
        form_id: "form-123",
    } as WidgetData,
    options: {
        height: 400,
    } as WidgetOptions,
};

beforeEach(() => {
    jest.clearAllMocks();
    mockShouldDisplayForTransaction.mockReset();
    mockShouldDisplayForTransaction.mockResolvedValue({ canDisplay: true });
    mockShouldDisplayWidget.mockReset();
    mockShouldDisplayWidget.mockResolvedValue({ canDisplay: true });
    mockRequestWidgetOptions.mockReset();
    mockRequestWidgetOptions.mockResolvedValue({ height: 400 });
    mockRequestWidgetUrl.mockReset();
    mockRequestWidgetUrl.mockResolvedValue({ available: true, url: bootstrappedWidgetUrl });
});

describe("SoluCXWidget type routing", () => {
    it("should render ModalWidget when type is modal", async () => {
        mockRequestWidgetUrl.mockResolvedValue({ available: true, url: bootstrappedWidgetUrl });

        const { UNSAFE_getByType } = render(<SoluCXWidget {...baseProps} type="modal" />);

        await waitFor(() => {
            const modal = UNSAFE_getByType(require("react-native").Modal);
            expect(modal).toBeTruthy();
        }, { timeout: 10000 });
    }, 15000);

    it("should render close button inside ModalWidget", async () => {
        mockRequestWidgetUrl.mockResolvedValue({ available: true, url: bootstrappedWidgetUrl });

        const { getByText } = render(<SoluCXWidget {...baseProps} type="modal" />);

        await waitFor(() => {
            expect(getByText("✕")).toBeTruthy();
        });
    });

    it("should render WebView inside ModalWidget with correct source", async () => {
        mockRequestWidgetUrl.mockResolvedValue({ available: true, url: bootstrappedWidgetUrl });

        const { getByTestId } = render(<SoluCXWidget {...baseProps} type="modal" />);

        await waitFor(() => {
            const webview = getByTestId("webview");
            expect(webview.props.source.uri).toBe(bootstrappedWidgetUrl);
        });
    });

    it("should render InlineWidget when type is inline", async () => {
        mockRequestWidgetUrl.mockResolvedValue({ available: true, url: bootstrappedWidgetUrl });

        const { queryByTestId, getByText } = render(<SoluCXWidget {...baseProps} type="inline" />);

        await waitFor(() => {
            expect(queryByTestId("webview")).toBeTruthy();
            expect(getByText("✕")).toBeTruthy();
        });
    });

    it("should not render Modal when type is inline", async () => {
        mockRequestWidgetUrl.mockResolvedValue({ available: true, url: bootstrappedWidgetUrl });

        const { UNSAFE_queryByType } = render(<SoluCXWidget {...baseProps} type="inline" />);

        await waitFor(() => {
            const modal = UNSAFE_queryByType(require("react-native").Modal);
            expect(modal).toBeNull();
        });
    });

    it("should render OverlayWidget when type is bottom", async () => {
        mockRequestWidgetUrl.mockResolvedValue({ available: true, url: bootstrappedWidgetUrl });

        const { queryByTestId, getByText } = render(<SoluCXWidget {...baseProps} type="bottom" />);

        await waitFor(() => {
            expect(queryByTestId("webview")).toBeTruthy();
            expect(getByText("✕")).toBeTruthy();
        });
    });

    it("should render OverlayWidget when type is top", async () => {
        mockRequestWidgetUrl.mockResolvedValue({ available: true, url: bootstrappedWidgetUrl });

        const { queryByTestId, getByText } = render(<SoluCXWidget {...baseProps} type="top" />);

        await waitFor(() => {
            expect(queryByTestId("webview")).toBeTruthy();
            expect(getByText("✕")).toBeTruthy();
        });
    });

    it("should not render Modal when type is bottom", async () => {
        mockRequestWidgetUrl.mockResolvedValue({ available: true, url: bootstrappedWidgetUrl });

        const { UNSAFE_queryByType } = render(<SoluCXWidget {...baseProps} type="bottom" />);

        await waitFor(() => {
            const modal = UNSAFE_queryByType(require("react-native").Modal);
            expect(modal).toBeNull();
        });
    });
});

describe("SoluCXWidget WebView configuration", () => {
    it("should set originWhitelist to allow all origins", async () => {
        mockRequestWidgetUrl.mockResolvedValue({ available: true, url: bootstrappedWidgetUrl });

        const { getByTestId } = render(<SoluCXWidget {...baseProps} type="modal" />);

        await waitFor(() => {
            const webview = getByTestId("webview");
            expect(webview.props.originWhitelist).toEqual(["*"]);
        });
    });

    it("should set WebView width style to screen width", async () => {
        mockRequestWidgetUrl.mockResolvedValue({ available: true, url: bootstrappedWidgetUrl });

        const { getByTestId } = render(<SoluCXWidget {...baseProps} type="modal" />);

        await waitFor(() => {
            const webview = getByTestId("webview");
            const widthStyle = webview.props.style.find((s: any) => s.width !== undefined);
            expect(widthStyle.width).toBeGreaterThan(0);
        });
    });

    it("should set WebView height style to widgetHeight", async () => {
        mockRequestWidgetUrl.mockResolvedValue({ available: true, url: bootstrappedWidgetUrl });

        const { getByTestId } = render(<SoluCXWidget {...baseProps} type="modal" />);

        await waitFor(() => {
            const webview = getByTestId("webview");
            const heightStyle = webview.props.style.find((s: any) => s.height !== undefined);
            expect(heightStyle.height).toBe(400);
        });
    });

    it("should use bootstrapped URL for widgets", async () => {
        mockRequestWidgetUrl.mockResolvedValue({ available: true, url: bootstrappedWidgetUrl });

        const { getByTestId } = render(<SoluCXWidget {...baseProps} type="inline" />);

        await waitFor(() => {
            const webview = getByTestId("webview");
            expect(webview.props.source.uri).toBe(bootstrappedWidgetUrl);
        });
    });
});

describe("SoluCXWidget bootstrap flow", () => {
    it("respects fetched type when local options are not provided", async () => {
        mockRequestWidgetOptions.mockResolvedValue({ type: "inline", height: 520 });
        mockRequestWidgetUrl.mockResolvedValue({ available: true, url: bootstrappedWidgetUrl });

        const props = {
            ...baseProps,
            type: "modal" as const,
            options: undefined,
            data: {
                customer_id: "cust-777",
                journey: "sac",
            },
        };

        const { UNSAFE_queryByType, queryByTestId } = render(<SoluCXWidget {...props} />);

        await waitFor(() => {
            expect(queryByTestId("webview")).toBeTruthy();
            const modal = UNSAFE_queryByType(require("react-native").Modal);
            expect(modal).toBeNull();
        });
    });

    it("respects fetched height when local options are not provided", async () => {
        mockRequestWidgetOptions.mockResolvedValue({ type: "inline", height: 520 });
        mockRequestWidgetUrl.mockResolvedValue({ available: true, url: bootstrappedWidgetUrl });

        const props = {
            ...baseProps,
            type: "modal" as const,
            options: undefined,
            data: {
                customer_id: "cust-777",
                journey: "sac",
            },
        };

        const { getByTestId } = render(<SoluCXWidget {...props} />);

        await waitFor(() => {
            const webview = getByTestId("webview");
            const heightStyle = webview.props.style.find((s: { height?: number }) => s.height !== undefined);
            expect(heightStyle.height).toBe(520);
        });
    });

    it("fetches widget URL for form widgets", async () => {
        mockRequestWidgetUrl.mockResolvedValue({ available: true, url: bootstrappedWidgetUrl });

        const props = {
            ...baseProps,
            type: "modal" as const,
        };

        const { queryByTestId, getByTestId } = render(<SoluCXWidget {...props} />);

        expect(queryByTestId("webview")).toBeNull();

        await waitFor(() => {
            expect(mockRequestWidgetUrl).toHaveBeenCalledTimes(1);
            expect(mockRequestWidgetUrl).toHaveBeenCalledWith(
                "test-key-abc",
                expect.objectContaining({
                    form_id: "form-123",
                }),
                "test-user-123",
            );
            expect(mockShouldDisplayWidget).toHaveBeenCalledTimes(1);
            expect(mockOpen).toHaveBeenCalledTimes(1);
            expect(queryByTestId("webview")).toBeTruthy();
        });

        const webview = getByTestId("webview");
        expect(webview.props.source.uri).toBe(bootstrappedWidgetUrl);
    });

    it("fetches widget URL before rendering non-form widgets", async () => {
        mockRequestWidgetUrl.mockResolvedValue({ available: true, url: bootstrappedWidgetUrl });

        const props = {
            ...baseProps,
            data: {
                customer_id: "cust-777",
                journey: "sac",
            },
            type: "bottom" as const,
        };

        const { queryByTestId, getByTestId } = render(<SoluCXWidget {...props} />);

        expect(queryByTestId("webview")).toBeNull();

        await waitFor(() => {
            expect(mockRequestWidgetUrl).toHaveBeenCalledTimes(1);
            expect(mockShouldDisplayWidget).toHaveBeenCalledTimes(1);
            expect(mockOpen).toHaveBeenCalledTimes(1);
            expect(queryByTestId("webview")).toBeTruthy();
        });

        const webview = getByTestId("webview");
        expect(webview.props.source.uri).toBe(bootstrappedWidgetUrl);
    });

    it("keeps widget hidden when preflight fetch fails", async () => {
        mockRequestWidgetUrl.mockRejectedValue(new Error("network"));

        const props = {
            ...baseProps,
            data: {
                customer_id: "cust-777",
                journey: "sac",
            },
            type: "bottom" as const,
        };

        const { queryByTestId } = render(<SoluCXWidget {...props} />);

        expect(queryByTestId("webview")).toBeNull();

        await waitFor(() => {
            // Validation runs BEFORE preflight to reduce API load at scale
            expect(mockShouldDisplayWidget).toHaveBeenCalledTimes(1);
            expect(mockRequestWidgetUrl).toHaveBeenCalledTimes(1);
            expect(queryByTestId("webview")).toBeNull();
        });
    });

    it("keeps widget hidden when validation fails before preflight", async () => {
        mockRequestWidgetUrl.mockResolvedValue({ available: true, url: bootstrappedWidgetUrl });
        mockShouldDisplayWidget.mockResolvedValue({ canDisplay: false, blockReason: "BLOCKED_BY_MAX_ATTEMPTS" });

        const props = {
            ...baseProps,
            data: {
                customer_id: "cust-777",
                journey: "sac",
            },
            type: "bottom" as const,
        };

        const { queryByTestId } = render(<SoluCXWidget {...props} />);

        expect(queryByTestId("webview")).toBeNull();

        await waitFor(() => {
            // Validation blocks BEFORE preflight — preflight is never called
            expect(mockShouldDisplayWidget).toHaveBeenCalledTimes(1);
            expect(mockRequestWidgetUrl).not.toHaveBeenCalled();
            expect(mockOpen).not.toHaveBeenCalled();
            expect(queryByTestId("webview")).toBeNull();
        });
    });

    it("keeps widget hidden and skips all fetches when transaction was already answered", async () => {
        mockShouldDisplayForTransaction.mockResolvedValue({
            canDisplay: false,
            blockReason: "BLOCKED_BY_TRANSACTION_ALREADY_ANSWERED",
        });
        const onBlocked = jest.fn();

        const props = {
            ...baseProps,
            type: "bottom" as const,
            callbacks: { onBlocked },
        };

        const { queryByTestId } = render(<SoluCXWidget {...props} />);

        await waitFor(() => {
            expect(mockShouldDisplayForTransaction).toHaveBeenCalledWith('txn-999');
            expect(mockShouldDisplayWidget).not.toHaveBeenCalled();
            expect(mockRequestWidgetOptions).not.toHaveBeenCalled();
            expect(mockRequestWidgetUrl).not.toHaveBeenCalled();
            expect(onBlocked).toHaveBeenCalledWith('BLOCKED_BY_TRANSACTION_ALREADY_ANSWERED');
            expect(queryByTestId("webview")).toBeNull();
        });
    });
});

describe("SoluCXWidget callbacks", () => {
    it("saves lastDismiss when native close button is pressed", async () => {
        mockRequestWidgetUrl.mockResolvedValue({ available: true, url: bootstrappedWidgetUrl });

        const { getByText } = render(<SoluCXWidget {...baseProps} type="modal" />);

        await waitFor(() => {
            expect(getByText("✕")).toBeTruthy();
        });

        fireEvent.press(getByText("✕"));

        await waitFor(() => {
            expect(mockHide).toHaveBeenCalledTimes(1);
            expect(mockStateManager.updateTimestamp).toHaveBeenCalledWith("lastDismiss");
        });
    });

    it("calls onError when data is not provided", () => {
        const onError = jest.fn();
        const props = {
            ...baseProps,
            data: null as any,
            callbacks: { onError },
        };

        render(<SoluCXWidget {...props} type="modal" />);

        expect(onError).toHaveBeenCalled();
        expect(onError).toHaveBeenCalledWith("Widget data is required but was not provided");
    });

    it("calls onError with Error message when bootstrap fails with Error instance", async () => {
        mockRequestWidgetUrl.mockRejectedValue(new Error("Network timeout"));
        const onError = jest.fn();

        const props = {
            ...baseProps,
            data: {
                customer_id: "cust-777",
                journey: "sac",
            },
            type: "bottom" as const,
            callbacks: { onError },
        };

        render(<SoluCXWidget {...props} />);

        await waitFor(() => {
            expect(onError).toHaveBeenCalledTimes(1);
            expect(onError).toHaveBeenCalledWith("Network timeout");
            expect(mockHide).toHaveBeenCalledTimes(1);
        });
    });

    it("calls onError with string when bootstrap fails with string error", async () => {
        mockRequestWidgetUrl.mockRejectedValue("Connection failed");
        const onError = jest.fn();

        const props = {
            ...baseProps,
            data: {
                customer_id: "cust-777",
                journey: "sac",
            },
            type: "bottom" as const,
            callbacks: { onError },
        };

        render(<SoluCXWidget {...props} />);

        await waitFor(() => {
            expect(onError).toHaveBeenCalledTimes(1);
            expect(onError).toHaveBeenCalledWith("Connection failed");
        });
    });

    it("calls onError with JSON string when bootstrap fails with object error", async () => {
        mockRequestWidgetUrl.mockRejectedValue({ code: 500, message: "Server error" });
        const onError = jest.fn();

        const props = {
            ...baseProps,
            data: {
                customer_id: "cust-777",
                journey: "sac",
            },
            type: "bottom" as const,
            callbacks: { onError },
        };

        render(<SoluCXWidget {...props} />);

        await waitFor(() => {
            expect(onError).toHaveBeenCalledTimes(1);
            expect(onError).toHaveBeenCalledWith('{"code":500,"message":"Server error"}');
        });
    });

    it('calls onError with "Unknown error" when bootstrap fails with null', async () => {
        mockRequestWidgetUrl.mockRejectedValue(null);
        const onError = jest.fn();

        const props = {
            ...baseProps,
            data: {
                customer_id: "cust-777",
                journey: "sac",
            },
            type: "bottom" as const,
            callbacks: { onError },
        };

        render(<SoluCXWidget {...props} />);

        await waitFor(() => {
            expect(onError).toHaveBeenCalledTimes(1);
            expect(onError).toHaveBeenCalledWith("Unknown error");
        });
    });

    it("calls onBlocked when validation fails", async () => {
        mockRequestWidgetUrl.mockResolvedValue({ available: true, url: bootstrappedWidgetUrl });
        mockShouldDisplayWidget.mockResolvedValue({
            canDisplay: false,
            blockReason: "BLOCKED_BY_MAX_ATTEMPTS",
        });
        const onBlocked = jest.fn();

        const props = {
            ...baseProps,
            data: {
                customer_id: "cust-777",
                journey: "sac",
            },
            type: "bottom" as const,
            callbacks: { onBlocked },
        };

        render(<SoluCXWidget {...props} />);

        await waitFor(() => {
            expect(onBlocked).toHaveBeenCalledTimes(1);
            expect(onBlocked).toHaveBeenCalledWith("BLOCKED_BY_MAX_ATTEMPTS");
            expect(mockHide).toHaveBeenCalledTimes(1);
        });
    });

    it("calls onPreOpen, onOpened callbacks for successful bootstrap", async () => {
        mockRequestWidgetUrl.mockResolvedValue({ available: true, url: bootstrappedWidgetUrl });
        mockShouldDisplayWidget.mockResolvedValue({ canDisplay: true });
        const onPreOpen = jest.fn();
        const onOpened = jest.fn();

        const props = {
            ...baseProps,
            data: {
                customer_id: "cust-777",
                journey: "sac",
            },
            type: "bottom" as const,
            callbacks: { onPreOpen, onOpened },
        };

        render(<SoluCXWidget {...props} />);

        await waitFor(() => {
            expect(onPreOpen).toHaveBeenCalledTimes(1);
            expect(onPreOpen).toHaveBeenCalledWith("test-user-123");
            expect(onOpened).toHaveBeenCalledTimes(1);
            expect(onOpened).toHaveBeenCalledWith("test-user-123");
        });
    });
});

describe("SoluCXWidget error handling from requestWidgetUrl", () => {
    it("calls onError when requestWidgetUrl throws error for non-ok response (404)", async () => {
        mockRequestWidgetUrl.mockRejectedValue(new Error("Failed to get error response: 404 Not Found"));
        const onError = jest.fn();

        const props = {
            ...baseProps,
            type: "modal" as const,
            callbacks: { onError },
        };

        const { queryByTestId } = render(<SoluCXWidget {...props} />);

        await waitFor(() => {
            expect(mockRequestWidgetUrl).toHaveBeenCalledTimes(1);
            expect(onError).toHaveBeenCalledTimes(1);
            expect(onError).toHaveBeenCalledWith("Failed to get error response: 404 Not Found");
            expect(mockHide).toHaveBeenCalledTimes(1);
            expect(queryByTestId("webview")).toBeNull();
        });
    });

    it("calls onError when requestWidgetUrl throws error for non-ok response (500)", async () => {
        mockRequestWidgetUrl.mockRejectedValue(new Error("Failed to get error response: 500 Internal Server Error"));
        const onError = jest.fn();

        const props = {
            ...baseProps,
            type: "inline" as const,
            callbacks: { onError },
        };

        const { queryByTestId } = render(<SoluCXWidget {...props} />);

        await waitFor(() => {
            expect(mockRequestWidgetUrl).toHaveBeenCalledTimes(1);
            expect(onError).toHaveBeenCalledTimes(1);
            expect(onError).toHaveBeenCalledWith("Failed to get error response: 500 Internal Server Error");
            expect(mockHide).toHaveBeenCalledTimes(1);
            expect(queryByTestId("webview")).toBeNull();
        });
    });

    it("calls onError when requestWidgetUrl throws error for fetch not available", async () => {
        mockRequestWidgetUrl.mockRejectedValue(new Error("Fetch is not available"));
        const onError = jest.fn();

        const props = {
            ...baseProps,
            type: "bottom" as const,
            callbacks: { onError },
        };

        const { queryByTestId } = render(<SoluCXWidget {...props} />);

        await waitFor(() => {
            expect(mockRequestWidgetUrl).toHaveBeenCalledTimes(1);
            expect(onError).toHaveBeenCalledTimes(1);
            expect(onError).toHaveBeenCalledWith("Fetch is not available");
            expect(mockHide).toHaveBeenCalledTimes(1);
            expect(queryByTestId("webview")).toBeNull();
        });
    });

    it("calls onError when requestWidgetUrl throws error for missing URL in response", async () => {
        mockRequestWidgetUrl.mockRejectedValue(new Error("Failed to get the widget api response."));
        const onError = jest.fn();

        const props = {
            ...baseProps,
            type: "top" as const,
            callbacks: { onError },
        };

        const { queryByTestId } = render(<SoluCXWidget {...props} />);

        await waitFor(() => {
            expect(mockRequestWidgetUrl).toHaveBeenCalledTimes(1);
            expect(onError).toHaveBeenCalledTimes(1);
            expect(onError).toHaveBeenCalledWith("Failed to get the widget api response.");
            expect(mockHide).toHaveBeenCalledTimes(1);
            expect(queryByTestId("webview")).toBeNull();
        });
    });

    it("calls shouldDisplayWidget before requestWidgetUrl and handles preflight failure", async () => {
        mockRequestWidgetUrl.mockRejectedValue(new Error("Failed to fetch widget URL: 403 Forbidden"));
        const onError = jest.fn();

        const props = {
            ...baseProps,
            type: "modal" as const,
            callbacks: { onError },
        };

        render(<SoluCXWidget {...props} />);

        await waitFor(() => {
            // Validation runs BEFORE preflight to avoid unnecessary API calls
            expect(mockShouldDisplayWidget).toHaveBeenCalled();
            expect(mockRequestWidgetUrl).toHaveBeenCalledTimes(1);
            expect(mockOpen).not.toHaveBeenCalled();
            expect(onError).toHaveBeenCalledWith("Failed to fetch widget URL: 403 Forbidden");
        });
    });

    it("does not call onPreOpen or onOpened when requestWidgetUrl fails", async () => {
        mockRequestWidgetUrl.mockRejectedValue(new Error("Failed to fetch widget URL: 401 Unauthorized"));
        const onPreOpen = jest.fn();
        const onOpened = jest.fn();
        const onError = jest.fn();

        const props = {
            ...baseProps,
            type: "inline" as const,
            callbacks: { onPreOpen, onOpened, onError },
        };

        render(<SoluCXWidget {...props} />);

        await waitFor(() => {
            // Validation runs first, then preflight fails
            expect(mockShouldDisplayWidget).toHaveBeenCalled();
            expect(mockRequestWidgetUrl).toHaveBeenCalledTimes(1);
            expect(onPreOpen).not.toHaveBeenCalled();
            expect(onOpened).not.toHaveBeenCalled();
            expect(onError).toHaveBeenCalledWith("Failed to fetch widget URL: 401 Unauthorized");
        });
    });

    it("widget remains hidden when requestWidgetUrl fails with 404", async () => {
        mockRequestWidgetUrl.mockRejectedValue(new Error("Failed to get error response: 404 Not Found"));

        const props = {
            ...baseProps,
            type: "bottom" as const,
        };

        const { queryByTestId } = render(<SoluCXWidget {...props} />);

        // Initially null
        expect(queryByTestId("webview")).toBeNull();

        await waitFor(() => {
            // Validation runs first, then preflight fails
            expect(mockShouldDisplayWidget).toHaveBeenCalled();
            expect(mockRequestWidgetUrl).toHaveBeenCalledTimes(1);
        });

        // Should remain null after failure
        expect(queryByTestId("webview")).toBeNull();
        expect(mockHide).toHaveBeenCalledTimes(1);
    });
});
