const statusCodes = require("../utilities/statusCodes");
const { readFile } = require("fs-extra");
const { timeout } = require("./helpers");

module.exports = (app, appName, userName) => {

    const credentials = app.credentials[userName];

    it("should return unauthorized if username is incorrect", async () => {
        await app.post(`/${appName}/api/authenticate`, {
            username: "unknownuser",
            password: credentials.password
        })
        .expect(statusCodes.UNAUTHORIZED); 
    })

    it("should return unauthorized if password is incorrect", async () => {
        await app.post(`/${appName}/api/authenticate`, {
            username: credentials.username,
            password: "incorrect_password"
        })
        .expect(statusCodes.UNAUTHORIZED); 
    })

    it("should not get cookie when unauthorized", async () => {
        const response = await app.post(`/${appName}/api/authenticate`, {
            username: credentials.username,
            password: "incorrect_password"
        });
        
        expect(response.header['set-cookie']).toBeUndefined();

    });

    it("should return ok correct username and password supplied", async () => {

        const response = await app.post(`/${appName}/api/authenticate`, {
            username: credentials.username,
            password: credentials.password
        })
        .expect(statusCodes.OK);

        credentials.cookie = response.header['set-cookie'];
    });

    const testUserName = appName + "_test_user";
    let testPassword = "test_user_password";
    it("should be able to create new user with authenticated cookie", async () => {
                
        await app.post(`/${appName}/api/createUser`, {
            user: {
                name: testUserName, 
                accessLevels:["owner"], 
                enabled:true
            },
            password: testPassword
        })
        .set("cookie", credentials.cookie)
        .expect(statusCodes.OK);

        
    });

    let newUserCookie;
    it("should be able to authenticate with new user", async () => {

        const responseNewUser = await app.post(`/${appName}/api/authenticate`, {
            username: testUserName,
            password: testPassword
        })
        .expect(statusCodes.OK);
        
        newUserCookie = responseNewUser.header['set-cookie'];

        expect(newUserCookie).toBeDefined();
        expect(newUserCookie).not.toEqual(credentials.cookie);

        app.get("/_master/api/users/")
        .set("cookie", newUserCookie)
        .expect(statusCodes.OK);
    });

    it("should not be able to perform requests when user is disabled", async () => {

        //HERE
        await app.post(`/${appName}/api/disableUser`, {
            username: testUserName
        })
        .set("cookie", credentials.cookie)
        .expect(statusCodes.OK);

        await app.get(`/${appName}/api/users`)
            .set("cookie", newUserCookie)
            .expect(statusCodes.UNAUTHORIZED);

        await app.post(`/${appName}/api/authenticate`, {
            username: testUserName,
            password: testPassword
        })
        .expect(statusCodes.UNAUTHORIZED);

    });

    it("should not be able to re-authenticate when user is disabled", async () => {
        await app.post(`/${appName}/api/authenticate`, {
            username: testUserName,
            password: testPassword
        })
        .expect(statusCodes.UNAUTHORIZED);
    });

    it("should be able with re-authenticate when user is enabled again", async () => {

        await app.post(`/${appName}/api/enableUser`, {
            username: testUserName
        })
        .set("cookie", credentials.cookie)
        .expect(statusCodes.OK);

        await app.post(`/${appName}/api/authenticate`, {
            username: testUserName,
            password: testPassword
        })
        .expect(statusCodes.OK);
    });

    let testUserTempCode;
    it("should be able to reset password with temporary access", async () => {

        await app.post(`/${appName}/api/createTemporaryAccess`, {
            username: testUserName
        })
        .expect(statusCodes.OK);

        testPassword = "test_user_new_password";

        // the behaviour that creates the below file is async,
        /// to this timeout is giving it a change to work its magic        
        await timeout(10);

        const testUserTempCode = await readFile(`./tests/.data/tempaccess${testUserName}`, "utf8");
    
        await app.post(`/${appName}/api/setPasswordFromTemporaryCode`, {
            username: testUserName,
            tempCode:testUserTempCode,
            newPassword:testPassword
        })
        .expect(statusCodes.OK);

        await app.post(`/${appName}/api/authenticate`, {
            username: testUserName,
            password: testPassword
        })
        .expect(statusCodes.OK);

        

    });

    it("should not be able to set password with used temp code", async () => {
      
        await app.post(`/${appName}/api/setPasswordFromTemporaryCode`, {
            username: testUserName,
            tempCode:testUserTempCode,
            newPassword:"whatever"
        })
        .expect(statusCodes.OK);

        await app.post(`/${appName}/api/authenticate`, {
            username: testUserName,
            password: "whatever"
        })
        .expect(statusCodes.UNAUTHORIZED);

        await app.post(`/${appName}/api/authenticate`, {
            username: testUserName,
            password: testPassword
        })
        .expect(statusCodes.OK);

    });
};