const query = require('../storage/database').query;
const track = require('../tools/tracking')
const { v4: uuid } = require('uuid');
const security = require('../tools/security')


/**
 * Registra un nuovo utente
 */
async function register(username, password) {
    const userExists = await query('SELECT id FROM users WHERE username = $1', [username]);

    if (userExists.rows.length > 0) {
        throw new Error('User already exists');
    }

    const hashedPassword = await security.hashPassword(password);
    const id = uuid();

    await query('INSERT INTO users (id, username, password_hash) VALUES ($1, $2, $3)', [id, username, hashedPassword]);

    return { 
        success: true,
        user: {
            id,
            username
        }
     };
}


/**
 * Esegue il login di un utente
 */
async function login(username, password) {
    console.log('[DEBUG AUTH] login() START - username:', username);
    
    const result = await query('SELECT id, username, password_hash, created_at FROM users WHERE username = $1', [username]);
    console.log('[DEBUG AUTH] login() - query result rows:', result.rows.length);
    
    if (result.rows.length === 0) {
        console.log('[DEBUG AUTH] login() - user not found');
        throw new Error('No user matched')
    }

    const user = result.rows[0];
    console.log('[DEBUG AUTH] login() - user found:', { id: user.id, username: user.username });
    
    const isValid = await security.verifyPassword(password, user.password_hash);
    console.log('[DEBUG AUTH] login() - password valid:', isValid);

    if (!isValid) {
        console.log('[DEBUG AUTH] login() - password mismatch');
        throw new Error('Password mismatch')
    }

    const result_obj = {
        id: user.id,
        username: user.username,
        created: user.created_at
    };
    console.log('[DEBUG AUTH] login() SUCCESS - returning user:', result_obj);
    return result_obj;
}

/**
 * Esegue il logout di un utente
 * 
 */
async function logout(sessionID) {
    if (!sessionID) {
        throw new Error('no sessio id passed');
    }

    const result = await query('UPDATE sessions SET is_revoked = TRUE WHERE id = $1', [sessionID]);
    return result.rowCount > 0;
}

/**
 * Crea una nuova sessione per un utente che ha appaena eseguito il login
 */
async function newSession(userId, userAgent, ip) {
    console.log('[DEBUG AUTH] newSession() START - userId:', userId);
    
    const id = uuid();
    const sessionCode = security.generateSessionCode();
    const metadata = track.getBasicMetadata(userAgent);
    console.log('[DEBUG AUTH] newSession() - sessionCode generated:', sessionCode, 'metadata:', metadata);

    const insertResult = await query(
        `INSERT INTO sessions (id, user_id, session_code, encoded_username, ip_address, user_agent, browser, os, device_type)
         VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`,
        [id, userId, sessionCode, '', ip, userAgent, metadata.browser, metadata.os, metadata.device_type]
    );
    console.log('[DEBUG AUTH] newSession() - INSERT result:', { rowCount: insertResult.rowCount });

    const result = { id, sessionCode };
    console.log('[DEBUG AUTH] newSession() SUCCESS - returning:', result);
    return result;
}

/**
 * Valida una sessione tramite il suo UUID
 */
async function validateSession(sessionId) {
    console.log('[DEBUG AUTH] validateSession() START - sessionId:', sessionId);
    
    if (!sessionId || typeof sessionId !== 'string') {
        console.log('[DEBUG AUTH] validateSession() - invalid sessionId type');
        throw new Error('Invalid session ID');
    }

    console.log('[DEBUG AUTH] validateSession() - executing query with sessionId:', sessionId);
    
    try {
        const result = await query(
            'SELECT s.id, u.is_active FROM sessions s JOIN users u ON s.user_id = u.id WHERE s.id = $1 AND s.is_revoked = FALSE',
            [sessionId]
        );
        console.log('[DEBUG AUTH] validateSession() - query SUCCESS, rows:', result.rows.length);

        if (result.rows.length === 0) {
            console.log('[DEBUG AUTH] validateSession() - session not found or revoked');
            throw new Error('Session not found or revoked');
        }

        console.log('[DEBUG AUTH] validateSession() - row data:', result.rows[0]);
        
        if (!result.rows[0].is_active) {
            console.log('[DEBUG AUTH] validateSession() - user not active');
            throw new Error('User account is not active');
        }
        
        console.log('[DEBUG AUTH] validateSession() SUCCESS');
    } catch (err) {
        console.error('[DEBUG AUTH] validateSession() ERROR:', err.message, err.code);
        throw err;
    }
}


module.exports = {
    register,
    login,
    logout,
    newSession,
    validateSession
}