const bcrypt = require( 'bcrypt' );
const fs = require( 'fs-extra' );
const jsonfile = require( 'jsonfile' );
const glob = require( 'glob' );
const moment = require( 'moment' );
const jwt = require( 'jwt-simple' );
const UUID = require( 'uuid' );
const Outputs = require( './Outputs.js' );
const config = require( '../tribes/townconf.js' );
const checkdata = require( `../nationchains/socialworld/contracts/checkdata.js`);

/*
Gestion des utilisateurs connecte

/tribes/tribeid/users/
                     UUID.json
                     /searchindex/indexTOKEN = {TOKEN:UUID}
                                   to check authentification
                                  indexLOGIN = {LOGIN:UUID}
                                  to check if LOGIN exist

Used for referntial:
To update
Global: datashared/referentials/dataManagement/object/users.json
Local: data/tribe/*${header.workOn}/referentials/dataManagement/object/users.json
To use after a server rerun
data/tribe/*${header.workOn}/referentials/${header.langue}/object/users.json

Faire comme contact charger les index au lancement
et changer la logique de user/id/profil o


 On initialise les objets au lancement du serveur
this.uids[u.UUID] = [u.LOGIN, u.EMAIL, u.password, u.profil, u.TOKEN];
this.logins[u.LOGIN] = u.UUID;
this.tokens[u.UUID] = u.TOKEN;
on stocke /domain/tribeid/users/logins.json et /uids.json
on stocke /domain/tribeids.json et tokkens.json

On retourne l'objet {tribeids:[list tribeid], tokens:{UUID:TOKEN}}
*/
const Pagans = {};
Pagans.init = tribeids => {
	console.group( 'init Pagans logins, tokens ...' );
	// store globaly tokens
	const tokens = {};
	const emailsglob = {};
	const loginsglob = {};
	// For each tribeid create series of indexes
	//logger.info(tribeids);
	tribeids.forEach( tribeid => {
		// Reset for each domain
		const uids = {};
		const logins = {};
		const emails = {};
		//check folder exist
		/*if( !fs.existsSync( `${config.tribes}/${tribeid}/users` ) ) {
			fs.mkdirSync( `${config.tribes}/${tribeid}/users` )
		}
		if( !fs.existsSync( `${config.tribes}/${tribeid}/users/searchindex` ) ) {
			fs.mkdirSync( `${config.tribes}/${tribeid}/users/searchindex` )
		}*/
		glob.sync( `${config.tribes}/${tribeid}/users/*.json` )
			.forEach( file => {
				//logger.info( file );
				const u = fs.readJsonSync( file, 'utf-8' );
				if( !u.TOKEN ) {
					u.TOKEN = '';
				}
				//logger.info( u )
				uids[ u.UUID ] = [ u.LOGIN, u.EMAIL, u.PASSWORD, u.ACCESSRIGHTS, u.TOKEN ];
				logins[ u.LOGIN ] = u.UUID;
				loginsglob[ u.LOGIN ] = tribeid;
				// On ne charge que les TOKEN valide
				let decodedTOKEN = {};
				if( u.TOKEN != '' ) {
					try {
						decodedTOKEN = jwt.decode( u.TOKEN, config.jwtSecret );
						//logger.info( 'decodeTOKEN', decodedTOKEN )
						if( moment( decodedTOKEN.expiration ) > moment() ) {
							tokens[ u.UUID ] = { TOKEN: u.TOKEN, ACCESSRIGHTS: u.ACCESSRIGHTS };
							//logger.info( `add token valid for ${u.UUID}:`, tokens[ u.UUID ] )
						}
					} catch ( err ) {
						logger.info( 'pb de TOKEN impossible a decoder' + u.TOKEN, err );
					}
				}
				if( u.EMAIL ) {
					emails[ u.EMAIL ] = u.UUID;
					emailsglob[ u.EMAIL ] = tribeid;
				}
			} );
		// UIDS INDEX BY DOMAIN ={UUID:[LOGIN,EMAIL,psw,accessRight,TOKEN]}
		fs.outputJson( `${config.tribes}/${tribeid}/users/searchindex/uids.json`, uids, {
			spaces: 2
		}, err => {
			if( err ) throw err;
		} );
		// LOGINS INDEX BY DOMAIN ={LOGIN:UUID}
		fs.outputJson( `${config.tribes}/${tribeid}/users/searchindex/logins.json`, logins, {
			spaces: 2
		}, err => {
			if( err ) throw err;
		} );
		// EMAILS INDEX BY DOMAIN ={EMAIL:UUID}
		fs.outputJson( `${config.tribes}/${tribeid}/users/searchindex/emails.json`, emails, {
			spaces: 2
		}, err => {
			if( err ) throw err;
		} );
	} );
	// EMAILS et appartenance domain
	fs.outputJson( `${config.tmp}/emailsglob.json`, emailsglob, {
		spaces: 2
	}, err => {
		if( err ) throw err;
	} );
	// logins et appartenance domain (permet de retrouver tribeid pour un LOGIN)
	fs.outputJson( `${config.tmp}/loginsglob.json`, loginsglob, {
		spaces: 2
	}, err => {
		if( err ) throw err;
	} );
	// TOKENS GLOBAL INDEX Centralise tous les TOKEN pour plus de rapidité
	// {UUID:TOKEN}
	fs.outputJson( `${config.tmp}/tokens.json`, tokens, {
		spaces: 2
	}, err => {
		if( err ) throw err;
	} );
	console.groupEnd();
	return { tokens };
};
/**
 * Update indexes: logins, uids and tokens
 * @param  {object} user     User object
 * @param  {string} tribeid - The client identifier
 * @rm {boolean} false => update, true => remove
 */
Pagans.updateDatabase = ( user, tribeid, rm = false ) => {
	console.group( `Pagans.updateDatabase for ${tribeid} with user ${user.LOGIN}` )
	console.assert( config.loglevel == "quiet", 'user', user );
	const loginsIndex = `${config.tribes}/${tribeid}/users/searchindex/logins.json`;
	jsonfile.readFile( loginsIndex, function ( err, logins ) {
		console.assert( config.loglevel == "quiet", 'logins', logins );
		try {
			if( rm ) {
				delete logins[ user.LOGIN ];
			} else {
				logins[ user.LOGIN ] = user.UUID;
			}
			jsonfile.writeFile( loginsIndex, logins, {
				spaces: 2
			}, err => {
				if( err ) logger.info( err );
			} );
		} catch ( err ) {
			logger.info( 'Gros pb de mise à jour Pagans.updateDatabase conflit des logins' );
		}
	} );
	const uidsIndex = `${config.tribes}/${tribeid}/users/searchindex/uids.json`;
	jsonfile.readFile( uidsIndex, function ( err, uids ) {
		try {
			if( rm ) {
				delete uids[ user.UUID ];
			} else {
				uids[ user.UUID ] = [
        user.LOGIN,
        user.EMAIL,
        user.PASSWORD,
        user.ACCESSRIGHTS,
        user.TOKEN
      ];
			}
			jsonfile.writeFile( uidsIndex, uids, {
				spaces: 2
			}, err => {
				if( err ) logger.info( err );
			} );
		} catch ( err ) {
			logger.info( 'Gros pb de mise à jour Pagans.updateDatabase conflit des uids si ce reproduit passer en mode sync bloquant' );
		}
	} );
	const emailsIndex = `${config.tribes}/${tribeid}/users/searchindex/emails.json`;
	jsonfile.readFile( emailsIndex, function ( err, emails ) {
		console.assert( config.loglevel == "quiet", 'emailss', emails );
		try {
			if( rm ) {
				delete emails[ user.EMAIL ];
			} else {
				emails[ user.EMAIL ] = user.UUID;
			}
			jsonfile.writeFile( emailsIndex, emails, {
				spaces: 2
			}, err => {
				if( err ) logger.info( err );
			} );
		} catch ( err ) {
			logger.info( 'Gros pb de mise à jour Pagans.updateDatabase conflit des emails' );
		}
	} );
	const tokensIndex = `${config.tmp}/tokens.json`;
	let tokens = {};
	try {
		tokens = jsonfile.readFileSync( tokensIndex );
	} catch ( err ) {
		logger.info( 'tokens.json not available' )
	}
	//  tokens[user.UUID] = user.TOKEN;
	tokens[ user.UUID ] = { TOKEN: user.TOKEN, ACCESSRIGHTS: user.ACCESSRIGHTS };
	jsonfile.writeFileSync( tokensIndex, tokens, {
		spaces: 2
	} );
	/*
	jsonfile.readFile(tokensIndex, function(err, tokens) {
	  tokens[user.UUID] = user.TOKEN;
	  jsonfile.writeFile(tokensIndex, tokens, { spaces: 2 }, err => {
	    if (err) logger.info(err);
	  });
	});*/
	console.groupEnd();
};
/**
 * Read the profil.json of an user
 * @param  {[type]} UUID     ID of the user
 * @param  {[type]} tribeid tribeid
 * @return {Promise} - Return a promise resolved with user data or rejected with an error
 */
// A     S U P P R I M E R utiliser getinfousers pour recuperer des indexs de users
// en créer d'autres si necessaire
Pagans.getUserlist = ( header, filter, field ) => {
	console.group( `getUserlist filter with filter ${filter} to get ${field}` );
	/*  const getuser = Pagans.getUser(header.xuuid, header.xtribeid);
	if (getuser.status != 200)
	  return { status: getuser.status, data: getuser.payload };
	const user = getuser.payload.data;
	// logger.info(user);
	// check if update accessright allowed
	// choose the level depending of ownby xuuid
	let accessright = user.objectRights[header.xtribeid].users[0];
	if (user.ownby.includes(header.xtribeid)) {
	  accessright = user.objectRights[header.xtribeid].users[1];
	}
	// Check update is possible at least user itself ownby itself
	logger.info(accessright);
	logger.info(accessright & 4);
	if ((accessright & 4) != 4) {
	  return {
	    status: 403,
	    data: { info: ['forbiddenAccess'], model: 'Pagans' }
	  };
	}
	*/
	const Userlist = [];
	glob.sync( `${config.tribes}/${header.xworkon}/users/*/profil.json` )
		.forEach( f => {
			const infouser = jsonfile.readFileSync( f );
			// Ajouter filter et liste de field
			if( filter != 'all' ) {
				// decode filter et test
			}
			const info = {};
			field.split( '______' )
				.forEach( k => {
					if( ![ 'password' ].includes( k ) ) info[ k ] = infouser[ k ];
				} );
			Userlist.push( info );
		} );
	//  logger.info('userlist', Userlist);
	console.groupEnd();
	return {
		status: 200,
		data: {
			data: Userlist
		}
	};
};
Pagans.getinfoPagans = ( tribeid, accessrights, listindex ) => {
	const info = {}
	const object = 'users';
	const indexs = listindex.split( '_' )
	let access = true;
	indexs.forEach( index => {
		access = !( [ 'emails', 'logins', 'uids' ].includes( index ) && !( accessrights.data[ object ] && accessrights.data[ object ].includes( 'R' ) ) );
		if( access && fs.existsSync( `${config.tribes}/${tribeid}/${object}/searchindex/${index}.json` ) ) {
			info[ index ] = jsonfile.readFileSync( `${config.tribes}/${tribeid}/${object}/searchindex/${index}.json` )
		}
	} )
	logger.info( info )
	return { status: 200, data: { info: info } }
}
Pagans.getUser = ( UUID, tribeid, accessrights ) => {
	console.assert( config.loglevel == "quiet", `getUser on ${UUID} for ${tribeid} with ${JSON.stringify(accessrights)}` );
	if( !fs.existsSync( `${config.tribes}/${tribeid}/users/${UUID}.json` ) ) {
		return {
			status: 404,
			data: {
				info: [ 'useridNotfound' ],
				model: 'Pagans',
				render: {
					UUID,
					tribeid
				}
			}
		}
	}
	const user = jsonfile.readFileSync( `${config.tribes}/${tribeid}/users/${UUID}.json` );
	let access = true;
	//logger.info("test accessrights.data['users'].includes('R')", accessrights.data['users'].includes('R'))
	console.assert( config.loglevel == "quiet", 'accessrights', accessrights )
	access = accessrights.users && ( accessrights.users.includes( 'R' ) || ( accessrights.users.includes( 'O' ) && user.OWNEDBY.includes( UUID ) ) );
	if( access ) {
		return {
			status: 200,
			data: {
				user: user,
				model: "User",
				info: [ "Authorizedtogetuserinfo" ]
			}
		};
	}
	return {
		status: 403,
		data: {
			info: [ 'Forbidden' ],
			model: 'Pagans',
			render: {
				UUID,
				tribeid
			}
		}
	};
};
Pagans.getUserIdFromEMAIL = ( tribeid, EMAIL ) => {
	if( !checkdata.test.EMAIL( EMAIL ) ) {
		return {
			status: 400,
			data: {
				info: [ 'ERREMAIL' ],
				model: 'Pagans'
			}
		};
	}
	const emailsIndex = jsonfile.readFileSync( `${config.tribes}/${tribeid}/users/searchindex/emails.json` );
	if( !emailsIndex.hasOwnProperty( EMAIL ) ) {
		return {
			status: 404,
			data: {
				info: [ 'userEMAILNotfound' ],
				model: 'Pagans'
			}
		};
	}
	return emailsIndex[ EMAIL ];
};
Pagans.updateUserpassword = ( UUID, header, data ) => {
	const getUser = Pagans.getUser( UUID, header.xtribeid, { users: 'W' } );
	if( getUser.status == 200 ) {
		const user = getUser.data.user;
		// logger.info('user exist', user);
		const match = bcrypt.compareSync( data.password, user.PASSWORD );
		if( !match ) {
			return {
				status: 401,
				data: {
					info: [ 'checkCredentials' ],
					model: 'Pagans'
				}
			};
		}
		// logger.info('Credentials are matching!');
		if( checkdata.test.password( {}, data.pswnew ) ) {
			user.PASSWORD = bcrypt.hashSync( data.pswnew, config.saltRounds );
			jsonfile.writeFileSync( `${config.tribes}/${header.xworkon}/users/${UUID}.json`, user, {
				spaces: 2
			} );
			Pagans.updateDatabase( user, header.xworkon, false );
			return {
				status: 200,
				data: {
					info: [ 'successfulUpdate' ],
					model: 'Pagans'
				}
			};
		} else {
			return {
				status: 401,
				data: {
					info: [ 'pswTooSimple' ],
					model: 'Pagans'
				}
			};
		}
	}
};
Pagans.createUser = ( header, data ) => {
	/*
	@input data={PUBKEY,EMAIL,LOGIN,UUID} check and create for header xworkon a user with generic password
	*/
	logger.info( 'createUser on header.xworkon:' + header.xworkon + ' by user:' + header.xpaganid );
	console.assert( config.loglevel == "quiet", 'with data:', data );
	const ref = jsonfile.readFileSync( `${config.tribes}/${header.xworkon}/referentials/${header.xlang}/object/users.json` );
	const logins = jsonfile.readFileSync( `${config.tribes}/${header.xworkon}/users/searchindex/logins.json` );
	const LOGIN = Object.keys( logins );
	console.assert( config.loglevel == "quiet", 'LOGIN list', LOGIN );
	const emails = jsonfile.readFileSync( `${config.tribes}/${header.xworkon}/users/searchindex/emails.json` );
	console.assert( config.loglevel == "quiet", 'emails', emails );
	const EMAIL = Object.keys( emails );
	console.assert( config.loglevel == "quiet", 'EMAIL list', EMAIL );
	// list.UUID est forcement unique car on est en update et pas en create
	if( !data.UUID ) data.UUID = UUID.v4();
	// pour la logique de checkdata il faut passer le parametre
	const check = checkdata.evaluate( {
		list: {
			LOGIN,
			EMAIL,
			UUID: []
		}
	}, ref, data );
	console.assert( config.loglevel == "quiet", 'check & clean data before update ', check );
	if( check.invalidefor.length > 0 ) {
		return {
			status: 403,
			data: {
				model: 'Pagans',
				info: check.invalidefor
			}
		};
	}
	const clientConfig = jsonfile.readFileSync( `${config.tribes}/${header.xworkon}/clientconf.json` );
	const user = check.data;
	user.DATE_CREATE = new Date()
		.toISOString();
	user.PASSWORD = bcrypt.hashSync( clientConfig.genericpsw, config.saltRounds );
	user.OWNBY = [ data.UUID ];
	user.OBJECT = 'users';
	// set le minimum de droit sur l'objet users dont il est le Owner
	if( data.ACCESSRIGHTS ) {
		user.ACCESSRIGHTS = data.ACCESSRIGHTS
	} else {
		user.ACCESSRIGHTS = { app: {}, data: {} };
	}
	user.ACCESSRIGHTS.data[ header.xworkon ] = { users: "O" };
	jsonfile.writeFileSync( `${config.tribes}/${header.xworkon}/users/${user.UUID}.json`, user, {
		spaces: 2
	} );
	Pagans.updateDatabase( user, header.xworkon, false );
	return {
		status: 200,
		data: {
			uuid: user.UUID,
			info: [ 'successfulCreate' ],
			model: 'Pagans'
		}
	};
};
Pagans.updateUser = ( UUID, header, data ) => {
	logger.info( 'updateUser UUID:' + UUID + ' on header.xworkon:' + header.xworkon + ' by user' + header.xpaganid );
	// logger.info('header', header);
	console.assert( config.loglevel == "quiet", 'with data', data );
	const getuser = Pagans.getUser( UUID, header.xworkon, { users: 'R' } );
	if( getuser.status != 200 ) return {
		status: getuser.status,
		data: getuser.data.user
	};
	const user = getuser.data.user;
	/*
	let userconnected = user;
	if (UUID != header.xuuid) {
	  // mean connected user want to change other user
	  const getuserconnected = Pagans.getUser(header.xuuid, header.xtribeid);
	  userconnected = getuserconnected.payload.data;
	}
	logger.info('user to update', user);
	logger.info('user connected that request update', userconnected);

	// check if update accessright allowed
	// choose the level depending of ownby xuuid
	let accessright = userconnected.objectRights[header.xworkon].users[0];
	if (user.ownby.includes(header.xuuid)) {
	  accessright = userconnected.objectRights[header.xworkon].users[1];
	}
	// Check update is possible at least user itself ownby itself
	logger.info(accessright);
	logger.info(accessright & 2);
	if ((accessright & 2) != 2) {
	  return {
	    status: 403,
	    data: { info: ['forbiddenAccess'], model: 'Pagans' }
	  };
	}
	*/
	const ref = jsonfile.readFileSync( `${config.tribes}/${header.xworkon}/referentials/object/users_${
      header.xlang
    }.json` );
	const logins = jsonfile.readFileSync( `${config.tribes}/${header.xworkon}/users/searchindex/logins.json` );
	const LOGIN = Object.keys( logins )
		.filter( l => logins[ l ] != user.UUID );
	//	logger.info( 'LOGIN list', LOGIN );
	const emails = jsonfile.readFileSync( `${config.tribes}/${header.xworkon}/users/searchindex/emails.json` );
	//	logger.info( 'emails', emails );
	const EMAIL = Object.keys( emails )
		.filter( e => emails[ e ] != user.UUID );
	//	logger.info( 'EMAIL list', EMAIL );
	// list.UUID est forcement unique car on est en update et pas en create
	// pour la logique de checkdata il faut passer le parametre
	const check = checkdata.evaluate( {
		profil: user[ 'apps' + header.xworkon + 'profil' ],
		list: {
			LOGIN,
			EMAIL,
			UUID: []
		}
	}, ref, data );
	if( check.invalidefor.length > 0 ) {
		return {
			status: 403,
			data: {
				model: 'Pagans',
				info: check.invalidefor,
			}
		};
	}
	data = check.data;
	let saveuser = false;
	let updateDatabase = false;
	Object.keys( data )
		.forEach( k => {
			//logger.info( user[ k ] )
			//logger.info( data[ k ] )
			//logger.info( '---' )
			if( user[ k ] != data[ k ] ) {
				user[ k ] = data[ k ];
				saveuser = true;
				if( [ 'TOKEN', 'LOGIN', 'EMAIL' ].includes( k ) ) updateDatabase = true;
				// attention si LOGIN ou EMAIL change il faut checker qu il n existe pas dejà risque de conflit
			}
		} );
	if( saveuser ) {
		//logger.info( 'mise à jour user profile.json' );
		if( data.TOKEN ) {
			user.date_lastLOGIN = new Date()
				.toISOString();
		} else {
			user.date_update = new Date()
				.toISOString();
		}
		try {
			jsonfile.writeFileSync( `${config.tribes}/${header.xworkon}/users/${UUID}.json`, user, {
				spaces: 2
			} );
			//logger.info( 'declenche updatabase', updateDatabase )
			if( updateDatabase ) {
				// mean index have to be updated
				Pagans.updateDatabase( user, header.xworkon, false );
				console.assert( config.loglevel == "quiet", 'MISE A JOUR DU TOKEN ou de l\'EMAIL ou du LOGIN' );
			}
		} catch ( err ) {
			logger.info( 'ERRRRR need to understand update impossible of user: ' + UUID + ' in domain:' + header.xworkon + ' from user ' + header.xpaganid + ' of domain:' + header.xtribe );
			logger.info( 'with data :', data );
			return {
				status: 400,
				data: {
					info: [ 'failtoWritefs' ],
					model: 'Pagans'
				}
			};
		}
	}
	return {
		status: 200,
		data: {
			info: [ 'successfulUpdate' ],
			model: 'Pagans'
		}
	};
};
Pagans.deleteUser = ( UUID, header ) => {
	// Delete remove from users object UUID and update index
	// Activity is not deleted => means some activity can concern an UUID that does not exist anymore.
	// update index
	const infouser = jsonfile.readFileSync( `${config.tribes}/${header.xworkon}/users/${UUID}.json` );
	Pagans.updateDatabase( infouser, header.xworkon, true );
	fs.removeSync( `${config.tribes}/${header.xworkon}/users/${UUID}.json` );
	return {
		status: 200,
		data: {
			info: [ 'successfulDelete' ],
			modedl: 'Pagans'
		}
	};
};
/*
@header { xtribeid: client domain name data
      A VERIFIER inutile    ,xworkon: client domain name where user is store and where data are stored
          ,xuuid: 1 if unknown else if user id auhtneticated
          ,xlanguage: langue used fr en return referential in this lang
          ,xauth: TOKEN valid for 24h'}
      workon=xtribeid in an app client usage
      in case of xtribeid=mymaidigit,
         if workon==mymaildigit =>  admin role on any xworkon
                                 else   adlin role only in xworkon specified
@body {LOGIN: password:}
return {status:200, data:{data:{TOKEN,UUID}}}
return {status:401,data:{info:[code list], model: referential}}
*/
Pagans.loginUser = ( header, body, checkpsw ) => {
	// On recupere tribeid du LOGIN
	// ATTENTION  xworkon peut être different du user xtribeid
	//(cas d'un user qui a des droits sur un autre domain et qui travail sur cet autre domain)
	// les function Pagans utilise le domain de travail xWorkon
	// il faut donc modifier le header au moment du LOGIN
	// pour que l'update du user au moment du LOGIN concerne bien le bon domain
	header.xworkon = header.xtribe
	const LOGINdom = jsonfile.readFileSync( `${config.tmp}/loginsglob.json` );
	console.assert( config.loglevel == "quiet", LOGINdom )
	console.assert( config.loglevel == "quiet", body )
	if( !LOGINdom[ body.LOGIN ] ) {
		return {
			status: 401,
			data: { info: [ 'LoginDoesNotExist' ], model: 'Pagans' }
		};
	}
	const logins = jsonfile.readFileSync( `${config.tribes}/${LOGINdom[body.LOGIN]}/users/searchindex/logins.json` );
	if( !Object.keys( logins )
		.includes( body.LOGIN ) ) {
		return {
			status: 401,
			data: {
				info: [ 'LOGINDoesNotExist' ],
				model: 'Pagans',
				moreinfo: `Le login ${body.LOGIN} does not exist for tribeid ${LOGINdom[body.LOGIN]}`
			}
		};
	}
	// Load user
	const uid = logins[ body.LOGIN ];
	const getUser = Pagans.getUser( uid, LOGINdom[ body.LOGIN ], { users: 'R' } );
	logger.info( 'getPagans', getUser )
	if( getUser.status != 200 ) {
		return { status: 200, data: { model: 'Pagans', user: getUser.data.user } };
	}
	const user = getUser.data.user;
	logger.info( 'user', user )
	if( checkpsw ) {
		const match = bcrypt.compareSync( body.PASSWORD, user.PASSWORD );
		if( !match ) {
			return {
				status: 401,
				data: {
					info: [ 'checkCredentials' ],
					model: 'Pagans'
				}
			};
		}
	}
	// Mise à jour user pour app LOGIN
	user.tribeid = LOGINdom[ body.LOGIN ]
	user.TOKEN = jwt.encode( {
		expiration: moment()
			.add( 1, 'day' ),
		UUID: user.UUID
	}, config.jwtSecret );
	// on met à jour le header qui authentifie le user connecte
	header.xtribe = LOGINdom[ body.LOGIN ]
	header.xpaganid = user.UUID;
	header.xauth = user.TOKEN;
	// On modifie xworkon car au LOGIN on est forcemenet identifiable sur tribeid
	// xworkon est utiliser pour travailler sur un environnement client different de celui
	// de l'appartenace du user
	header.xworkon = LOGINdom[ body.LOGIN ];
	const majuser = Pagans.updateUser( user.UUID, header, {
		UUID: user.UUID,
		TOKEN: user.TOKEN
	} );
	// Enleve info confidentiel
	delete user.PASSWORD;
	if( user.ACCESSRIGHTS.data[ "Alltribeid" ] ) {
		//cas admin on transforme les droits sur tous les tribeid existant
		const newaccessrightsdata = {}
		jsonfile.readFileSync( `${config.tribes}/tribeids.json` )
			.forEach( cid => {
				newaccessrightsdata[ cid ] = user.ACCESSRIGHTS.data[ "Alltribeid" ]
			} )
		user.ACCESSRIGHTS.data = newaccessrightsdata;
	}
	// on recupere le menu de l app qui demande le LOGIN si existe dans user.ACCESSRIGHTS.app[]
	// header['X-app'] = tribeid:Projet pour récuperer le menu correspondant
	console.assert( config.loglevel == "quiet", "header.xapp", header.xapp )
	console.assert( config.loglevel == "quiet", "user.ACCESSRIGHTS.app[header.xapp]", user.ACCESSRIGHTS.app[ header.xapp ] );

	return {
		status: 200,
		data: {
			model: "Pagans",
			info: [ 'loginSuccess' ],
			user: user
		}
	};
};
Pagans.getlinkwithoutpsw = async ( EMAIL, header ) => {
	// check le domain d'appartenance de l'eamail dans /tribes/emailsglob.json={email:cleintId}
	// on remplace le header.xtribeid
	const domforemail = jsonfile.readFileSync( `${config.tribes}/emailsglob.json`, 'utf-8' );
	if( domforemail[ EMAIL ] ) {
		header.xtribe = domforemail[ EMAIL ]
	} else {
		return { status: 404, info: { model: 'Pagans', info: [ 'emailnotfound' ], moreinfo: "email does not exist in /emailsglob.json" } };
	}
	// recupere le uuid du user dans /tribes/tribeid/users/searchindex/emails.json
	// puis l'ensemble des info des user du domain /uuids.json
	// infoforuuid[uuidforemail[EMAIL]] permet de récupérer toutes info du user, droit, etc...
	const uuidforemail = jsonfile.readFileSync( `${config.tribes}/${header.xtribe}/users/searchindex/emails.json`, 'utf8' );
	const infoforuuid = jsonfile.readFileSync( `${config.tribes}/${header.xtribe}/users/searchindex/uids.json`, 'utf8' );
	// On recupere le modele d'email appemailinfo qui doit être présent dans clientconf.json
	let confdom = jsonfile.readFileSync( `${config.tribes}/${header.xtribe}/clientconf.json`, 'utf8' );
	let checkinfomail = "";
	if( !confdom.appemailinfo ) {
		checkinfomail += ' Erreur de clientconfig il manque un objet appemailinfo pour poursuivre';
	}
	if( checkinfomail != "" ) {
		logger.info( `Pb de config pour ${header.xtribe} ${checkinfomail} ` )
		return {
			status: 500,
			info: {
				model: 'Pagans',
				info: [ 'objectmissingclientconf' ],
				moreinfo: checkinfomail
			}
		};
	}
	let simulelogin;
	try {
		simulelogin = await Pagans.loginUser( header, {
			LOGIN: infoforuuid[ uuidforemail[ EMAIL ] ][ 0 ],
			PASSWORD: ""
		}, false );
		logger.info( 'info simulelogin', simulelogin )
	} catch ( err ) {
		return {
			status: 501,
			info: {
				model: 'Pagans',
				info: [ 'loginImpossible' ],
				moreinfo: "Impossible de se loger avec " + infoforuuid[ uuidforemail[ EMAIL ] ][ 0 ]
			}
		};
	}
	const url = `${config.rootURL}?xauth=${simulelogin.data.TOKEN}&xuuid=${simulelogin.data.UUID}&xtribeid=${simulelogin.data.tribeid}&xworkOn=${header.xworkon}&xlang=${header.xlang}`
	//logger.info('envoi email avec' + url)
	confdom.appemailinfo.msg.destperso = [ {} ];
	confdom.appemailinfo.msg.destperso[ 0 ].email = EMAIL;
	confdom.appemailinfo.msg.destperso[ 0 ].subject = "Lien de réinitialisation valable 1h"
	confdom.appemailinfo.msg.destperso[ 0 ].titre = "Vous avez oublier votre mot de passe"
	confdom.appemailinfo.msg.destperso[ 0 ].texte = `
            <p style='color: #999999; font-size: 16px; line-height: 24px; margin: 0;text-align:justify;'>
            Bonjour,<br> Vous nous avez signalé que vous avez oublié votre mot de passe pour cette email.
            Avec le lien suivant vous allez pouvoir utiliser votre interface 1h maximum.
            <a href="${url}">Clicker ICI</a>.<br>
            Nous vous conseillons de changer votre mot de passe.</p>
    `
	//logger.info('envoi header :', header);
	Outputs.sendMailcampain( confdom.appemailinfo.msg, header );
	logger.info( confdom.appemailinfo );
	return {
		status: 200,
		info: {
			model: 'Pagans',
			info: [ 'emailsentforReinit' ],
			moreinfo: 'EMAIL sent with unique link ' + url
		}
	};
}
module.exports = Pagans;
