import {
    getFunnelCookie,
    getDeviceIdValue,
    getSessionKeyValue,
    getSessionIdValue,
    setCookieProperties,
    regenerateDeviceId,
    getUserIdValue,
    regenerateUserId,
    setSessionKeyIfUnset,
    setSessionIdIfUnset,
    isCookieSet,
    refreshCookieExpiration,
    getAffiliateCookies,
} from "@/helpers/heritage-integration/cookie-helper.js";
import { cookieNames } from "@/constants/cookie-names";
import {
    removeAllTestCookies,
    setupCookies,
    setupCrypto,
    setupAffiliateCookies,
} from "@/helpers/unit-test-helper";
import { deleteFunnelCookie } from "./cookie-helper";

const randomUUID = "68d89736-c277-46f1-8fee-c3dacdb23c08";

describe("cookies", () => {
    beforeEach(() => {
        setupCrypto(randomUUID);
    });

    afterEach(() => {
        removeAllTestCookies();
    });

    describe("getFunnelCookie method", () => {
        test("gets correct value when cookie is present", () => {
            // Arrange
            const testReferralNumber = 1566818;
            const testReferralDate = "2022-03-15T10:56:24.597";
            const testReferralCorrelationId = "404d2b04-f86e-45c3-b373-127b6217b060";
            const testShouldResetState = false;
            const testDidHeritageFunnelUpdateLast = true;

            const testCookieValue = {
                ReferralNumber: testReferralNumber,
                ReferralDate: testReferralDate,
                ReferralCorrelationId: testReferralCorrelationId,
                ShouldResetState: testShouldResetState,
                DidHeritageFunnelUpdateLast: testDidHeritageFunnelUpdateLast,
                SuppressConceptFunnel: true,
            };

            setupCookies({ funnelCookieValue: JSON.stringify(testCookieValue) });

            // Act
            var result = getFunnelCookie();

            // Assert
            expect(result).toEqual(testCookieValue);
            expect(typeof result).toEqual("object");
            expect(result.ReferralNumber).toEqual(testReferralNumber);
            expect(result.ReferralDate).toEqual(testReferralDate);
            expect(result.ReferralCorrelationId).toEqual(testReferralCorrelationId);
            expect(result.ShouldResetState).toEqual(testShouldResetState);
            expect(result.DidHeritageFunnelUpdateLast).toEqual(testDidHeritageFunnelUpdateLast);
        });

        test("returns empty object when value is empty object", () => {
            // Arrange
            const testCookieValue = {};
            setupCookies({ funnelCookieValue: JSON.stringify(testCookieValue) });

            // Act
            var result = getFunnelCookie();

            // Assert
            expect(result).toEqual(testCookieValue);
            expect(typeof result).toEqual("object");
            expect(Object.keys(result)).toHaveLength(0);
        });

        test("returns null when value is empty string", () => {
            // Arrange
            const testCookieValue = "";
            setupCookies({ funnelCookieValue: testCookieValue });

            // Act
            var result = getFunnelCookie();

            // Assert
            expect(result).toEqual(null);
        });

        test("returns null when funnel cookie doesn't exist", () => {
            // Arrange
            setupCookies({ includeHeritageCookie: false });

            // Act
            var result = getFunnelCookie();

            // Assert
            expect(result).toEqual(null);
        });

        test("gets correct cookie value", () => {
            // Arrange
            const testCookieValue = { test: "testValue" };

            setupCookies({ funnelCookieValue: JSON.stringify(testCookieValue) });

            // Act
            const actualCookieValue = getFunnelCookie();

            // Assert
            expect(actualCookieValue).toEqual(testCookieValue);
        });

        test("getCookieValue: Gets null cookie value", () => {
            // Arrange
            setupCookies({ includeHeritageCookie: false });

            // Act
            const actualCookieValue = getFunnelCookie();

            // Assert
            expect(actualCookieValue).toBeNull();
        });

        test("delete should not return a cookie", () => {
            // Arrange
            const testReferralNumber = 1566818;
            const testReferralDate = "2022-03-15T10:56:24.597";
            const testReferralCorrelationId = "404d2b04-f86e-45c3-b373-127b6217b060";
            const testShouldResetState = false;
            const testDidHeritageFunnelUpdateLast = true;

            const testCookieValue = {
                ReferralNumber: testReferralNumber,
                ReferralDate: testReferralDate,
                ReferralCorrelationId: testReferralCorrelationId,
                ShouldResetState: testShouldResetState,
                DidHeritageFunnelUpdateLast: testDidHeritageFunnelUpdateLast,
                SuppressConceptFunnel: true,
            };

            setupCookies({ funnelCookieValue: JSON.stringify(testCookieValue) });

            // Act
            deleteFunnelCookie();
            var result = getFunnelCookie();

            // Assert
            expect(result).not.toEqual(testCookieValue);
            expect(typeof result).toEqual("object");
        });
    });

    describe("Device Id", () => {
        describe("getDeviceIdValue", () => {
            test("getDeviceIdValue, should return GUID", () => {
                // Arrange
                setupCookies({});

                // Act
                const result = getDeviceIdValue();

                //Assert
                expect(result).toBe("21b9b94a-ec23-42c1-aaac-e2ae4e4dbffe");
            });

            test("Should return 0s if unset", () => {
                //Arrange
                //Act
                const result = getDeviceIdValue();

                //Assert
                expect(result).toBe("00000000-0000-0000-0000-000000000000");
            });

            test("Should return id even if cookie contains other data", () => {
                //Arrange
                setCookieProperties(
                    {
                        [cookieNames.DXDEV]:
                            "did=f4a1a9e8-b3f3-4936-8c30-2f06a98644af&tz=-300&tzd=1",
                    },
                    {}
                );

                //Act
                const result = getDeviceIdValue();

                //Assert
                expect(result).toBe("f4a1a9e8-b3f3-4936-8c30-2f06a98644af");
            });
        });

        describe("regenerateDeviceId", () => {
            test("Generates a new id if unset", () => {
                // Arrange
                // Act
                regenerateDeviceId();
                const result = getDeviceIdValue();

                // Assert
                expect(result).not.toBe("00000000-0000-0000-0000-000000000000");
                expect(global.crypto.randomUUID).toBeCalled();
            });

            test("Does not create a new id if already set", () => {
                // Arrange
                setupCookies({});

                // Act
                regenerateDeviceId();
                const result = getDeviceIdValue();

                // Assert
                expect(result).toBe("21b9b94a-ec23-42c1-aaac-e2ae4e4dbffe");
                expect(global.crypto.randomUUID).not.toBeCalled();
            });
        });
    });

    describe("User Id", () => {
        describe("getUserIdValue", () => {
            test("Should return GUID", () => {
                // Arrange
                setupCookies({});

                // Act
                const result = getUserIdValue();

                //Assert
                expect(result).toBe("11aec5e8-92ba-4dc9-a8b6-179a916d8d7a");
            });

            test("Should return 0s if unset", () => {
                //Arrange
                //Act
                const result = getUserIdValue();

                //Assert
                expect(result).toBe("00000000-0000-0000-0000-000000000000");
            });
        });

        describe("regenerateUserId", () => {
            test("Generates a new id if unset", () => {
                // Arrange
                // Act
                regenerateUserId();
                const result = getUserIdValue();

                // Assert
                expect(result).not.toBe("00000000-0000-0000-0000-000000000000");
                expect(global.crypto.randomUUID).toBeCalled();
            });

            test("Does not create a new id if already set", () => {
                // Arrange
                setupCookies({});

                // Act
                regenerateUserId();
                const result = getUserIdValue();

                // Assert
                expect(result).toBe("11aec5e8-92ba-4dc9-a8b6-179a916d8d7a");
                expect(global.crypto.randomUUID).not.toBeCalled();
            });
        });
    });

    describe("Session Key", () => {
        describe("getSessionKeyValue", () => {
            test("Should return session key int", () => {
                // Arrange
                setupCookies({});

                // Act
                const result = getSessionKeyValue();

                //Assert
                expect(result).toBe("12345");
            });

            test("Should return 0 if unset", () => {
                // Arrange

                // Act
                const result = getSessionKeyValue();

                //Assert
                expect(result).toBe(0);
            });
        });

        describe("setSessionKeyIfUnset", () => {
            test("Should set the cookie if not previously set", () => {
                // Arrange

                // Act
                setSessionKeyIfUnset("54321");
                const result = getSessionKeyValue();

                // Assert
                expect(result).toBe("54321");
            });

            test("Should not set the cookie if previously set", () => {
                // Arrange
                setupCookies({});

                // Act
                setSessionKeyIfUnset("54321");
                const result = getSessionKeyValue();

                // Assert
                expect(result).toBe("12345");
            });
        });
    });

    describe("Session Id", () => {
        describe("getSessionIdValue", () => {
            test("Should return session id", () => {
                // Arrange
                setupCookies({});

                // Act
                const result = getSessionIdValue();

                //Assert
                expect(result).toBe("cba0c3d1-3c1b-4305-bb56-31aa50f58e27");
            });

            test("Should return 0s if unset", () => {
                // Arrange

                // Act
                const result = getSessionIdValue();

                //Assert
                expect(result).toBe("00000000-0000-0000-0000-000000000000");
            });
        });

        describe("setSessionIdIfUnset", () => {
            test("Should set the cookie if not previously set", () => {
                // Arrange

                // Act
                setSessionIdIfUnset("f01f463a-a02c-4d1a-8aaf-6ca920ae5f02");
                const result = getSessionIdValue();

                // Assert
                expect(result).toBe("f01f463a-a02c-4d1a-8aaf-6ca920ae5f02");
            });

            test("Should not set the cookie if previously set", () => {
                // Arrange
                setupCookies({});

                // Act
                setSessionIdIfUnset("f01f463a-a02c-4d1a-8aaf-6ca920ae5f02");
                const result = getSessionIdValue();

                // Assert
                expect(result).toBe("cba0c3d1-3c1b-4305-bb56-31aa50f58e27");
            });
        });
    });

    describe("isCookieSet", () => {
        test("Returns true if cookie is set and unexpired", () => {
            // Arrange
            setupCookies({});

            // Act
            const result = isCookieSet(cookieNames.SESSION_ID);

            // Assert
            expect(result).toBe(true);
        });

        test("Returns false if never set", () => {
            // Arrange
            // Act
            const result = isCookieSet(cookieNames.SESSION_ID);

            // Assert
            expect(result).toBe(false);
        });

        test("Returns false if cookie is expired", () => {
            // Arrange
            setupCookies({});

            // Act
            setCookieProperties(
                {
                    [cookieNames.SESSION_ID]: "test",
                },
                { maxAge: 0 }
            );
            const result = isCookieSet(cookieNames.SESSION_ID);

            // Assert
            expect(result).toBe(false);
        });
    });

    describe("refreshCookieExpiration", () => {
        test("Preserves value", () => {
            // Arrange
            setupCookies({});

            // Act
            const result1 = getSessionIdValue();
            refreshCookieExpiration(cookieNames.SESSION_ID, 1000000);
            const result2 = getSessionIdValue();

            // Assert
            expect(result1).toBe(result2);
        });

        test("Does not set cookie if not already set", () => {
            // Arrange

            // Act
            refreshCookieExpiration(cookieNames.SESSION_ID, 1000000);
            const result = isCookieSet(cookieNames.SESSION_ID);

            expect(result).toBe(false);
        });
    });
});
describe("getAffiliateCookies", () => {
    it("should return an empty array if no affiliate cookies are found", () => {
        setupAffiliateCookies({});
        expect(getAffiliateCookies()).toEqual([]);
    });

    it("should return an array of affiliate cookies when they are present", () => {
        setupAffiliateCookies({
            CookieName: "affiliate_cookie1_Track",
            CookieValue: "value_of_affiliate_cookie1",
        });

        const expectedCookies = [
            { CookieName: "affiliate_cookie1_Track", CookieValue: "value_of_affiliate_cookie1" },
        ];
        expect(getAffiliateCookies()).toEqual(expectedCookies);
    });
});
