import {
    getEndOfTheWeek,
    getSunday,
    getTomorrow,
    getUTC,
    getYesterday,
    isBetween,
    areSame,
    isSameOrBefore,
    isToday,
    theDayAfter,
    theDayBefore,
    getStartOfTheWeek,
    getStartOfTheCurrentWeek,
    isTomorrow,
} from '@utils/date';

describe('date utils', () => {
    beforeEach(() => {
        jasmine.clock().install();
        jasmine.clock().mockDate(new Date(2022, 4, 28));
    });

    afterEach(() => {
        jasmine.clock().uninstall();
    });

    it('getUTC should return utc', () => {
        expect(getUTC('2022-05-27T14:00:00')).toBe('+00:00');
        expect(getUTC('2022-05-27T14:00:00Z')).toBe('+00:00');
        expect(getUTC('2022-05-27T17:00:00+03:00')).toBe('+03:00');
        expect(getUTC('2022-05-27T17:00:00-03:30')).toBe('-03:30');
    });

    it('theDayBefore should return correct date', () => {
        const input = new Date(2022, 4, 28);
        const expected = new Date(2022, 4, 27);

        expect(theDayBefore(input)).toEqual(expected);
    });

    it('theDayAfter should return correct date', () => {
        const input = new Date(2022, 4, 28);
        const expected = new Date(2022, 4, 29);

        expect(theDayAfter(input)).toEqual(expected);
    });

    it('getYesterday should return correct date', () => {
        const expected = new Date(2022, 4, 27);

        expect(getYesterday()).toEqual(expected);
    });

    it('getTomorrow should return correct date', () => {
        const expected = new Date(2022, 4, 29);

        expect(getTomorrow()).toEqual(expected);
    });

    it('isToday should return true if provided date is today', () => {
        expect(isToday(new Date(2022, 4, 29))).toBe(false);
        expect(isToday(new Date(2022, 4, 28))).toBe(true);
    });

    it('isTomorrow should return true if provided date is tomorrow', () => {
        expect(isTomorrow(new Date(2022, 4, 29))).toBe(true);
        expect(isTomorrow(new Date(2022, 4, 28))).toBe(false);
    });

    it('isBetween should return true if provided date is in range', () => {
        const firstDate = new Date(2022, 4, 1);
        const secondDate = new Date(2022, 4, 10);
        let thirdDate = new Date(2022, 4, 20);

        expect(isBetween(firstDate, secondDate, thirdDate)).toBe(false);
        expect(isBetween(secondDate, firstDate, thirdDate)).toBe(true);
        expect(isBetween(secondDate, thirdDate, firstDate)).toBe(false);

        thirdDate = secondDate;

        expect(isBetween(secondDate, firstDate, thirdDate)).toBe(true);
    });

    it('isSame should return true if provided dates are equal', () => {
        const firstDate = new Date(2022, 4, 1);
        let secondDate = new Date(2022, 4, 10);

        expect(areSame(firstDate, secondDate)).toBe(false);

        secondDate = firstDate;

        expect(areSame(firstDate, secondDate)).toBe(true);
    });

    it('isSameOrBefore should return true if provided dates are equal or the first date is less than the second', () => {
        const firstDate = new Date(2022, 4, 1);
        let secondDate = new Date(2022, 4, 10);

        expect(isSameOrBefore(firstDate, secondDate)).toBe(true);
        secondDate = firstDate;
        expect(areSame(firstDate, secondDate)).toBe(true);
        secondDate = new Date(2022, 3, 20);
        expect(areSame(firstDate, secondDate)).toBe(false);
    });

    it('getSunday should return sunday of the week of provided monday', () => {
        const monday = new Date(2022, 4, 23);
        const sunday = new Date(2022, 4, 29);

        expect(getSunday(monday)).toEqual(sunday);
    });

    it('getEndOfTheWeek should return sunday of the week of provided date', () => {
        let date = new Date(2022, 4, 28);
        const sunday = new Date(2022, 4, 29);

        let result = getEndOfTheWeek(date);
        expect(areSame(result, sunday)).toBe(true);
        date = sunday;

        result = getEndOfTheWeek(date);
        expect(areSame(result, sunday)).toBe(true);
    });

    it('getStartOfTheWeek should return monday of the week of provided date', () => {
        let date = new Date(2022, 4, 28);
        const monday = new Date(2022, 4, 23);

        let result = getStartOfTheWeek(date);
        expect(areSame(result, monday)).toBe(true);
        date = monday;

        result = getStartOfTheWeek(date);
        expect(areSame(result, monday)).toBe(true);
    });

    it('getStartOfTheCurrentWeek should return monday of the current week', () => {
        const monday = new Date(2022, 4, 23);

        const result = getStartOfTheCurrentWeek();
        expect(areSame(result, monday)).toBe(true);
    });
});
