const { Pool } = require('pg');

const config = {
    user: process.env.DB_USER,
    password: process.env.DB_PASSWORD,
    host: process.env.DB_HOST,
    port: process.env.DB_PORT,
    max: 10,
    idleTimeoutMillis: 30000,
    connectionTimeoutMillis: 5000
}

const pool = new Pool({ ...config, database: process.env.USERS_DB });

pool.on('error', (err) => {
    console.error('Error in database', err);
});

/**
 * Execute a query with parameters
 * @param {string} text - SQL query
 * @param {Array} params - Query parameters
 * @returns {Promise<Object>} Query result
 */
async function query(text, params) {
    const start = Date.now();
    console.log('[DEBUG DB] Executing query:', text.substring(0, 120));
    if (params && params.length > 0) {
        console.log('[DEBUG DB] Parameters:', params);
    }
    
    try {
        const result = await pool.query(text, params);
        const duration = Date.now() - start;

        if (duration > 100) {
            console.warn(`[DB] Slow query (${duration}ms):`, text.substring(0, 80));
        }
        
        console.log('[DEBUG DB] Query successful - rows:', result.rowCount, 'duration:', duration + 'ms');
        return result;
    } catch (err) {
        const duration = Date.now() - start;
        console.error('[DEBUG DB] Query FAILED:', err.message);
        console.error('[DEBUG DB] Error code:', err.code);
        console.error('[DEBUG DB] Query:', text.substring(0, 120));
        console.error('[DEBUG DB] Duration:', duration + 'ms');
        console.error('[DEBUG DB] Full error:', err);
        throw err;
    }
}

/**
 * Get a client from pool for transactions
 * @returns {Promise<Object>} Pool client
 */
async function getClient() {
    return await pool.connect();
}

/**
 * Initialize database and ensure tables exist
 */
async function initDb() {
    // Test connection
    await pool.query('SELECT NOW()');
    // Ensure pgcrypto extension (provides gen_random_uuid)
    // Note: creating extensions requires proper DB permissions (usually superuser in PG)
    try {
        await pool.query(`CREATE EXTENSION IF NOT EXISTS pgcrypto;`);
    } catch (err) {
        console.warn('[DB] Could not create pgcrypto extension (may require superuser):', err.message);
    }

    // Ensure tables exist (UUID default generated by DB)
    await pool.query(`
        CREATE TABLE IF NOT EXISTS users (
            id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
            username VARCHAR(50) UNIQUE NOT NULL,
            password_hash VARCHAR(255) NOT NULL,
            is_active BOOLEAN DEFAULT TRUE,
            created_at TIMESTAMP DEFAULT NOW(),
            telegram_id VARCHAR(50) UNIQUE
        );

        CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
        CREATE INDEX IF NOT EXISTS idx_users_telegram_id ON users(telegram_id);
    `);

    await pool.query(`
        CREATE TABLE IF NOT EXISTS sessions (
            id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
            user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
            session_code VARCHAR(64) NOT NULL,
            encoded_username TEXT NOT NULL,
            ip_address INET,
            user_agent TEXT,
            browser VARCHAR(100),
            os VARCHAR(100),
            device_type VARCHAR(50),
            location_country VARCHAR(100),
            location_city VARCHAR(100),
            created_at TIMESTAMP DEFAULT NOW(),
            last_active TIMESTAMP DEFAULT NOW(),
            is_revoked BOOLEAN DEFAULT FALSE
        );

        -- Altera colonna in base al nuovo standard token 32 byte - 64 url chars
        ALTER TABLE sessions ALTER COLUMN session_code TYPE VARCHAR(64);

        CREATE INDEX IF NOT EXISTS idx_sessions_code ON sessions(session_code);
        CREATE INDEX IF NOT EXISTS idx_sessions_user_id ON sessions(user_id);
    `);
}

async function checkPostgres() {
    try {
        await pool.query('SELECT NOW()');
        return true;
    } catch (error) {
        return false;
    }
}

module.exports = {
    pool,
    query,
    getClient,
    initDb,
    checkPostgres
};
