const jwt = require('jsonwebtoken');

const secret = process.env.JWT_SECRET;
const expires_in = process.env.JWT_EXPIRES_IN;

/**
 * Genera un JWT Token a partire dall'utente e crea una nuova sessione
 * 
 * Uso dell'algoritmo HS256 per firmare il token con JWT_SECRET
 * 
 * @param {Object} user - Utente
 * @param {string} sessionID - ID della sessione
 * @returns {string} - JWT Token
 */
function generateToken(user, sessionID) {
    const payload = {
        sub: user.id,
        username: user.username,
        session_id: sessionID,
        iat: Math.floor(Date.now() / 1000)
    };

    return jwt.sign(payload, secret, { expiresIn: expires_in, algorithm: 'HS256' });
}

/**
 * Verifica e decodifica il token
 * @param {string} token - JWT Token
 * @returns {{valid: boolean, payload?: Object, error?: string, reason?: string}} - Il risultato della verifica. Se fallisce restituisce errore e motivo, altrimenti restituisce una conferma e il payload completo
 */
function verifyToken(token) {
    try {
        const payload = jwt.verify(token, secret, {
            algorithms: ['HS256']
        });
        return {
            valid: true,
            payload: {
                user_id: payload.sub,
                username: payload.username,
                session_id: payload.session_id,
                iat: payload.iat,
                exp: payload.exp
            }
        };
    } catch (err) {

        const reason = err.name === 'TokenExpiredError' ? 'expired' : 'invalid';

        return {
            valid: false,
            error: err.message,
            reason: `token ${reason}`
        };
    }
}

function getToken(header) {
    if (!header) return null;

    const parts = header.split(' ');
    if (parts.length === 2 && parts[0].toLowerCase() === 'bearer') {
        return parts[1];
    }

    return null;
}

module.exports = { generateToken, verifyToken, getToken };