/**
 * SLM Framework - Utilities
 * Funciones auxiliares para manejo de respuestas y datos
 */

/**
 * Crea una respuesta de error estándar
 * @param {string} message - Mensaje de error
 * @param {number} statusCode - Código HTTP (opcional)
 * @param {object} additionalData - Datos adicionales (opcional)
 * @returns {object} Respuesta formateada
 */
function errorResponse(message, statusCode = null, additionalData = {}) {
    const response = {
        error: true,
        message: message,
        timestamp: Date.now()
    };

    // Agregar código de estado si se proporciona
    if (statusCode) {
        response.statusCode = statusCode;
    }

    // Agregar datos adicionales si existen
    if (additionalData && Object.keys(additionalData).length > 0) {
        Object.assign(response, additionalData);
    }

    return response;
}

/**
 * Crea una respuesta de éxito estándar
 * @param {object} data - Datos de respuesta
 * @param {string} message - Mensaje opcional
 * @returns {object} Respuesta formateada
 */
function successResponse(data, message = null) {
    const response = {
        error: false,
        timestamp: Date.now()
    };

    if (message) {
        response.message = message;
    }

    if (data !== undefined) {
        response.data = data;
    }

    return response;
}

/**
 * Sanitiza datos sensibles para logging
 * @param {string} value - Valor a sanitizar
 * @param {number} showChars - Caracteres a mostrar (default: 8)
 * @returns {string} Valor sanitizado
 */
function sanitizeForLog(value, showChars = 8) {
    if (!value || typeof value !== 'string') {
        return '[INVALID]';
    }

    if (value.length <= showChars) {
        return '*'.repeat(value.length);
    }

    const start = value.substring(0, showChars);
    return `${start}...`;
}

/**
 * Valida si un email es válido
 * @param {string} email - Email a validar
 * @returns {boolean}
 */
function isValidEmail(email) {
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    return emailRegex.test(email);
}

/**
 * Valida si un string es JSON válido
 * @param {string} str - String a validar
 * @returns {boolean}
 */
function isValidJSON(str) {
    try {
        JSON.parse(str);
        return true;
    } catch (e) {
        return false;
    }
}

/**
 * Extrae parámetros de query con valores por defecto
 * @param {object} query - Objeto query de Express
 * @param {object} defaults - Valores por defecto
 * @returns {object} Parámetros procesados
 */
function extractQueryParams(query, defaults = {}) {
    const params = { ...defaults };

    Object.keys(defaults).forEach(key => {
        if (query[key] !== undefined) {
            // Convertir a tipo apropiado
            const defaultValue = defaults[key];

            if (typeof defaultValue === 'number') {
                params[key] = parseInt(query[key]) || defaultValue;
            } else if (typeof defaultValue === 'boolean') {
                params[key] = query[key] === 'true' || query[key] === '1';
            } else {
                params[key] = query[key];
            }
        }
    });

    return params;
}

/**
 * Genera ID único basado en timestamp y random
 * @param {string} prefix - Prefijo opcional
 * @returns {string} ID único
 */
function generateId(prefix = '') {
    const timestamp = Date.now().toString(36);
    const random = Math.random().toString(36).substring(2, 9);
    return prefix ? `${prefix}-${timestamp}-${random}` : `${timestamp}-${random}`;
}

/**
 * Valida parámetros requeridos en un objeto
 * @param {object} data - Objeto a validar
 * @param {array} requiredFields - Campos requeridos
 * @returns {object} { valid: boolean, missing: array }
 */
function validateRequiredFields(data, requiredFields) {
    const missing = [];

    requiredFields.forEach(field => {
        if (data[field] === undefined || data[field] === null || data[field] === '') {
            missing.push(field);
        }
    });

    return {
        valid: missing.length === 0,
        missing
    };
}

/**
 * Formatea bytes a formato legible
 * @param {number} bytes - Bytes a formatear
 * @param {number} decimals - Decimales (default: 2)
 * @returns {string} String formateado
 */
function formatBytes(bytes, decimals = 2) {
    if (bytes === 0) return '0 Bytes';

    const k = 1024;
    const dm = decimals < 0 ? 0 : decimals;
    const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];

    const i = Math.floor(Math.log(bytes) / Math.log(k));

    return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}

/**
 * Sleep async
 * @param {number} ms - Milisegundos
 * @returns {Promise}
 */
function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

/**
 * Trunca texto a longitud máxima
 * @param {string} text - Texto a truncar
 * @param {number} maxLength - Longitud máxima
 * @param {string} suffix - Sufijo (default: '...')
 * @returns {string}
 */
function truncate(text, maxLength, suffix = '...') {
    if (!text || text.length <= maxLength) {
        return text;
    }
    return text.substring(0, maxLength - suffix.length) + suffix;
}

module.exports = {
    errorResponse,
    successResponse,
    sanitizeForLog,
    isValidEmail,
    isValidJSON,
    extractQueryParams,
    generateId,
    validateRequiredFields,
    formatBytes,
    sleep,
    truncate
};
