const app = require('vn-loopback/server/server');
const LoopBackContext = require('loopback-context');

describe('setPosition()', () => {
    const activeCtx = {
        accessToken: {userId: 9},
        http: {
            req: {
                headers: {origin: 'http://localhost'}
            }
        }
    };
    const ctx = {
        req: activeCtx
    };

    beforeEach(() => {
        spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
            active: activeCtx
        });
    });

    it('should increase the orders module position by replacing it with clients and vice versa', async() => {
        const tx = await app.models.StarredModule.beginTransaction({});

        const filter = {
            where: {
                workerFk: ctx.req.accessToken.userId,
                moduleFk: 'Orders'
            }
        };

        try {
            const options = {transaction: tx};
            await app.models.StarredModule.toggleStarredModule(ctx, 'Orders', options);
            await app.models.StarredModule.toggleStarredModule(ctx, 'Clients', options);

            let orders = await app.models.StarredModule.findOne(filter, options);

            filter.where.moduleFk = 'Clients';
            let clients = await app.models.StarredModule.findOne(filter, options);

            expect(orders.position).toEqual(1);
            expect(clients.position).toEqual(2);

            await app.models.StarredModule.setPosition(ctx, 'Clients', 'left', options);

            filter.where.moduleFk = 'Clients';
            clients = await app.models.StarredModule.findOne(filter, options);

            filter.where.moduleFk = 'Orders';
            orders = await app.models.StarredModule.findOne(filter, options);

            expect(clients.position).toEqual(1);
            expect(orders.position).toEqual(2);

            await tx.rollback();
        } catch (e) {
            await tx.rollback();
            throw e;
        }
    });

    it('should decrease the orders module position by replacing it with clients and vice versa', async() => {
        const tx = await app.models.StarredModule.beginTransaction({});

        const filter = {
            where: {
                workerFk: ctx.req.accessToken.userId,
                moduleFk: 'Orders'
            }
        };

        try {
            const options = {transaction: tx};
            await app.models.StarredModule.toggleStarredModule(ctx, 'Orders', options);
            await app.models.StarredModule.toggleStarredModule(ctx, 'Clients', options);

            let orders = await app.models.StarredModule.findOne(filter, options);

            filter.where.moduleFk = 'Clients';
            let clients = await app.models.StarredModule.findOne(filter, options);

            expect(orders.position).toEqual(1);
            expect(clients.position).toEqual(2);

            await app.models.StarredModule.setPosition(ctx, 'Orders', 'right', options);

            filter.where.moduleFk = 'Orders';
            orders = await app.models.StarredModule.findOne(filter, options);

            filter.where.moduleFk = 'Clients';
            clients = await app.models.StarredModule.findOne(filter, options);

            expect(orders.position).toEqual(2);
            expect(clients.position).toEqual(1);

            await tx.rollback();
        } catch (e) {
            await tx.rollback();
            throw e;
        }
    });

    it('should switch two modules after adding and deleting several modules', async() => {
        const tx = await app.models.StarredModule.beginTransaction({});

        const filter = {
            where: {
                workerFk: ctx.req.accessToken.userId,
                moduleFk: 'Items'
            }
        };

        try {
            const options = {transaction: tx};

            await app.models.StarredModule.toggleStarredModule(ctx, 'Clients', options);
            await app.models.StarredModule.toggleStarredModule(ctx, 'Orders', options);
            await app.models.StarredModule.toggleStarredModule(ctx, 'Clients', options);
            await app.models.StarredModule.toggleStarredModule(ctx, 'Orders', options);
            await app.models.StarredModule.toggleStarredModule(ctx, 'Items', options);
            await app.models.StarredModule.toggleStarredModule(ctx, 'Claims', options);
            await app.models.StarredModule.toggleStarredModule(ctx, 'Clients', options);
            await app.models.StarredModule.toggleStarredModule(ctx, 'Orders', options);
            await app.models.StarredModule.toggleStarredModule(ctx, 'Zones', options);

            const items = await app.models.StarredModule.findOne(filter, options);

            filter.where.moduleFk = 'Claims';
            const claims = await app.models.StarredModule.findOne(filter, options);

            filter.where.moduleFk = 'Clients';
            let clients = await app.models.StarredModule.findOne(filter, options);

            filter.where.moduleFk = 'Orders';
            let orders = await app.models.StarredModule.findOne(filter, options);

            filter.where.moduleFk = 'Zones';
            const zones = await app.models.StarredModule.findOne(filter, options);

            expect(items.position).toEqual(1);
            expect(claims.position).toEqual(2);
            expect(clients.position).toEqual(3);
            expect(orders.position).toEqual(4);
            expect(zones.position).toEqual(5);

            await app.models.StarredModule.setPosition(ctx, 'Clients', 'right', options);

            filter.where.moduleFk = 'Orders';
            orders = await app.models.StarredModule.findOne(filter, options);

            filter.where.moduleFk = 'Clients';
            clients = await app.models.StarredModule.findOne(filter, options);

            expect(orders.position).toEqual(3);
            expect(clients.position).toEqual(4);

            await tx.rollback();
        } catch (e) {
            await tx.rollback();
            throw e;
        }
    });

    it('should switch two modules after adding and deleting a module between them', async() => {
        const tx = await app.models.StarredModule.beginTransaction({});

        const filter = {
            where: {
                workerFk: ctx.req.accessToken.userId,
                moduleFk: 'Items'
            }
        };

        try {
            const options = {transaction: tx};

            await app.models.StarredModule.toggleStarredModule(ctx, 'Items', options);
            await app.models.StarredModule.toggleStarredModule(ctx, 'Clients', options);
            await app.models.StarredModule.toggleStarredModule(ctx, 'Claims', options);
            await app.models.StarredModule.toggleStarredModule(ctx, 'Orders', options);
            await app.models.StarredModule.toggleStarredModule(ctx, 'Zones', options);

            const items = await app.models.StarredModule.findOne(filter, options);

            filter.where.moduleFk = 'Clients';
            let clients = await app.models.StarredModule.findOne(filter, options);

            filter.where.moduleFk = 'Claims';
            const claims = await app.models.StarredModule.findOne(filter, options);

            filter.where.moduleFk = 'Orders';
            let orders = await app.models.StarredModule.findOne(filter, options);

            filter.where.moduleFk = 'Zones';
            const zones = await app.models.StarredModule.findOne(filter, options);

            expect(items.position).toEqual(1);
            expect(clients.position).toEqual(2);
            expect(claims.position).toEqual(3);
            expect(orders.position).toEqual(4);
            expect(zones.position).toEqual(5);

            await app.models.StarredModule.toggleStarredModule(ctx, 'Claims', options);
            await app.models.StarredModule.setPosition(ctx, 'Clients', 'right', options);

            filter.where.moduleFk = 'Clients';
            clients = await app.models.StarredModule.findOne(filter, options);

            filter.where.moduleFk = 'Orders';
            orders = await app.models.StarredModule.findOne(filter, options);

            expect(orders.position).toEqual(2);
            expect(clients.position).toEqual(4);

            await tx.rollback();
        } catch (e) {
            await tx.rollback();
            throw e;
        }
    });
});