@testable import App
import Fluent
import XCTVapor

final class UserTests: XCTestCase {

    func test1() async throws{
        let app = Application(.testing)
        defer{app.shutdown()}
        try await configure(app)
        let basepath = "/api/v2.0/users/"
        let fn = "Mike"
        let ln = "Carman"
        let email = "mcarman@rpmindustries.com"
        let username = "bryckman"
        let password = "password"
        let isactive = true
        let cuserid = -1
        let uuserid = -1
        //new
        try app.test(.POST, basepath, beforeRequest: {
            req in
            let input = mdlUser(id: nil, number: nil, firstname: fn, lastname: ln, username: username, password: password, email: email, isactive: isactive, createuserid: cuserid, updateuserid: uuserid, divisionid: nil, locationid: nil, gateid: nil)
            try req.content.encode(input)
        }, afterResponse: {
            res in
            XCTAssertEqual(res.status, .created)
            let obj = try res.content.decode(mdlUser.self)
            XCTAssertEqual(obj.firstname, fn)
            let id = obj.id
            
            //Update object just created
            try app.test(.POST, basepath, beforeRequest:{
                req in
                let input = mdlUser(id: id, number: "1", firstname: fn, lastname: ln, username: username, password: password, email: email, isactive: isactive, createuserid: cuserid, updateuserid: uuserid, divisionid: nil, locationid: nil, gateid: nil)
                try req.content.encode(input)
            }, afterResponse: {
                res in
                XCTAssertEqual(res.status, .accepted)
                let obj = try res.content.decode(mdlUser.self)
                XCTAssertEqual(obj.firstname, fn)
            })
            
            //All
            try app.test(.GET, basepath, afterResponse: { res in
                XCTAssertEqual(res.status, .ok)
                XCTAssertEqual(res.headers.contentType, .json)
                _ = try res.content.decode([mdlUser].self)
            })
            
            //read
            var parameter = try CustomCrypto.EncryptString(input: String(id!))
            
            var path = "\(basepath)\(parameter)"
            try app.test(.GET, path, afterResponse: { res in
                XCTAssertEqual(res.status, .ok)
                XCTAssertEqual(res.headers.contentType, .json)
                _ = try res.content.decode(mdlUser.self)
            })
            
            //login
            let gooduser = "bryckman"
            let goodpwd = "password"
            
            
            let baduser = "brycman_"
            let badpwd = "p@$$w0rd"
            
            var combo = "\(gooduser):\(goodpwd)"
            parameter = try CustomCrypto.EncryptString(input: combo)
            path = "\(basepath)login/\(parameter)"
            try app.test(.GET, path, afterResponse: {
                res in
                XCTAssertEqual(res.status, .ok)
                XCTAssertEqual(res.headers.contentType, .json)
                _ = try res.content.decode(mdlUser.self)
            })
            combo = "\(gooduser):\(badpwd)"
            parameter = try CustomCrypto.EncryptString(input: combo)
            path = "\(basepath)login/\(parameter)"
            try app.test(.GET, path, afterResponse: {
                res in
                XCTAssertEqual(res.status, .unauthorized)
                XCTAssertEqual(res.headers.contentType, .json)
            })
            combo = "\(baduser):\(badpwd)"
            parameter = try CustomCrypto.EncryptString(input: combo)
            path = "\(basepath)login/\(parameter)"
            try app.test(.GET, path, afterResponse: {
                res in
                XCTAssertEqual(res.status, .unauthorized)
                XCTAssertEqual(res.headers.contentType, .json)
            })
            combo = "\(baduser):\(goodpwd)"
            parameter = try CustomCrypto.EncryptString(input: combo)
            path = "\(basepath)login/\(parameter)"
            try app.test(.GET, path, afterResponse: {
                res in
                XCTAssertEqual(res.status, .unauthorized)
                XCTAssertEqual(res.headers.contentType, .json)
            })
            
            //delete user
            let encryptedid = try CustomCrypto.EncryptString(input: String(id!))
            path = "api/v2.0/users/"
            let url = "\(path)\(encryptedid)"
            try app.test(.DELETE, url, afterResponse: {
                res in
                XCTAssertEqual(res.status, .ok)
                _ = try res.content.decode(mdlUser.self)
            })
        })
    }
    
}
