import * as nodeHtmlParser from 'node-html-parser';
import Bugsnag from '@bugsnag/js';
import * as cdnUtils from "../cdnTransformation";
import * as mockdata from "./cdnTransformation.mockdata";
import * as cdnTransformationHandler from './cdnTransformation.handler.mockdata';
import * as Api from '../../services/api';

let bugsnagSpy;
let localStorageMock;
jest.setTimeout(30000);
beforeEach(() => {
  localStorageMock = (() => {
    let store = {
      CREATIVES_CDN_TRANSFORMATION_URL_SUFFIX: "cdn-cgi/image",
      CREATIVES_S3_BUCKET_PATH: "intouch_creative_assets",
      CREATIVES_CDN_BASE_URL: "https://storage.crm.n.content-cdn.io",
      CREATIVES_CDN_QUALITY_CONFIG:
        '{"EMAIL":75,"RCS":75,"VIBER":75,"WHATSAPP":75,"MOBILE_PUSH":75,"FACEBOOK":75,"LINE":75,"DEFAULT":75}',
      S3_CDN_MAP: '{"crm-nightly-new-fileservice.s3.amazonaws.com":{"cdn_host":"storage.crm.n.content-cdn.io","bucket_path":"intouch_creative_assets"}, "crm-prod-new-fileservice.s3.amazonaws.com": { "cdn_host": "storage.crm.p.content-cdn.io", "bucket_path": "fileservice.p/intouch_creative_assets" }}',
    };
    return {
      getItem(key) {
        return store[key];
      },
      setItem(key, value) {
        store[key] = value.toString();
      },
      clear() {
        store = {};
      },
      removeItem(key) {
        delete store[key];
      },
    };
  })();
  Object.defineProperty(window, "localStorage", { value: localStorageMock, writable: true, configurable: true});
  bugsnagSpy = jest.spyOn(Bugsnag, 'notify');
});

afterEach(() => {
  localStorage.setItem(
    "CREATIVES_CDN_QUALITY_CONFIG",
    '{"EMAIL":75,"RCS":75,"VIBER":75,"WHATSAPP":75,"MOBILE_PUSH":75,"FACEBOOK":75,"LINE":75,"DEFAULT":75}'
  );
  localStorage.setItem(
    "CREATIVES_S3_BUCKET_PATH", "intouch_creative_assets"
  );
  jest.restoreAllMocks();
  jest.resetAllMocks();
  delete window?.[cdnUtils.CREATIVES_S3_ASSET_FILESIZES];
});

describe("cdnTransformationTests", () => {
  describe("getCdnUrl()", () => {
    it("should return s3 url if bucket subfolder doesn't contain intouch_creative_assets", () => {
      const TEST_S3_URL = `https://crm-nightly-new-fileservice.s3.amazonaws.com/test/2c9233ed-0959-4aff-b749-9171b5c8.jpg`;
      const GENERATED_CDN_URL = cdnUtils.getCdnUrl({
        url: TEST_S3_URL,
        channelName: "EMAIL",
      });
      expect(GENERATED_CDN_URL).toEqual(TEST_S3_URL);
    });

    it("should return s3 if channelName is not defined", () => {
      const TEST_S3_URL = `https://crm-nightly-new-fileservice.s3.amazonaws.com/intouch_creative_assets/2c9233ed-0959-4aff-b749-9171b5c8.jpg`;
      const GENERATED_CDN_URL = cdnUtils.getCdnUrl({ url: TEST_S3_URL });
      expect(GENERATED_CDN_URL).toEqual(TEST_S3_URL);
    });

    it("should return s3 if specified channelSubType doesn't exist", () => {
      const TEST_S3_URL = `https://crm-nightly-new-fileservice.s3.amazonaws.com/intouch_creative_assets/2c9233ed-0959-4aff-b749-9171b5c8.jpg`;
      const GENERATED_CDN_URL = cdnUtils.getCdnUrl({
        url: TEST_S3_URL,
        channelName: "LINE",
        channelSubType: "ABC",
      });
      expect(GENERATED_CDN_URL).toEqual(TEST_S3_URL);
    });

    it("Should replace s3 url with cdn url for email when h/w are not provided", () => {
      const TEST_S3_URL = `https://crm-nightly-new-fileservice.s3.amazonaws.com/intouch_creative_assets/2c9233ed-0959-4aff-b749-9171b5c8.jpg`;
      const GENERATED_CDN_URL = cdnUtils.getCdnUrl({
        url: TEST_S3_URL,
        channelName: "EMAIL",
      });
      const EXPECTED_CDN_URL = `https://storage.crm.n.content-cdn.io/cdn-cgi/image/format=auto,quality=75,/intouch_creative_assets/2c9233ed-0959-4aff-b749-9171b5c8.jpg`;
      expect(GENERATED_CDN_URL).toEqual(EXPECTED_CDN_URL);
    });

    it("Should replace s3 url with cdn url for email when h/w are provided", () => {
      const TEST_S3_URL = `https://crm-nightly-new-fileservice.s3.amazonaws.com/intouch_creative_assets/2c9233ed-0959-4aff-b749-9171b5c8.jpg`;
      const GENERATED_CDN_URL = cdnUtils.getCdnUrl({
        url: TEST_S3_URL,
        channelName: "EMAIL",
        height: 100,
        width: 200,
      });
      const EXPECTED_CDN_URL = `https://storage.crm.n.content-cdn.io/cdn-cgi/image/width=200,height=100,format=auto,quality=75,/intouch_creative_assets/2c9233ed-0959-4aff-b749-9171b5c8.jpg`;
      expect(GENERATED_CDN_URL).toEqual(EXPECTED_CDN_URL);
    });

    it("Should replace s3 url with cdn url for email when bucket name is other than intouch_creatives_assets in case of prod.", () => {
      localStorage.setItem("CREATIVES_S3_BUCKET_PATH", "fileservice.in/intouch_creative_assets");
      const TEST_S3_URL = `https://crm-prod-new-fileservice.s3.amazonaws.com/fileservice.p/intouch_creative_assets/2c9233ed-0959-4aff-b749-9171b5c8.jpg`;
      const GENERATED_CDN_URL = cdnUtils.getCdnUrl({
        url: TEST_S3_URL,
        channelName: "EMAIL",
        height: 100,
        width: 200,
      });
      const EXPECTED_CDN_URL = `https://storage.crm.p.content-cdn.io/cdn-cgi/image/width=200,height=100,format=auto,quality=75,/fileservice.p/intouch_creative_assets/2c9233ed-0959-4aff-b749-9171b5c8.jpg`;
      expect(GENERATED_CDN_URL).toEqual(EXPECTED_CDN_URL);
    });

    it("Should replace s3 url with cdn url for email when bucket name is other than intouch_creatives_assets in case of prod. It should remove leading/trailing forward slashes from bucket path", () => {
      localStorage.setItem("CREATIVES_S3_BUCKET_PATH", "/fileservice.in/intouch_creative_assets/");
      const TEST_S3_URL = `https://crm-prod-new-fileservice.s3.amazonaws.com/fileservice.p/intouch_creative_assets/2c9233ed-0959-4aff-b749-9171b5c8.jpg`;
      const GENERATED_CDN_URL = cdnUtils.getCdnUrl({
        url: TEST_S3_URL,
        channelName: "EMAIL",
        height: 100,
        width: 200,
      });
      const EXPECTED_CDN_URL = `https://storage.crm.p.content-cdn.io/cdn-cgi/image/width=200,height=100,format=auto,quality=75,/fileservice.p/intouch_creative_assets/2c9233ed-0959-4aff-b749-9171b5c8.jpg`;
      expect(GENERATED_CDN_URL).toEqual(EXPECTED_CDN_URL);
    });

    it("Should replace s3 url with cdn url for email for gif formats", () => {
      const TEST_S3_URL = `https://crm-nightly-new-fileservice.s3.amazonaws.com/intouch_creative_assets/02557e68-6b7b-4d0e-ba6f-efcf8972.gif`;
      const GENERATED_CDN_URL = cdnUtils.getCdnUrl({
        url: TEST_S3_URL,
        channelName: "EMAIL",
        height: 100,
        width: 200,
      });
      const EXPECTED_CDN_URL = `https://storage.crm.n.content-cdn.io/cdn-cgi/image/width=200,height=100,format=auto,quality=75,/intouch_creative_assets/02557e68-6b7b-4d0e-ba6f-efcf8972.gif`;
      expect(GENERATED_CDN_URL).toEqual(EXPECTED_CDN_URL);
    });
    
    it("Should replace s3 url with cdn url for email without transformation for formats other than jpg/png/jpeg/gif", () => {
      const TEST_S3_URL = `https://crm-nightly-new-fileservice.s3.amazonaws.com/intouch_creative_assets/2c9233ed-0959-4aff-b749-9171b5c8.avif`; //this is random url
      const GENERATED_CDN_URL = cdnUtils.getCdnUrl({
        url: TEST_S3_URL,
        channelName: "EMAIL",
        height: 100,
        width: 200,
      });
      const EXPECTED_CDN_URL = `https://storage.crm.n.content-cdn.io/intouch_creative_assets/2c9233ed-0959-4aff-b749-9171b5c8.avif`;
      expect(GENERATED_CDN_URL).toEqual(EXPECTED_CDN_URL);
    });

    it("should replace cdn url with new cdn url for email incase h/w etc changed", () => {
      const TEST_S3_URL = `https://storage.crm.n.content-cdn.io/cdn-cgi/image/width=200,height=100,format=auto,quality=75,/intouch_creative_assets/2c9233ed-0959-4aff-b749-9171b5c8.jpg`;
      const GENERATED_CDN_URL = cdnUtils.getCdnUrl({
        url: TEST_S3_URL,
        channelName: "EMAIL",
        height: 400,
        width: 500,
      });
      const EXPECTED_CDN_URL = `https://storage.crm.n.content-cdn.io/cdn-cgi/image/width=500,height=400,format=auto,quality=75,/intouch_creative_assets/2c9233ed-0959-4aff-b749-9171b5c8.jpg`;
      expect(GENERATED_CDN_URL).toEqual(EXPECTED_CDN_URL);
    });

    it("should replace cdn url with new cdn url incase channelName is LINE and channelSubType is RICH_MESSAGE without transformation", () => {
      const TEST_S3_URL = `https://crm-nightly-new-fileservice.s3.amazonaws.com/intouch_creative_assets/2c9233ed-0959-4aff-b749-9171b5c8`;
      const GENERATED_CDN_URL = cdnUtils.getCdnUrl({
        url: TEST_S3_URL,
        channelName: "LINE",
        channelSubType: "RICH_MESSAGE",
      });
      const EXPECTED_CDN_URL = `https://storage.crm.n.content-cdn.io/intouch_creative_assets/2c9233ed-0959-4aff-b749-9171b5c8`;
      expect(GENERATED_CDN_URL).toEqual(EXPECTED_CDN_URL);
    });

    it("should replace cdn url with new cdn url for channels which has predefined h/w for channel", () => {
      const TEST_S3_URL = `https://crm-nightly-new-fileservice.s3.amazonaws.com/intouch_creative_assets/2c9233ed-0959-4aff-b749-9171b5c8.jpg`;
      const GENERATED_CDN_URL = cdnUtils.getCdnUrl({
        url: TEST_S3_URL,
        channelName: "RCS",
      });
      const EXPECTED_CDN_URL = `https://storage.crm.n.content-cdn.io/cdn-cgi/image/width=1440,height=720,quality=75,/intouch_creative_assets/2c9233ed-0959-4aff-b749-9171b5c8.jpg`;
      expect(GENERATED_CDN_URL).toEqual(EXPECTED_CDN_URL);
    });

    it("should return url directly if typeof CREATIVES_CDN_QUALITY_CONFIG is not object", () => {
      localStorage.setItem("CREATIVES_CDN_QUALITY_CONFIG", "a");
      const TEST_S3_URL = `https://crm-nightly-new-fileservice.s3.amazonaws.com/intouch_creative_assets/2c9233ed-0959-4aff-b749-9171b5c8.jpg`;
      const GENERATED_CDN_URL = cdnUtils.getCdnUrl({
        url: TEST_S3_URL,
        channelName: "EMAIL",
      });
      expect(GENERATED_CDN_URL).toEqual(TEST_S3_URL);
    });

    it("should return cdn url with full quality if quality is not number", () => {
      localStorage.setItem(
        "CREATIVES_CDN_QUALITY_CONFIG",
        '{"EMAIL":"a","RCS":75,"VIBER":75,"WHATSAPP":75,"MOBILE_PUSH":75,"FACEBOOK":75,"LINE":75,"DEFAULT":75}'
      );

      const TEST_S3_URL = `https://crm-nightly-new-fileservice.s3.amazonaws.com/intouch_creative_assets/2c9233ed-0959-4aff-b749-9171b5c8.jpg`;
      const GENERATED_CDN_URL = cdnUtils.getCdnUrl({
        url: TEST_S3_URL,
        channelName: "EMAIL",
        height: 100,
        width: 200,
      });
      const EXPECTED_CDN_URL = `https://storage.crm.n.content-cdn.io/cdn-cgi/image/width=200,height=100,format=auto,quality=100,/intouch_creative_assets/2c9233ed-0959-4aff-b749-9171b5c8.jpg`;

      expect(GENERATED_CDN_URL).toEqual(EXPECTED_CDN_URL);
    });
  });

  describe("updateImagesInHtml()", () => {
    it("should update images in html", async () => {
      const htmlContentsInput = mockdata.emailRawInput;
      const htmlContentsOutput = await cdnUtils.updateImagesInHtml(htmlContentsInput);
      const expected = mockdata.emailRawTransformed;
      expect(htmlContentsOutput).toEqual(expected);
    });

    it("should return input itself if input is either among undefined/null/empty string", async () => {
      expect(await cdnUtils.updateImagesInHtml(undefined)).toEqual(undefined);
      expect(await cdnUtils.updateImagesInHtml(null)).toEqual(null);
      expect(await cdnUtils.updateImagesInHtml("")).toEqual("");
    });

    it("should call bugsnag when parse() throws some unexpected error.", async () => {
      const parseSpy = jest.spyOn(nodeHtmlParser, 'parse').mockImplementation(() => {
        throw new Error();
      });
      expect(await cdnUtils.updateImagesInHtml(mockdata.emailRawInput)).toEqual(mockdata.emailRawInput);
      expect(bugsnagSpy).toHaveBeenCalled();
      parseSpy.mockRestore();
    });

    it("Should update images in html, (api call made here to find s3 images file sizes which are not in window object)", async () => {
      /**
       * Out of 3 images. One s3 url is in window object, one is cdn url and another is also s3 url but not in window object.
       */
      cdnTransformationHandler.server.listen();
      cdnTransformationHandler.server.use(cdnTransformationHandler.getS3FileSizesFromUrlSuccessResponse2);
      localStorage.setItem("CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY", "true");
      localStorage.setItem("CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY_MAPPING", "[[30, 90], [80, 85], [150, 80], [400, 75], [600, 70], [1200, 65], [102400, 60]]");
      window[cdnUtils.CREATIVES_S3_ASSET_FILESIZES] = {
        "https://crm-nightly-new-fileservice.s3.amazonaws.com/intouch_creative_assets/394c053f-309b-49fc-ba74-6e700b1.jpeg": 76800, //this image has quality 85 since file size less than 80kb
      };
      
      const htmlContentsInput = mockdata.emailRawInput2;
      const htmlContentsOutput = await cdnUtils.updateImagesInHtml(htmlContentsInput);
      const expected = mockdata.emailRawTransformed2;
      expect(htmlContentsOutput).toEqual(expected);
      cdnTransformationHandler.server.close();
    })

    it("Should update images in html, (api call results in failure - not mocked with msw)", async ()=>{
      /**
       * Out of 3 images. One s3 url is in window object, one is cdn url and another is also s3 url but not in window object.
       */
      localStorage.setItem("CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY", "true");      
      localStorage.setItem("CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY_MAPPING", "[[30, 90], [80, 85], [150, 80], [400, 75], [600, 70], [1200, 65], [102400, 60]]");
      window[cdnUtils.CREATIVES_S3_ASSET_FILESIZES] = {
        "https://crm-nightly-new-fileservice.s3.amazonaws.com/intouch_creative_assets/394c053f-309b-49fc-ba74-6e700b1.jpeg": 76800, //this image has quality 85 since file size less than 80kb
      };
      
      //since we are not able to make api call(since not used msw). We should get default quality for this image.
      const htmlContentsInput = mockdata.emailRawInput2;
      const htmlContentsOutput = await cdnUtils.updateImagesInHtml(htmlContentsInput);
      const expected = mockdata.emailRawTransformed3;
      expect(htmlContentsOutput).toEqual(expected);
    })
  });

  describe("transformEmailTemplate()", () => {
    it("should transform email template", async () => {
      const emailTemplateInput = mockdata.emailTemplateRaw;
      const emailTemplateOutput =
        await cdnUtils.transformEmailTemplates(emailTemplateInput);
      expect(emailTemplateOutput).toMatchSnapshot();
    });
    it("should return original contents transform email template throws an error inside. This might be due to improper input or unexpected error.", async () => {
      const emailTemplateInputWithError = mockdata.emailTemplateRawWithError;
      const emailTemplateOutput =
        await cdnUtils.transformEmailTemplates(emailTemplateInputWithError);
      expect(emailTemplateOutput).toEqual(emailTemplateInputWithError);
      expect(bugsnagSpy).toHaveBeenCalled();
    });
    it("should handle edge case where input is not in proper format", async () => {
      const emailTemplateOutput =
        await cdnUtils.transformEmailTemplates(mockdata.emailTemplateRaw2);
      expect(emailTemplateOutput).toEqual(mockdata.emailTemplateRaw2);
      expect(bugsnagSpy).toHaveBeenCalled();
    })

    it("should transform email template with overrideEmailQualityMapping when overrideEmailQuality is set true", async () => {
      localStorage.setItem("CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY", "true");      
      localStorage.setItem("CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY_MAPPING", "[[30, 90], [80, 85], [150, 80], [400, 75], [600, 70], [1200, 65], [102400, 60]]");
      
      window[cdnUtils.CREATIVES_S3_ASSET_FILESIZES] = {
        "https://crm-nightly-new-fileservice.s3.amazonaws.com/intouch_creative_assets/8d1498ab-099d-4145-ad15-edd77f7.jpeg": 292485,
        "https://crm-nightly-new-fileservice.s3.amazonaws.com/intouch_creative_assets/546a3d95-48be-4955-a07c-c4775da.jpeg": 9960,
      };

      const emailTemplateInput = mockdata.emailTemplateOverrideInput1;
      const emailTemplateOutput =
        await cdnUtils.updateImagesInHtml(emailTemplateInput);
      expect(emailTemplateOutput).toEqual(mockdata.emailTemplateOverrideOutput1); //first image has q=75 since less than 400KB, second image has q=90 since less than 30kB

    });


    it("should reuse the same previous quality from cdn url when overrideEmailQuality is set true", async () => {
      localStorage.setItem("CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY", "true");      
      localStorage.setItem("CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY_MAPPING", "[[30, 90], [80, 85], [150, 80], [400, 75], [600, 70], [1200, 65], [102400, 60]]");
      
      const emailTemplateInput = mockdata.emailTemplateOverrideOutput1;
      const emailTemplateOutput =
        await cdnUtils.updateImagesInHtml(emailTemplateInput);
      expect(emailTemplateOutput).toEqual(mockdata.emailTemplateOverrideOutput1); // Both input and output should be exactly same.
    });

    it("should transform email template with qualtyCfg if window objects CREATIVES_S3_ASSET_FILESIZES is somehow deleted", async () => {
      localStorage.setItem("CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY", "true");      
      localStorage.setItem("CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY_MAPPING", "[[30, 90], [80, 85], [150, 80], [400, 75], [600, 70], [1200, 65], [102400, 60]]");
      
      delete window?.[cdnUtils.CREATIVES_S3_ASSET_FILESIZES];

      const emailTemplateInput = mockdata.emailTemplateOverrideInput1;
      const emailTemplateOutput =
        await cdnUtils.updateImagesInHtml(emailTemplateInput);
      expect(emailTemplateOutput).toEqual(mockdata.emailTemplateOverrideOutputWithWindowDeleted1); //first image has q=75 since less than 400KB, second image has q=90 since less than 30kB

    });
  });

  describe("saveCdnConfigs()", () => {
    it("should set received input values in localStorage", () => {
      const cdnConfigs = {
        transformationUrlSuffix: "cdn-cgi/image",
        hostname: "https://storage.crm.n.content-cdn.io",
        qualityCfg: {
          EMAIL: 75,
          RCS: 75,
          VIBER: 75,
          WHATSAPP: 75,
          MOBILE_PUSH: 75,
          FACEBOOK: 75,
          LINE: 75,
          DEFAULT: 75,
        },
        bucketPath: 'intouch_creative_assets'
      };

      const expected = {
        CREATIVES_CDN_TRANSFORMATION_URL_SUFFIX: "cdn-cgi/image",
        CREATIVES_CDN_BASE_URL: "https://storage.crm.n.content-cdn.io",
        CREATIVES_CDN_QUALITY_CONFIG:
          '{"EMAIL":75,"RCS":75,"VIBER":75,"WHATSAPP":75,"MOBILE_PUSH":75,"FACEBOOK":75,"LINE":75,"DEFAULT":75}',
          CREATIVES_S3_BUCKET_PATH: 'intouch_creative_assets',
      };
      cdnUtils.saveCdnConfigs(cdnConfigs);

      expect(
        localStorage.getItem("CREATIVES_CDN_TRANSFORMATION_URL_SUFFIX")
      ).toBe(expected.CREATIVES_CDN_TRANSFORMATION_URL_SUFFIX);
      expect(localStorage.getItem("CREATIVES_CDN_BASE_URL")).toBe(
        expected.CREATIVES_CDN_BASE_URL
      );
      expect(localStorage.getItem("CREATIVES_CDN_QUALITY_CONFIG")).toBe(
        expected.CREATIVES_CDN_QUALITY_CONFIG
      );
      expect(localStorage.getItem("CREATIVES_S3_BUCKET_PATH")).toBe(
        expected.CREATIVES_S3_BUCKET_PATH
      );
    });

    it("should remove overrideEmailQualityMapping overrideEmailQuality if either of them is empty", () => {
      const cdnConfigs = {
        transformationUrlSuffix: "cdn-cgi/image",
        hostname: "https://storage.crm.n.content-cdn.io",
        qualityCfg: {
          EMAIL: 75,
          RCS: 75,
          VIBER: 75,
          WHATSAPP: 75,
          MOBILE_PUSH: 75,
          FACEBOOK: 75,
          LINE: 75,
          DEFAULT: 75,
        },
        bucketPath: 'intouch_creative_assets',
        overrideEmailQuality:true,
        overrideEmailQualityMapping: [[50, 90], [100, 85], [200, 80], [400, 75], [800,70], [5000, 65], [102400, 60]]
      };

      const expected = {
        CREATIVES_CDN_TRANSFORMATION_URL_SUFFIX: "cdn-cgi/image",
        CREATIVES_CDN_BASE_URL: "https://storage.crm.n.content-cdn.io",
        CREATIVES_CDN_QUALITY_CONFIG:
          '{"EMAIL":75,"RCS":75,"VIBER":75,"WHATSAPP":75,"MOBILE_PUSH":75,"FACEBOOK":75,"LINE":75,"DEFAULT":75}',
          CREATIVES_S3_BUCKET_PATH: 'intouch_creative_assets',
          CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY: "true",
          CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY_MAPPING: "[[50,90],[100,85],[200,80],[400,75],[800,70],[5000,65],[102400,60]]"
      };

      localStorage.setItem('CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY',true);
      cdnUtils.saveCdnConfigs(cdnConfigs);

      expect(
        localStorage.getItem("CREATIVES_CDN_TRANSFORMATION_URL_SUFFIX")
      ).toBe(expected.CREATIVES_CDN_TRANSFORMATION_URL_SUFFIX);
      expect(localStorage.getItem("CREATIVES_CDN_BASE_URL")).toBe(
        expected.CREATIVES_CDN_BASE_URL
      );
      expect(localStorage.getItem("CREATIVES_CDN_QUALITY_CONFIG")).toBe(
        expected.CREATIVES_CDN_QUALITY_CONFIG
      );
      expect(localStorage.getItem("CREATIVES_S3_BUCKET_PATH")).toBe(
        expected.CREATIVES_S3_BUCKET_PATH
      );
      expect(localStorage.getItem("CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY")).toBe(expected.CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY);
      expect(localStorage.getItem("CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY_MAPPING")).toBe(expected.CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY_MAPPING);
    });

    it("should remove overrideEmailQualityMapping overrideEmailQuality if either of them is empty", () => {
      const cdnConfigs = {
        transformationUrlSuffix: "cdn-cgi/image",
        hostname: "https://storage.crm.n.content-cdn.io",
        qualityCfg: {
          EMAIL: 75,
          RCS: 75,
          VIBER: 75,
          WHATSAPP: 75,
          MOBILE_PUSH: 75,
          FACEBOOK: 75,
          LINE: 75,
          DEFAULT: 75,
        },
        bucketPath: 'intouch_creative_assets'
      };

      const expected = {
        CREATIVES_CDN_TRANSFORMATION_URL_SUFFIX: "cdn-cgi/image",
        CREATIVES_CDN_BASE_URL: "https://storage.crm.n.content-cdn.io",
        CREATIVES_CDN_QUALITY_CONFIG:
          '{"EMAIL":75,"RCS":75,"VIBER":75,"WHATSAPP":75,"MOBILE_PUSH":75,"FACEBOOK":75,"LINE":75,"DEFAULT":75}',
          CREATIVES_S3_BUCKET_PATH: 'intouch_creative_assets',
      };

      localStorage.setItem('CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY',true);
      cdnUtils.saveCdnConfigs(cdnConfigs);

      expect(
        localStorage.getItem("CREATIVES_CDN_TRANSFORMATION_URL_SUFFIX")
      ).toBe(expected.CREATIVES_CDN_TRANSFORMATION_URL_SUFFIX);
      expect(localStorage.getItem("CREATIVES_CDN_BASE_URL")).toBe(
        expected.CREATIVES_CDN_BASE_URL
      );
      expect(localStorage.getItem("CREATIVES_CDN_QUALITY_CONFIG")).toBe(
        expected.CREATIVES_CDN_QUALITY_CONFIG
      );
      expect(localStorage.getItem("CREATIVES_S3_BUCKET_PATH")).toBe(
        expected.CREATIVES_S3_BUCKET_PATH
      );
      expect(localStorage.getItem("CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY")).toBe(undefined);
    });

    it("should clear items from localStorage if qualityConfigs is not present", () => {
      const cdnConfigs = {
        bucketPath: "intouch_creative_assets",
      };
      cdnUtils.saveCdnConfigs(cdnConfigs);
      expect(localStorage.getItem("CREATIVES_CDN_QUALITY_CONFIG")).toBe(
        undefined
      );
    });

    it("should clear items from localStorage if input does not contain hostname or transformationUrlSuffix", () => {
      const cdnConfigs = {
        qualityCfg: {
          EMAIL: 75,
          RCS: 75,
          VIBER: 75,
          WHATSAPP: 75,
          MOBILE_PUSH: 75,
          FACEBOOK: 75,
          LINE: 75,
          DEFAULT: 75,
        },
      };

      const expected = {
        CREATIVES_CDN_TRANSFORMATION_URL_SUFFIX: "cdn-cgi/image",
        CREATIVES_CDN_BASE_URL: "https://storage.crm.n.content-cdn.io",
        CREATIVES_CDN_QUALITY_CONFIG:
          '{"EMAIL":75,"RCS":75,"VIBER":75,"WHATSAPP":75,"MOBILE_PUSH":75,"FACEBOOK":75,"LINE":75,"DEFAULT":75}',
      };
      cdnUtils.saveCdnConfigs(cdnConfigs);

      expect(
        localStorage.getItem("CREATIVES_CDN_TRANSFORMATION_URL_SUFFIX")
      ).toBe(undefined);
      expect(localStorage.getItem("CREATIVES_CDN_BASE_URL")).toBe(undefined);
      expect(localStorage.getItem("CREATIVES_CDN_QUALITY_CONFIG")).toBe(
        expected.CREATIVES_CDN_QUALITY_CONFIG
      );
    });

    it("should clear items from localStorage if input is null or empty object", () => {
      const cdnConfigs = {};

      cdnUtils.saveCdnConfigs(cdnConfigs);

      expect(
        localStorage.getItem("CREATIVES_CDN_TRANSFORMATION_URL_SUFFIX")
      ).toBe(undefined);
      expect(localStorage.getItem("CREATIVES_CDN_BASE_URL")).toBe(undefined);
      expect(localStorage.getItem("CREATIVES_CDN_QUALITY_CONFIG")).toBe(undefined);
    });

    it("should call bugsnag notify if any unexpected error occured during removeAllCdnLocalStorageItems", () => {
      delete window.localStorage.removeItem;

      cdnUtils.removeAllCdnLocalStorageItems('CREATIVES_CDN_BASE_URL');

      expect(bugsnagSpy).toHaveBeenCalled();
    });

    it("should call bugsnag notify if any unexpected error occured during saveCdnConfigs", () => {
      delete window?.localStorage?.setItem; //this is a case used to mimick any unexpected error

      const cdnConfigs = {
        transformationUrlSuffix: "cdn-cgi/image",
        hostname: "https://storage.crm.n.content-cdn.io",
        qualityCfg: {
          DEFAULT: 75,
        },
        bucketPath: 'intouch_creative_assets'
      };

      cdnUtils.saveCdnConfigs(cdnConfigs);

      expect(bugsnagSpy).toHaveBeenCalled();

      window.localStorage.setItem = ()=>{};
    });
  });

  describe("initCdnConfigFromEnv()", () => {
    afterEach(() => {
      delete window.APP_ENV;
    });

    it("returns false when window.APP_ENV is undefined", () => {
      delete window.APP_ENV;
      expect(cdnUtils.initCdnConfigFromEnv()).toBe(false);
    });

    const completeEnv = {
      CDN_HOSTNAME: "https://storage.crm.n.content-cdn.io",
      CDN_IMG_TRANSFORMATION_URL_SUFFIX: "cdn-cgi/image",
      CREATIVE_ASSETS_BUCKET_PATH: "intouch_creative_assets",
      OVERRIDE_IMAGE_QUALITY: "false",
      CDN_IMG_QUALITY_CFG: "{}",
      IMAGE_QUALITY_MAPPING: "[]",
      S3_CDN_MAP: '{"host.s3.amazonaws.com":{"cdn_host":"cdn.example.com","bucket_path":"x"}}',
    };

    it.each([
      ["CDN_HOSTNAME"],
      ["CDN_IMG_TRANSFORMATION_URL_SUFFIX"],
      ["CREATIVE_ASSETS_BUCKET_PATH"],
      ["S3_CDN_MAP"],
    ])("returns false when required field %s is missing", (missingKey) => {
      window.APP_ENV = { ...completeEnv };
      delete window.APP_ENV[missingKey];
      expect(cdnUtils.initCdnConfigFromEnv()).toBe(false);
    });

    it.each([
      ["CDN_HOSTNAME"],
      ["CDN_IMG_TRANSFORMATION_URL_SUFFIX"],
      ["CREATIVE_ASSETS_BUCKET_PATH"],
      ["S3_CDN_MAP"],
    ])("returns false when required field %s is empty string", (emptyKey) => {
      window.APP_ENV = { ...completeEnv, [emptyKey]: "" };
      expect(cdnUtils.initCdnConfigFromEnv()).toBe(false);
    });

    it("populates localStorage and returns true for a complete env", () => {
      window.APP_ENV = {
        CDN_HOSTNAME: "https://storage.crm.n.content-cdn.io",
        CDN_IMG_TRANSFORMATION_URL_SUFFIX: "cdn-cgi/image",
        CREATIVE_ASSETS_BUCKET_PATH: "intouch_creative_assets",
        OVERRIDE_IMAGE_QUALITY: "true",
        CDN_IMG_QUALITY_CFG: '{"EMAIL":65,"DEFAULT":70}',
        IMAGE_QUALITY_MAPPING: '[[30,90],[80,85]]',
        S3_CDN_MAP: '{"host.s3.amazonaws.com":{"cdn_host":"cdn.example.com","bucket_path":"x"}}',
      };

      expect(cdnUtils.initCdnConfigFromEnv()).toBe(true);
      expect(localStorage.getItem("CREATIVES_CDN_BASE_URL")).toBe("https://storage.crm.n.content-cdn.io");
      expect(localStorage.getItem("CREATIVES_CDN_TRANSFORMATION_URL_SUFFIX")).toBe("cdn-cgi/image");
      expect(localStorage.getItem("CREATIVES_S3_BUCKET_PATH")).toBe("intouch_creative_assets");
      expect(localStorage.getItem("CREATIVES_CDN_QUALITY_CONFIG")).toBe('{"EMAIL":65,"DEFAULT":70}');
      expect(localStorage.getItem("CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY")).toBe("true");
      expect(localStorage.getItem("CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY_MAPPING")).toBe("[[30,90],[80,85]]");
      expect(JSON.parse(localStorage.getItem("S3_CDN_MAP"))).toEqual({
        "host.s3.amazonaws.com": { cdn_host: "cdn.example.com", bucket_path: "x" },
      });
    });

    it("uses fallback values for malformed optional JSON env vars (qualityCfg, mapping)", () => {
      window.APP_ENV = {
        CDN_HOSTNAME: "https://storage.crm.n.content-cdn.io",
        CDN_IMG_TRANSFORMATION_URL_SUFFIX: "cdn-cgi/image",
        CREATIVE_ASSETS_BUCKET_PATH: "intouch_creative_assets",
        OVERRIDE_IMAGE_QUALITY: "false",
        CDN_IMG_QUALITY_CFG: "not-valid-json{{",
        IMAGE_QUALITY_MAPPING: "also-broken",
        S3_CDN_MAP: '{"host.s3.amazonaws.com":{"cdn_host":"cdn.example.com","bucket_path":"x"}}',
      };

      expect(cdnUtils.initCdnConfigFromEnv()).toBe(true);
      expect(localStorage.getItem("CREATIVES_CDN_BASE_URL")).toBe("https://storage.crm.n.content-cdn.io");
    });

    it("returns false when S3_CDN_MAP is malformed JSON", () => {
      window.APP_ENV = { ...completeEnv, S3_CDN_MAP: "}{" };
      expect(cdnUtils.initCdnConfigFromEnv()).toBe(false);
    });

    it.each([
      ["empty object", "{}"],
      ["array", '["a","b"]'],
      ["null", "null"],
      ["number", "42"],
      ["string", '"foo"'],
    ])("returns false when S3_CDN_MAP parses to %s (not a non-empty object)", (_label, value) => {
      window.APP_ENV = { ...completeEnv, S3_CDN_MAP: value };
      expect(cdnUtils.initCdnConfigFromEnv()).toBe(false);
    });

    it("treats OVERRIDE_IMAGE_QUALITY values other than the string \"true\" as false", () => {
      window.APP_ENV = {
        CDN_HOSTNAME: "https://storage.crm.n.content-cdn.io",
        CDN_IMG_TRANSFORMATION_URL_SUFFIX: "cdn-cgi/image",
        CREATIVE_ASSETS_BUCKET_PATH: "intouch_creative_assets",
        OVERRIDE_IMAGE_QUALITY: "no",
        CDN_IMG_QUALITY_CFG: "{}",
        IMAGE_QUALITY_MAPPING: "[]",
        S3_CDN_MAP: '{"host.s3.amazonaws.com":{"cdn_host":"cdn.example.com","bucket_path":"x"}}',
      };

      cdnUtils.initCdnConfigFromEnv();
      expect(localStorage.getItem("CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY")).toBe(undefined);
    });

    it("returns false and notifies Bugsnag when window.APP_ENV access throws", () => {
      // Force the `window.APP_ENV` read inside initCdnConfigFromEnv to throw,
      // which exercises the function's outer catch block.
      Object.defineProperty(window, "APP_ENV", {
        get() { throw new Error("APP_ENV access boom"); },
        configurable: true,
      });
      const breadcrumbSpy = jest.spyOn(Bugsnag, "leaveBreadcrumb");

      expect(cdnUtils.initCdnConfigFromEnv()).toBe(false);
      expect(breadcrumbSpy).toHaveBeenCalledWith(
        "initCdnConfigFromEnv failed to apply window.APP_ENV"
      );
      expect(bugsnagSpy).toHaveBeenCalled();
    });
  });

  describe("getEmailImageOverrideQuality()",()=>{
    it("Should return quality of last element in array if file size is greater than max provided in array",()=>{
      localStorage.setItem("CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY", "true");      
      localStorage.setItem("CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY_MAPPING", "[[30, 90], [80, 85], [150, 80], [400, 75], [600, 70], [1200, 65], [102400, 60]]");
     
      let fileSize = 10**8; // large file size. We don't have mapping for a file this large. 

      expect(cdnUtils.getEmailImageOverrideQuality(fileSize)).toEqual(60);
    })

    it("Should return -1 if any exception is thrown",()=>{
      localStorage.setItem("CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY", "true");      
      localStorage.setItem("CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY_MAPPING", 'abc');
     
      let fileSize = 200;

      expect(cdnUtils.getEmailImageOverrideQuality(fileSize)).toEqual(-1);
    })

    it("Should return -1 if mapping is empty",()=>{
      localStorage.setItem("CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY", "true");      
      localStorage.setItem("CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY_MAPPING", "[]");
     
      let fileSize = 10**8; // large file size. We don't have mapping for a file this large. 

      expect(cdnUtils.getEmailImageOverrideQuality(fileSize)).toEqual(-1);
    })

    it("Should return -1 if mapping is not proper",()=>{
      localStorage.setItem("CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY", "true");      
      localStorage.setItem("CREATIVES_CDN_OVERRIDE_DEFAULT_EMAIL_QUALITY_MAPPING", "[[]]");
     
      let fileSize = 10**8; // large file size. We don't have mapping for a file this large. 

      expect(cdnUtils.getEmailImageOverrideQuality(fileSize)).toEqual(-1);
    })
  })

  describe("getFizeSizeFromUrl()",()=>{
    it("Should return -1 if fileSize details is empty/null in window object",()=>{

      let s3Url = "https://crm-nightly-new-fileservice.s3.amazonaws.com/intouch_creative_assets/8d1498ab-099d-4145-ad15-edd77f7.jpeg";

      window[cdnUtils.CREATIVES_S3_ASSET_FILESIZES] = {
        [s3Url]: null,
      };

      expect(cdnUtils.getFizeSizeFromUrl(s3Url)).toEqual(undefined);
    })
  })

  describe("storeS3FileSizeDetails()",()=>{
    it("Should store fileSize in window object in property CREATIVES_S3_ASSET_FILESIZES",()=>{
      let s3Url = "https://crm-nightly-new-fileservice.s3.amazonaws.com/intouch_creative_assets/8d1498ab-099d-4145-ad15-edd77f7.jpeg";
      let fileSize = 1024;

      cdnUtils.storeS3FileSizeDetails(s3Url, fileSize);

      expect(window[cdnUtils.CREATIVES_S3_ASSET_FILESIZES][s3Url]).toEqual(fileSize);
    })

    it("Should not store in window object if url is not string or fileSize is not number ",()=>{
      let s3Url = "https://crm-nightly-new-fileservice.s3.amazonaws.com/intouch_creative_assets/8d1498ab-099d-4145-ad15-edd77f7.jpeg";
      let fileSize = 1024;

      cdnUtils.storeS3FileSizeDetails({}, fileSize);
      expect(window[cdnUtils.CREATIVES_S3_ASSET_FILESIZES]?.[s3Url]).toEqual(undefined);

      cdnUtils.storeS3FileSizeDetails(s3Url, 'abc');
      expect(window[cdnUtils.CREATIVES_S3_ASSET_FILESIZES]?.[s3Url]).toEqual(undefined);
    })

    it("Should  not store in window object property CREATIVES_S3_ASSET_FILESIZES was modified and freezed",()=>{
      let s3Url = "https://crm-nightly-new-fileservice.s3.amazonaws.com/intouch_creative_assets/8d1498ab-099d-4145-ad15-edd77f7.jpeg";
      let fileSize = 1024;

      window[cdnUtils.CREATIVES_S3_ASSET_FILESIZES] = {};
      Object.freeze(window[cdnUtils.CREATIVES_S3_ASSET_FILESIZES]);

      cdnUtils.storeS3FileSizeDetails(s3Url, fileSize);

      expect(window[cdnUtils.CREATIVES_S3_ASSET_FILESIZES][s3Url]).toEqual(undefined);
    })
  })

  describe('getCdnEmailImageQuality()', () => { 
    it("should return -1 if previous quality param in cdn url is not a number",()=>{
      let cdnUrl = "https://storage.crm.n.content-cdn.io/cdn-cgi/image/width=200,height=100,format=auto,quality=abc,/fileservice.in/intouch_creative_assets/2c9233ed-0959-4aff-b749-9171b5c8.jpg";
      expect(cdnUtils.getCdnEmailImageQuality(cdnUrl)).toEqual(-1);
    })

    it("should return -1 if string doesn't contain quality",()=>{
      let cdnUrl = "https://storage.crm.n.content-cdn.io/cdn-cgi/image/width=200,height=100,format=auto/fileservice.in/intouch_creative_assets/2c9233ed-0959-4aff-b749-9171b5c8.jpg";
      expect(cdnUtils.getCdnEmailImageQuality(cdnUrl)).toEqual(-1);
    })

    it("should return -1 if quality is 0",()=>{
      let cdnUrl = "https://storage.crm.n.content-cdn.io/cdn-cgi/image/width=200,height=100,format=auto,quality=0/fileservice.in/intouch_creative_assets/2c9233ed-0959-4aff-b749-9171b5c8.jpg";
      expect(cdnUtils.getCdnEmailImageQuality(cdnUrl)).toEqual(-1);
    })
   })

  describe('getS3FileSizesFromUrl()',()=>{
    beforeEach(()=>{
      cdnTransformationHandler.server.listen()
    })
    afterEach(()=>{
      cdnTransformationHandler.server.resetHandlers();
      cdnTransformationHandler.server.close();
    })

        it("getS3FileSizesFromUrl : success case", async () => {
      // Mock the API call directly since MSW isn't working in this environment
      const mockApiResponse = {
        success: true,
        status: {
          isError: false,
          code: 200,
          message: "success"
        },
        message: "Meta data fecthed successfully",
        response: {
          "123.jpg": 400,
          "456.jpg": 500,
        }
      };
      
      jest.spyOn(Api, 'getS3UrlFileSizes').mockResolvedValue(mockApiResponse);

      const result = await cdnUtils.getS3FileSizesFromUrl([
        "123.jpg",
        "456.jpg",
      ]);
      
      expect(result).toEqual({
        "123.jpg": 400,
        "456.jpg": 500,
      });
    });

    it("getS3FileSizesFromUrl : failure case", async () => {
      cdnTransformationHandler.server.use(cdnTransformationHandler.getS3FileSizesFromUrlFailureResponse);

      expect(
        await cdnUtils.getS3FileSizesFromUrl([
          "123.jpg",
          "456.jpg",
        ])
      ).toEqual({});
    });

  })
});
