/**
 * Elasticsearch Demo Endpoint
 * GET /v1/example/es-demo
 *
 * Demuestra las capacidades del servicio de Elasticsearch
 */

const constants = require('../../../system/constants.slm');
const utils = require('../../../system/utils.slm');
const logger = require('../../../system/logger.slm');

module.exports = async (req, res, next, slmapi) => {
    try {
        const demoId = `demo-${Date.now()}`;
        const results = {};

        // 1. Crear un objeto de prueba
        logger.info('ES Demo: Creating test object');
        const createResult = await slmapi.setNewObject({
            slm: {
                type: 'demo',
                timestamp: slmapi.timestamp()
            },
            name: 'Demo Object',
            description: 'Este es un objeto de demostración',
            status: 'active',
            counter: 0,
            tags: ['demo', 'test', 'elasticsearch']
        }, demoId);

        results.create = {
            success: true,
            id: createResult._id,
            result: createResult.result
        };

        // 2. Obtener el objeto por ID
        logger.info('ES Demo: Getting object by ID');
        const getResult = await slmapi.getObjectById(demoId);

        results.getById = {
            success: !!getResult,
            object: getResult
        };

        // 3. Actualizar el objeto
        logger.info('ES Demo: Updating object');
        const updateResult = await slmapi.updateObjectByID(demoId, {
            description: 'Descripción actualizada',
            counter: 1,
            lastUpdate: slmapi.now('mx')
        });

        results.update = {
            success: true,
            result: updateResult.result
        };

        // 4. Actualizar con script (incrementar contador)
        logger.info('ES Demo: Updating with script');
        const scriptResult = await slmapi.updateObjectByID(demoId, {
            script: {
                source: 'ctx._source.counter += params.increment',
                params: { increment: 5 }
            }
        });

        results.updateWithScript = {
            success: true,
            result: scriptResult.result
        };

        // 5. Buscar objetos de tipo 'demo'
        logger.info('ES Demo: Searching by type');
        const searchResults = await slmapi.searchByType('demo', {}, 5);

        results.searchByType = {
            success: true,
            found: searchResults.length,
            items: searchResults.map(item => ({
                id: item.id,
                name: item.name,
                status: item.status
            }))
        };

        // 6. Contar documentos tipo 'demo'
        logger.info('ES Demo: Counting documents');
        const count = await slmapi.countDocuments({
            query: {
                term: { 'slm.type': 'demo' }
            }
        });

        results.count = {
            success: true,
            total: count
        };

        // 7. Buscar con query complejo
        logger.info('ES Demo: Complex search');
        const complexSearch = await slmapi.search({
            query: {
                bool: {
                    must: [
                        { term: { 'slm.type': 'demo' } },
                        { term: { 'status.keyword': 'active' } }
                    ]
                }
            },
            size: 5,
            sort: [
                { 'slm.timestamp': { order: 'desc' } }
            ]
        });

        results.complexSearch = {
            success: true,
            total: complexSearch.hits.total.value,
            hits: complexSearch.hits.hits.length
        };

        // 8. Verificar existencia
        logger.info('ES Demo: Checking existence');
        const exists = await slmapi.existsDocument(demoId);

        results.exists = {
            success: true,
            exists
        };

        // 9. Obtener objeto con valor específico
        logger.info('ES Demo: Get object with value');
        const objectWithValue = await slmapi.getObjectWithValue(
            'demo',
            'name.keyword',
            'Demo Object'
        );

        results.getObjectWithValue = {
            success: !!objectWithValue.id,
            found: !!objectWithValue.id,
            object: objectWithValue
        };

        // 10. Eliminar el objeto de prueba
        logger.info('ES Demo: Deleting test object');
        const deleteResult = await slmapi.deleteObjectByID(demoId);

        results.delete = {
            success: true,
            result: deleteResult.result
        };

        // Respuesta final
        return res.status(constants.HTTP.OK).json(
            utils.successResponse({
                message: 'Elasticsearch demo completado exitosamente',
                operations: results,
                summary: {
                    totalOperations: Object.keys(results).length,
                    allSuccessful: Object.values(results).every(r => r.success),
                    timestamp: slmapi.timestamp()
                }
            }, 'Demo de Elasticsearch ejecutado')
        );

    } catch (error) {
        logger.error('ES Demo error', {
            error: error.message,
            stack: error.stack
        });

        return res.status(constants.HTTP.INTERNAL_ERROR).json(
            utils.errorResponse(
                'Error ejecutando demo de Elasticsearch',
                constants.HTTP.INTERNAL_ERROR,
                {
                    details: process.env.NODE_ENV === 'development' ? error.message : undefined
                }
            )
        );
    }
};
