import { IRecommendation } from '@rh-support/api';
import CaseUtils from '../caseUtils';

describe('CaseUtils getApiResourceObject', () => {
    it('getApiResourceObject should return the passed data and defaults for other fields', () => {
        const res = CaseUtils.getApiResourceObject({details: 'Test'});
        expect(res.data).toEqual({details: 'Test'});
        expect(res.isFetching).toBe(false);
        expect(res.isError).toBe(false);
        expect(res.errorMessage).toBe('');
    });
    it('getApiResourceObject should return the passed data and loading state with defaults for others', () => {
        const res = CaseUtils.getApiResourceObject({details: 'Test'}, true);
        expect(res.data).toEqual({details: 'Test'});
        expect(res.isFetching).toBe(true);
        expect(res.isError).toBe(false);
        expect(res.errorMessage).toBe('');
    });
    it('getApiResourceObject should return the passed data, loading and error state with defaults for others', () => {
        const res = CaseUtils.getApiResourceObject({details: 'Test'}, true, true);
        expect(res.data).toEqual({details: 'Test'});
        expect(res.isFetching).toBe(true);
        expect(res.isError).toBe(true);
        expect(res.errorMessage).toBe('');
    });
    it('getApiResourceObject should return the passed fields and not use defaults', () => {
        const res = CaseUtils.getApiResourceObject(null, true, true, 'There was and error fetching data');
        expect(res.data).toEqual(null);
        expect(res.isFetching).toBe(true);
        expect(res.isError).toBe(true);
        expect(res.errorMessage).toBe('There was and error fetching data');
    });
});

describe('CaseUtils getRecommendationTitle', () => {
    const doc: IRecommendation = {
        '[elevated]': false,
        abstract: '',
        allTitle: '',
        publishedAbstract: '',
        publishedTitle: '',
        documentKind: '',
        id: '',
        issue: [''],
        kcsRateDown: 121,
        kcsRateUp: 0,
        kcsState: '',
        lastModifiedDate: new Date(),
        score: 132,
        uri: '',
        view_uri: '',
        authorSSOName: ''
    };
    it('getRecommendationTitle should return allTitle if publishedTitle is null', () => {
        const docLocal = {...doc, publishedTitle: null, allTitle: 'This is allTitle'};
        const title = CaseUtils.getRecommendationTitle(docLocal);
        expect(title).toEqual('This is allTitle');
    });
    it('getRecommendationTitle should return allTitle if publishedTitle is undefined', () => {
        const docLocal = {...doc, publishedTitle: undefined, allTitle: 'This is allTitle'};
        const title = CaseUtils.getRecommendationTitle(docLocal);
        expect(title).toEqual('This is allTitle');
    });
    it('getRecommendationTitle should return allTitle if publishedTitle is empty string', () => {
        const docLocal = {...doc, publishedTitle: '', allTitle: 'This is allTitle'};
        const title = CaseUtils.getRecommendationTitle(docLocal);
        expect(title).toEqual('This is allTitle');
    });
    it('getRecommendationTitle should return publishedTitle if publishedTitle is not empty and allTitle is undefined', () => {
        const docLocal = {...doc, publishedTitle: 'This is Published Title', allTitle: undefined};
        const title = CaseUtils.getRecommendationTitle(docLocal);
        expect(title).toEqual('This is Published Title');
    });
    it('getRecommendationTitle should return publishedTitle if publishedTitle is not empty and allTitle is null', () => {
        const docLocal = {...doc, publishedTitle: 'This is Published Title', allTitle: null};
        const title = CaseUtils.getRecommendationTitle(docLocal);
        expect(title).toEqual('This is Published Title');
    });
    it('getRecommendationTitle should return publishedTitle if publishedTitle is not empty and allTitle is not empty', () => {
        const docLocal = {...doc, publishedTitle: 'This is Published Title', allTitle: 'This is allTitle'};
        const title = CaseUtils.getRecommendationTitle(docLocal);
        expect(title).toEqual('This is Published Title');
    });
});

describe('CaseUtils getUrlParsedParams', () => {
    it('getUrlParsedParams should return empty object is there is no query param in the passed searchUrl', () => {
        const parsedParam = CaseUtils.getUrlParsedParams('');
        expect(parsedParam).toEqual({});
    });
    it('getUrlParsedParams should ignoreQueryPrefix and return single param if its present', () => {
        const parsedParam = CaseUtils.getUrlParsedParams(`?name=Vikas`);
        expect(parsedParam).toEqual({name: 'Vikas'});
    });
    it('getUrlParsedParams should ignoreQueryPrefix and return multiple params if its present', () => {
        const parsedParam = CaseUtils.getUrlParsedParams(`?name=Vikas&age=29`);
        expect(parsedParam).toEqual({name: 'Vikas', age: '29'});
    });
    it('getUrlParsedParams should ignoreQueryPrefix and return multiple params with whitespaces if its present', () => {
        const parsedParam = CaseUtils.getUrlParsedParams(`?name=Vikas Rathee&age=29`);
        expect(parsedParam).toEqual({name: 'Vikas Rathee', age: '29'});
    });
    it('getUrlParsedParams should return single param if its present', () => {
        const parsedParam = CaseUtils.getUrlParsedParams(`name=Vikas`);
        expect(parsedParam).toEqual({name: 'Vikas'});
    });
    it('getUrlParsedParams should return multiple params if its present', () => {
        const parsedParam = CaseUtils.getUrlParsedParams(`name=Vikas&age=29`);
        expect(parsedParam).toEqual({name: 'Vikas', age: '29'});
    });
    it('getUrlParsedParams should return multiple params with whitespaces if its present', () => {
        const parsedParam = CaseUtils.getUrlParsedParams(`name=Vikas Rathee&age=29`);
        expect(parsedParam).toEqual({name: 'Vikas Rathee', age: '29'});
    });
});
describe('CaseUtils getStringifiedParams', () => {
    it('getStringifiedParams should return empty object is there is no query param in the passed searchUrl', () => {
        const parsedParam = CaseUtils.getStringifiedParams({});
        expect(parsedParam).toEqual('');
    });
    it('getStringifiedParams should return single param if its present', () => {
        const parsedParam = CaseUtils.getStringifiedParams({name: 'Vikas'});
        expect(parsedParam).toEqual(`name=Vikas`);
    });
    it('getStringifiedParams should return multiple params if its present', () => {
        const parsedParam = CaseUtils.getStringifiedParams({name: 'Vikas', age: '29'});
        expect(parsedParam).toEqual(`name=Vikas&age=29`);
    });
    it('getStringifiedParams should return multiple params with whitespaces if its present', () => {
        const parsedParam = CaseUtils.getStringifiedParams({name: 'Vikas Rathee', age: '29'});
        expect(parsedParam).toEqual(`name=Vikas Rathee&age=29`);
    });
});

describe('CaseUtils canManageCase', () => {
    it('canManageCase should return false if roles is an empty array', () => {
        const loggedInUserJwtToken = {realm_access: {roles: []}};
        const canManageCase = CaseUtils.canManageCase(loggedInUserJwtToken);
        expect(canManageCase).toEqual(false);
    });
    it('canManageCase should return false if roles is null', () => {
        const loggedInUserJwtToken = {realm_access: {roles: null}};
        const canManageCase = CaseUtils.canManageCase(loggedInUserJwtToken);
        expect(canManageCase).toEqual(false);
    });
    it('canManageCase should return false if roles is undefined', () => {
        const loggedInUserJwtToken = {realm_access: {roles: null}};
        const canManageCase = CaseUtils.canManageCase(loggedInUserJwtToken);
        expect(canManageCase).toEqual(false);
    });
    it('canManageCase should return false if token is undefined', () => {
        const loggedInUserJwtToken = undefined;
        const canManageCase = CaseUtils.canManageCase(loggedInUserJwtToken);
        expect(canManageCase).toEqual(false);
    });
    it('canManageCase should return false if realm_access is undefined', () => {
        const loggedInUserJwtToken = {realm_access: undefined};
        const canManageCase = CaseUtils.canManageCase(loggedInUserJwtToken);
        expect(canManageCase).toEqual(false);
    });
    it('canManageCase should return true if roles containes portal_manage_cases as only item', () => {
        const loggedInUserJwtToken = {realm_access: {roles: ['portal_manage_cases']}};
        const canManageCase = CaseUtils.canManageCase(loggedInUserJwtToken);
        expect(canManageCase).toEqual(true);
    });
    it('canManageCase should return true if roles containes portal_manage_cases as last item', () => {
        const loggedInUserJwtToken = {realm_access: {roles: ['test role', 'portal_manage_cases']}};
        const canManageCase = CaseUtils.canManageCase(loggedInUserJwtToken);
        expect(canManageCase).toEqual(true);
    });
    it('canManageCase should return true if roles containes portal_manage_cases as middle item', () => {
        const loggedInUserJwtToken = {realm_access: {roles: ['test role', 'test role 2', 'portal_manage_cases', 'test more']}};
        const canManageCase = CaseUtils.canManageCase(loggedInUserJwtToken);
        expect(canManageCase).toEqual(true);
    });
});

describe('CaseUtils scrollIntoSection', () => {
    jest.useFakeTimers();
    it('scrollIntoSection should not throw error if sectionRef is null', () => {
        const sectionRef = null;
        CaseUtils.scrollIntoSection(sectionRef);
        expect(setTimeout).toHaveBeenCalledTimes(1);
        jest.runOnlyPendingTimers();
    });
    it('scrollIntoSection should not throw error if sectionRef.current is null', () => {
        const sectionRef = {current: null};
        CaseUtils.scrollIntoSection(sectionRef);
        expect(setTimeout).toHaveBeenCalledTimes(1);
        jest.runOnlyPendingTimers();
    });
    it('scrollIntoSection should call the scrollIntoView function exactly once', () => {
        const sectionRef = {current: {scrollIntoView: jest.fn()}};
        CaseUtils.scrollIntoSection(sectionRef as unknown as React.MutableRefObject<HTMLDivElement>);
        expect(setTimeout).toHaveBeenCalledTimes(1);
        jest.runOnlyPendingTimers();
        expect(sectionRef.current.scrollIntoView.mock.calls.length).toBe(1);
    });
});

describe('CaseUtils humanizeSize', () => {
    it('humanizeSize should return NaN kB when passed undefined', () => {
        const size = CaseUtils.humanizeSize(undefined);
        expect(size).toEqual('NaN kB');
    });
    it('humanizeSize should return 0.1 kB when passed 0', () => {
        const size = CaseUtils.humanizeSize(0);
        expect(size).toEqual('0.1 kB');
    });
    it('humanizeSize should return 1.0 kB when passed 1024', () => {
        const size = CaseUtils.humanizeSize(1024);
        expect(size).toEqual('1.0 kB');
    });
    it('humanizeSize should return 1.0 kB even when passed 1024 + 1', () => {
        const size = CaseUtils.humanizeSize(1024 + 1);
        expect(size).toEqual('1.0 kB');
    });
    it('humanizeSize should return 1.0 kB even when passed 1024 + 51', () => {
        const size = CaseUtils.humanizeSize(1024 + 51);
        expect(size).toEqual('1.0 kB');
    });
    it('humanizeSize should return 1.1 kB when passed 1024 + 52', () => {
        const size = CaseUtils.humanizeSize(1024 + 52);
        expect(size).toEqual('1.1 kB');
    });
    it('humanizeSize should return 1023.9 kB when passed Math.pow(1024, 2) - 52', () => {
        const size = CaseUtils.humanizeSize(Math.pow(1024, 2) - 52);
        expect(size).toEqual('1023.9 kB');
    });
    it('humanizeSize should return 1024.0 kB when passed Math.pow(1024, 2) - 1', () => {
        const size = CaseUtils.humanizeSize(Math.pow(1024, 2) - 1);
        expect(size).toEqual('1024.0 kB');
    });
    it('humanizeSize should return 1.0 MB when passed Math.pow(1024, 2)', () => {
        const size = CaseUtils.humanizeSize(Math.pow(1024, 2));
        expect(size).toEqual('1.0 MB');
    });
    it('humanizeSize should return 1.0 GB when passed Math.pow(1024, 3)', () => {
        const size = CaseUtils.humanizeSize(Math.pow(1024, 3));
        expect(size).toEqual('1.0 GB');
    });
    it('humanizeSize should return 1.0 TB when passed Math.pow(1024, 4)', () => {
        const size = CaseUtils.humanizeSize(Math.pow(1024, 4));
        expect(size).toEqual('1.0 TB');
    });
    it('humanizeSize should return 1.0 PB when passed Math.pow(1024, 5)', () => {
        const size = CaseUtils.humanizeSize(Math.pow(1024, 5));
        expect(size).toEqual('1.0 PB');
    });
    it('humanizeSize should return 1.0 EB when passed Math.pow(1024, 6)', () => {
        const size = CaseUtils.humanizeSize(Math.pow(1024, 6));
        expect(size).toEqual('1.0 EB');
    });
    it('humanizeSize should return 1.0 ZB when passed Math.pow(1024, 7)', () => {
        const size = CaseUtils.humanizeSize(Math.pow(1024, 7));
        expect(size).toEqual('1.0 ZB');
    });
    it('humanizeSize should return 1.0 YB when passed Math.pow(1024, 8)', () => {
        const size = CaseUtils.humanizeSize(Math.pow(1024, 8));
        expect(size).toEqual('1.0 YB');
    });
});

describe('CaseUtils markdownToHTML', () => {
    it('markdownToHTML return empty string for empty input', () => {
        expect(CaseUtils.markdownToHTML('')).toBe('');
    });
    it('markdownToHTML return empty string for null input', () => {
        expect(CaseUtils.markdownToHTML(null)).toBe('');
    });
    it('markdownToHTML return empty string for undefined input', () => {
        expect(CaseUtils.markdownToHTML(undefined)).toBe('');
    });
    it('markdownToHTML return <p> tag for simple string input', () => {
        expect(CaseUtils.markdownToHTML('Hello World')).toBe('<p>Hello World</p>\n');
    });
});

describe('CaseUtils showFts', () => {
    it('showFts should return false when both are empty', () => {
        expect(CaseUtils.showFts('', '')).toBe(false);
    });
    it('showFts should return false when both are null', () => {
        expect(CaseUtils.showFts(null, null)).toBe(false);
    });
    it('showFts should return false when both are undefined', () => {
        expect(CaseUtils.showFts(undefined, undefined)).toBe(false);
    });
    it('showFts should return false for non premium sev 1', () => {
        expect(CaseUtils.showFts('Test', '1')).toBe(false);
    });
    it('showFts should return true for PREMIUM sev 1', () => {
        expect(CaseUtils.showFts('PREMIUM', '1')).toBe(true);
    });
    it('showFts should return true for AMC sev 1', () => {
        expect(CaseUtils.showFts('AMC', '1')).toBe(true);
    });
    it('showFts should return true for PREMIUMPLUS sev 1', () => {
        expect(CaseUtils.showFts('PREMIUMPLUS', '1')).toBe(true);
    });
    it('showFts should return true for PREMIUM PLUS sev 1', () => {
        expect(CaseUtils.showFts('PREMIUM PLUS', '1')).toBe(true);
    });
});

describe('CaseUtils isPremiumEntitlement', () => {
    it('isPremiumEntitlement should return false for undefined', () => {
        expect(CaseUtils.isPremiumEntitlement(undefined)).toBe(false);
    });
    it('isPremiumEntitlement should return false for null', () => {
        expect(CaseUtils.isPremiumEntitlement(null)).toBe(false);
    });
    it('isPremiumEntitlement should return false for empty string', () => {
        expect(CaseUtils.isPremiumEntitlement('')).toBe(false);
    });
    it('isPremiumEntitlement should return true for PREMIUM', () => {
        expect(CaseUtils.isPremiumEntitlement('PREMIUM')).toBe(true);
    });
    it('isPremiumEntitlement should return true for AMC', () => {
        expect(CaseUtils.isPremiumEntitlement('AMC')).toBe(true);
    });
    it('isPremiumEntitlement should return true for PREMIUMPLUS', () => {
        expect(CaseUtils.isPremiumEntitlement('PREMIUMPLUS')).toBe(true);
    });
    it('isPremiumEntitlement should return true for PREMIUM PLUS', () => {
        expect(CaseUtils.isPremiumEntitlement('PREMIUM PLUS')).toBe(true);
    });
    it('isPremiumEntitlement should return false for PREMIUM in non caps', () => {
        expect(CaseUtils.isPremiumEntitlement('premium')).toBe(false);
    });
    it('isPremiumEntitlement should return false for AMC in non caps', () => {
        expect(CaseUtils.isPremiumEntitlement('amc')).toBe(false);
    });
    it('isPremiumEntitlement should return false for PREMIUMPLUS in non caps', () => {
        expect(CaseUtils.isPremiumEntitlement('premiumplus')).toBe(false);
    });
    it('isPremiumEntitlement should return false for PREMIUM PLUS in non caps', () => {
        expect(CaseUtils.isPremiumEntitlement('premium plus')).toBe(false);
    });
    it('isPremiumEntitlement should return false for any test string', () => {
        expect(CaseUtils.isPremiumEntitlement('test')).toBe(false);
    });
});

describe('CaseUtils isSev1', () => {
    it('isSev1 should return false when severity is null', () => {
        expect(CaseUtils.isSev1(null)).toBe(false);
    });
    it('isSev1 should return false when severity is undefined', () => {
        expect(CaseUtils.isSev1(undefined)).toBe(false);
    });
    it('isSev1 should return false when severity is empty', () => {
        expect(CaseUtils.isSev1('')).toBe(false);
    });
    it('isSev1 should return false when severity is 2 sev', () => {
        expect(CaseUtils.isSev1('2 sev')).toBe(false);
    });
    it('isSev1 should return false when severity is sev 1', () => {
        expect(CaseUtils.isSev1('sev 1')).toBe(false);
    });
    it('isSev1 should return true when severity is 1sev', () => {
        expect(CaseUtils.isSev1('1sev')).toBe(true);
    });
    it('isSev1 should return true when severity is 1', () => {
        expect(CaseUtils.isSev1('1')).toBe(true);
    });
});
