import {
    OpeningTimes,
    OpeningTimesCollection,
    Time,
    TimeRange,
    WeekdayBounds,
    WEEKDAYS,
} from '@nimius/toubiz-opening-times-calculation';
import { expect } from 'chai';
import sinon from 'sinon';
import { mount } from 'vue-test-utils';
import OpeningTimesTable from './opening-times-table.vue';

describe('opening-times-table', () => {

    const times = {
        monday1am: (new Date(2020, 1, 3, 1, 0, 0)),
        monday1pm: (new Date(2020, 1, 3, 13, 0, 0)),
        monday11pm: (new Date(2020, 1, 3, 23, 0, 0)),
        tuesday1am: (new Date(2020, 1, 4, 1, 0, 0)),
        tuesday1pm: (new Date(2020, 1, 4, 13, 0, 0)),
    };

    let openingTimes = null;
    let clock = null;

    function mockTime (time) {
        clock = sinon.useFakeTimers(time);
    }

    afterEach(() => {
        openingTimes = null;
        if (clock) {
            clock.restore();
            clock = null;
        }
    });
    beforeEach(() => {
        openingTimes = new OpeningTimesCollection([
            // Monday: 12:00 - 16:00, 22:00 - 02:00
            // Tuesday: 14:00 - 18:00

            new OpeningTimes({
                bounds: [new WeekdayBounds([WEEKDAYS.MONDAY])],
                timeRanges: [
                    new TimeRange(Time.parse('12:00'), Time.parse('16:00'), 'monday regular'),
                    new TimeRange(Time.parse('22:00'), Time.parse('24:00')),
                ],
            }),
            new OpeningTimes({
                bounds: [new WeekdayBounds([WEEKDAYS.TUESDAY])],
                timeRanges: [
                    new TimeRange(Time.parse('00:00'), Time.parse('02:00')),
                    new TimeRange(Time.parse('14:00'), Time.parse('18:00'), 'tuesday regular'),
                ],
            }),
            new OpeningTimes({
                bounds: [ new WeekdayBounds([ WEEKDAYS.WEDNESDAY ]) ],
                isClosed: true,
                comment: 'Closed on wednesday',
            }),
        ]);
    });

    it('should display 7 days of opening times by default', () => {
        mockTime(times.monday1pm);
        const wrapper = mount(OpeningTimesTable, {
            propsData: {
                openingTimes,
                forDateAndTime: times.monday1pm,
            },
        });

        expect(wrapper.html()).to.include('2020-02-03');
        expect(wrapper.html()).to.include('2020-02-04');
        expect(wrapper.html()).to.include('2020-02-05');
        expect(wrapper.html()).to.include('2020-02-06');
        expect(wrapper.html()).to.include('2020-02-07');
        expect(wrapper.html()).to.include('2020-02-08');
        expect(wrapper.html()).to.include('2020-02-09');

        expect(wrapper.html()).to.not.include('2020-02-02');
        expect(wrapper.html()).to.not.include('2020-02-10');
    });

    it('should merge day-spilling opening times', () => {
        mockTime(times.monday1pm);
        const wrapper = mount(OpeningTimesTable, {
            propsData: {
                openingTimes,
                forDateAndTime: times.monday1pm,
            },
        });

        expect(wrapper.html()).to.include('22:00 - 02:00');
        expect(wrapper.html()).to.not.include('00:00');
        expect(wrapper.html()).to.not.include('24:00');
    });

    it('should not display opening times spilled over from yesterday in first day', () => {
        mockTime(times.tuesday1pm);
        const wrapper = mount(OpeningTimesTable, {
            propsData: {
                openingTimes,
                forDateAndTime: times.tuesday1pm,
                length: 3,
            },
        });

        expect(wrapper.html()).to.not.include('00:00');
        expect(wrapper.html()).to.not.include('02:00');
    });

    it('should display spilling-over opening times in last day', () => {
        // 3 rows displayed beginning 2 days before a time should spill over
        // => spill over is last row.
        const time = new Date(times.monday1pm.getTime());
        time.setDate(time.getDate() - 2);
        mockTime(time);
        const wrapper = mount(OpeningTimesTable, {
            propsData: {
                openingTimes,
                forDateAndTime: time,
                length: 3,
            },
        });

        expect(wrapper.html()).to.include('22:00 - 02:00');
        expect(wrapper.html()).to.not.include('00:00');
        expect(wrapper.html()).to.not.include('24:00');
    });

    it('should display 8 days if a spilled-over opening time is currently active', () => {
        // On tuesday 1am a spilled over opening time from the last day is still in effect.
        mockTime(times.tuesday1am);
        const wrapper = mount(OpeningTimesTable, {
            propsData: {
                openingTimes,
                forDateAndTime: times.tuesday1am,
            },
        });

        expect(wrapper.html()).to.include('2020-02-03');
        expect(wrapper.html()).to.include('2020-02-04');
        expect(wrapper.html()).to.include('2020-02-05');
        expect(wrapper.html()).to.include('2020-02-06');
        expect(wrapper.html()).to.include('2020-02-07');
        expect(wrapper.html()).to.include('2020-02-08');
        expect(wrapper.html()).to.include('2020-02-09');
        expect(wrapper.html()).to.include('2020-02-10');

        expect(wrapper.html()).to.not.include('2020-02-02');
    });

    it('should not display 8 days if checked day has spilling-over opening times but is not current day', () => {
        mockTime(times.monday1pm);
        const wrapper = mount(OpeningTimesTable, {
            propsData: {
                openingTimes,
                forDateAndTime: times.tuesday1am,
            },
        });

        expect(wrapper.html()).to.include('2020-02-04');
        expect(wrapper.html()).to.include('2020-02-05');
        expect(wrapper.html()).to.include('2020-02-06');
        expect(wrapper.html()).to.include('2020-02-07');
        expect(wrapper.html()).to.include('2020-02-08');
        expect(wrapper.html()).to.include('2020-02-09');
        expect(wrapper.html()).to.include('2020-02-10');

        expect(wrapper.html()).to.not.include('2020-02-03');
        expect(wrapper.html()).to.not.include('2020-02-11');
    });

    it ('should render time range comments', () => {
        mockTime(times.monday1pm);
        const wrapper = mount(OpeningTimesTable, {
            propsData: { openingTimes },
        });

        expect(wrapper.html()).to.contain('monday regular');
        expect(wrapper.html()).to.contain('tuesday regular');
    });

    it ('should render closed day comments', () => {
        mockTime(times.monday1pm);
        const wrapper = mount(OpeningTimesTable, {
            propsData: { openingTimes },
        });

        expect(wrapper.html()).to.contain('Closed on wednesday');
    });

});
