function API.CreateUser(playerId, mappedIdentifiers)
    local playerName = GetPlayerName(playerId)

    local userId = MySQL.insert.await(
        [[
            INSERT INTO user (name) VALUES(?)
        ]],
        {
            playerName
        })

    if userId then
        MySQL.insert.await(
        [[
            INSERT INTO user_credentials (userId, fivem, steam, ip, license, license2, xbl, live, discord) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)
        ]],
        {            
            userId,
            mappedIdentifiers.fivem,
            mappedIdentifiers.steam,
            mappedIdentifiers.ip,
            mappedIdentifiers.license,
            mappedIdentifiers.license2,
            mappedIdentifiers.xbl,
            mappedIdentifiers.live,
            mappedIdentifiers.discord,
        })
    end

    local status, err = pcall(function()
        return exports.prime_api:createUser( playerId )
    end)

	lib.logger(playerId, 'User', ("Usuário CRIADO - %s (%s) - Discord:%s - Steam:%s"):format(playerName, userId, mappedIdentifiers.discord, mappedIdentifiers.steam))
    return userId
end

function API.GetUserIdentifiersByIdentifier(identifier, identifierKey)
    local res = MySQL.single.await([[
        SELECT * 
        FROM user_credentials 
        WHERE ?? = ?
    ]], {
        identifierKey,
        identifier
    })
    
    if res then 
        return res
    end
end

function API.GetUserIdByIdentifier(identifier, identifierKey)
    local res = MySQL.single.await([[
        SELECT * 
        FROM user_credentials 
        WHERE ?? = ?
    ]], {
        identifierKey,
        identifier
    })
    
    if res then 
        return res.userId
    end
end

function API.GetUserIdByIdentifiers(identifiers, name)
    local mappedIdentifiers =  MapIdentifiers( identifiers )
    local identiferKey = Config.PrimaryIdentifier

    local res = MySQL.single.await([[
        SELECT * 
        FROM user_credentials 
        WHERE ?? = ?
    ]], {
        identiferKey,
        mappedIdentifiers[identiferKey]
    })
    
    if res then 
        return res.userId
    end
end

function API.GetCharacterFromCitizenIdOffline( citizenId )
    return MySQL.single.await("SELECT * from `character` WHERE citizenId = ? LIMIT 1", { citizenId })
end

function API.GetCharacterFromCharId( charId )
    return MySQL.single.await("SELECT * from `character` WHERE `id` = ? LIMIT 1", { charId })
end

function API.GetUserFromUserIdOffline( userId )
    return MySQL.single.await("SELECT * from `user` WHERE id = ? LIMIT 1", { userId })
end

function API.GetUserCharactersOffline( userId )
    return API_Database.query("FRP/GetCharacters", {userId = userId})
end

function API.GetUserFromUserId(userId)
    return API.users[userId]
end

function API.GetUserIdFromServerId( source ) 
    local user = API.GetUserFromSource(source)
    if not user then return nil end
    return user:GetId()
end 

function API.GetUserFromSource(source)
    return API.users[API.sources[tostring(source)]]
end

function API.GetUserFromCharId(charId)
    return API.users[API.chars[tonumber(charId)]]
end

function API.GetUserFromCitizenId( citizenId )
    return API.users[API.citizen[ citizenId ]]
end

function API.GetUserFromDiscordId( discordId )
    return API.users[API.discord[ discordId ]]
end

function API.GetUserIdFromCharId(charId)
    if API.chars[charId] then
        return API.chars[charId]
    else
        local rows = API_Database.query("FRP/GetUserIdByCharId", {charId = charId})
        if #rows > 0 then
            return rows[1].userId
        end
    end
    return nil
end

function API.GetUsers()
    return API.users
end

function API.SetBanned(this, userid, reason)
    if userid ~= nil then
        API_Database.query("FRP/SetBanned", {userId = userid, reason = reason})
        DropPlayer(this, reason)
    end
end

function API.UnBan(this, userid)
    if userid ~= nil then
        API_Database.query("FRP/UnBan", {userId = userid})
    end
end

function API.IsBanned(userId)
    local rows = API_Database.query("FRP/BannedUser", {userId = userId})
    
    if #rows > 0 then
        return rows[1].banned
    else
        return false
    end
end

RegisterCommand("clearUser", function(source, args)
    assert(source < 1, "Só é possível executar esse comando pelo CONSOLE")

    local userId = tonumber(args[1])

    API.ClearUserFromCache( 0, userId )

    print(" CLEAR ::: ", userId)
end, false)

function API.ClearUserFromCache(source, userId)
    local User = API.users[userId]

    TriggerClientEvent("FRP:_CORE:SetServerIdAsUserId", -1, source, nil)

    API.sources[tostring(source)] = nil
    API.users[userId] = nil

    if User then
        API.identifiers[User.primaryIdentifier] = nil
    end
end

function API.CreateCitizenId()
	local isUnique = false
	local citizenId = nil

    repeat
        citizenId = ("%s%s"):format(RandomStr(1), RandomInt(4)):upper()

		local result = MySQL.prepare.await('SELECT COUNT(*) as count FROM `character` WHERE `citizenId` = ?', { citizenId })

		if result == 0 then
			isUnique = true
		end
    until isUnique

	return citizenId
end

function API.GenerateCharFingerPrint()
	local isUnique = false
	local fingerId = nil

    repeat
        fingerId = tostring(RandomStr(2) .. RandomInt(3) .. RandomStr(1) .. RandomInt(2) .. RandomStr(3) .. RandomInt(4))

		local result = MySQL.prepare.await('SELECT EXISTS(SELECT 1 FROM `character` WHERE JSON_UNQUOTE(JSON_EXTRACT(metaData, "$.fingerprint")) = ?) AS uniqueCheck', { fingerId })

		if result == 0 then
			isUnique = true
		end
    until isUnique

	return fingerId
end
