const models = require('vn-loopback/server/server').models;
const axios = require('axios');
const fs = require('fs');

const filter = {notificationFk: 'mrw-deadline'};
const mockBase64Binary = 'base64BinaryString';
const ticket1 = {
    'id': '44',
    'clientFk': 1101,
    'shipped': Date.vnNew(),
    'nickname': 'MRW',
    'addressFk': 1,
    'agencyModeFk': 999
};
let expedition;
const expedition1 = {
    'agencyModeFk': 999,
    'ticketFk': 44,
    'freightItemFk': 71,
    'created': '2001-01-01',
    'counter': 1,
    'workerFk': 18,
    'packagingFk': '94',
    'hostFk': '',
    'stateTypeFk': 3,
    'hasNewRoute': 0,
    'isBox': 71,
    'editorFk': 100
};

describe('MRWConfig createShipment()', () => {
    beforeAll(async() => {
        await models.Agency.create(
            {'id': 999, 'name': 'mrw'}
        );

        await models.AgencyMode.create(
            {'id': 999, 'name': 'mrw', 'agencyFk': 999, 'code': 'mrw'}

        );

        await models.MrwService.create(
            {'agencyModeCodeFk': 'mrw', 'clientType': '000001', 'serviceType': 105, 'kg': 10}
        );

        await createMrwConfig();

        await models.Ticket.create(ticket1);
        expedition = await models.Expedition.create(expedition1);
    });

    afterAll(async() => {
        await cleanFixtures();
        await models.Ticket.destroyAll(ticket1);
        await models.Expedition.destroyAll(ticket1);
    });

    beforeEach(async() => {
        const mockPostResponses = [
            {data: fs.readFileSync(__dirname + '/mockGetLabel.xml', 'utf-8')},
            {data: fs.readFileSync(__dirname + '/mockCreateShipment.xml', 'utf-8')}
        ];

        spyOn(axios, 'post').and.callFake(() => Promise.resolve(mockPostResponses.pop()));
        await cleanFixtures();
    });

    async function cleanFixtures() {
        await models.NotificationQueue.destroyAll(filter);
        await models.MrwConfig.updateAll({id: 1}, {expeditionDeadLine: null, notified: null});
    }

    async function createMrwConfig() {
        await models.MrwConfig.create(
            {
                'id': 1,
                'url': 'https://url.com',
                'user': 'user',
                'password': 'password',
                'franchiseCode': 'franchiseCode',
                'subscriberCode': 'subscriberCode',
                'clientTypeWidth': 6
            }
        );
    }

    async function getLastNotification() {
        return models.NotificationQueue.findOne({
            order: 'id DESC',
            where: filter
        });
    }

    it('should create a shipment and return a base64Binary label', async() => {
        const {file} = await models.MrwConfig.createShipment(expedition.id);

        expect(file).toEqual(mockBase64Binary);
    });

    it('should fail if mrwConfig has no data', async() => {
        let error;
        await models.MrwConfig.destroyAll();
        await models.MrwConfig.createShipment(expedition.id).catch(e => {
            error = e;
        }).finally(async() => {
            expect(error.message).toEqual(`MRW service is not configured`);
        });
        await createMrwConfig();

        expect(error).toBeDefined();
    });

    it('should fail if expeditionFk is not a MrwExpedition', async() => {
        let error;
        await models.MrwConfig.createShipment(15).catch(e => {
            error = e;
        }).finally(async() => {
            expect(error.message).toEqual(`ClientType not available`);
        });
    });

    it('should fail if the creation date of this ticket is before the current date', async() => {
        let error;
        const yesterday = Date.vnNew();
        yesterday.setDate(yesterday.getDate() - 1);

        await models.Ticket.updateAll({id: ticket1.id}, {shipped: yesterday});
        await models.MrwConfig.createShipment(expedition.id).catch(e => {
            error = e;
        }).finally(async() => {
            expect(error.message).toEqual(`This ticket has a shipped date earlier than today`);
        });
        await models.Ticket.updateAll({id: ticket1.id}, {shipped: Date.vnNew()});
    });

    it('should send mail if you are past the dead line and is not notified today', async() => {
        await models.MrwConfig.updateAll({id: 1}, {expeditionDeadLine: '10:00:00', notified: null});
        await models.MrwConfig.createShipment(expedition.id);
        const notification = await getLastNotification();

        expect(notification.notificationFk).toEqual(filter.notificationFk);
    });

    it('should send mail if you are past the dead line and it is notified from another day', async() => {
        await models.MrwConfig.updateAll({id: 1}, {expeditionDeadLine: '10:00:00', notified: new Date()});
        await models.MrwConfig.createShipment(expedition.id);
        const notification = await getLastNotification();

        expect(notification.notificationFk).toEqual(filter.notificationFk);
    });

    it('should not send mail if you are past the dead line and it is notified', async() => {
        await models.MrwConfig.updateAll({id: 1}, {expeditionDeadLine: '10:00:00', notified: Date.vnNew()});
        await models.MrwConfig.createShipment(expedition.id);
        const notification = await getLastNotification();

        expect(notification).toEqual(null);
    });
});