const router = require('express').Router();
const { queryAll, query, hset } = require('../store/redis');
const { connectedSensors } = require('../ws/handler');
const { flush, exportSessionCSV } = require('../store/influx');
const db = require('../store/db');

/**
 * GET /sessions — Lista tutte le sessioni attive dei sensori
 */
router.get('/', async (req, res) => {
    try {
        const keys = await queryAll('sensors');
        const sessions = {};
        for (const key of keys) {
            const name = key.replace('sensors:', '');
            const info = await query(name, 'sensors');
            sessions[name] = {
                name,
                connectedAt: info.connectedAt || info.timestamp || null,
                session: info.session || null,
                status: info.status || 'unknown'
            };
        }
        res.json(sessions);
    } catch (err) {
        console.error('Error fetching sessions', err);
        res.status(500).json({ error: 'internal server error' });
    }
});

/**
 * GET /sessions/history — Lista tutte le sessioni passate (da sessiondataref)
 */
router.get('/history', async (req, res) => {
    try {
        const result = await db.query('sensors',
            `SELECT * FROM sessiondataref ORDER BY created_at DESC LIMIT 100`
        );
        res.json(result.rows);
    } catch (err) {
        console.error('Error fetching session history:', err.message);
        res.status(500).json({ error: 'internal server error' });
    }
});

/**
 * GET /sessions/pending — Lista token di connessione pendenti
 */
router.get('/pending', async (req, res) => {
    try {
        const keys = await queryAll('sensors_pending');
        res.json(keys);
    } catch (err) {
        console.error('Error fetching pending tokens', err);
        res.status(500).json({ error: `Error fetching pending tokens, ${err}` });
    }
});

/**
 * GET /sessions/connected — Lista sensori attualmente connessi
 */
router.get('/connected', async (req, res) => {
    try {
        const keys = await queryAll('sensor');
        const connected = [];
        for (const key of keys) {
            const name = key.replace('sensor:', '');
            const info = await query(name, 'sensor');
            if (info.status === 'connected') {
                connected.push({ name, connectedAt: info.timestamp });
            }
        }
        res.json(connected);
    } catch (err) {
        console.error('Error fetching connected sensors', err);
        res.status(500).json({ error: `Error fetching connected sensors, ${err}` });
    }
});

/**
 * GET /sessions/connected/:id — Verifica se un sensore specifico e connesso
 */
router.get('/connected/:id', async (req, res) => {
    const { id } = req.params;
    try {
        const info = await query(id, 'sensor');
        if (!info || info.status !== 'connected') {
            return res.status(404).json({ error: 'sensor not connected' });
        }
        res.json({ name: id, connectedAt: info.timestamp });
    } catch (err) {
        console.error('Error fetching sensor connection status', err);
        res.status(500).json({ error: `Error fetching sensor connection status, ${err}` });
    }
});

/**
 * POST /sessions/:id/flush — Forza il flush del buffer InfluxDB
 */
router.post('/:id/flush', async (req, res) => {
    try {
        await flush();
        res.json({ status: 'ok' });
    } catch (err) {
        console.error('Error flushing:', err.message);
        res.status(500).json({ error: 'flush failed' });
    }
});

/**
 * GET /sessions/:id/csv — Esporta tutti i dati della sessione come CSV.
 * Usa il session_id da Redis (sensore connesso) oppure il query param ?session=sXXXX.
 * Il CSV contiene tutti i dati logs per quel sensor + session da InfluxDB.
 */
router.get('/:id/csv', async (req, res) => {
    const sensorName = req.params.id;

    try {
        // Determina il session_id: da query param, da Redis, o dall'ultimo in DB
        let sessionId = req.query.session || null;

        if (!sessionId) {
            // Prova da Redis (sensore connesso)
            const info = await query(sensorName, 'sensors');
            sessionId = info?.session || null;
        }

        if (!sessionId) {
            // Ultima sessione in sessiondataref
            const result = await db.query('sensors',
                `SELECT session_id FROM sessiondataref WHERE sensor_name = $1 ORDER BY created_at DESC LIMIT 1`,
                [sensorName]
            );
            sessionId = result.rows[0]?.session_id || null;
        }

        if (!sessionId) {
            return res.status(404).json({ error: 'No session found for this sensor' });
        }

        // Determina il range temporale: da connectedAt della sessione
        let since = req.query.from ? new Date(parseInt(req.query.from)).toISOString() : null;

        if (!since) {
            // Cerca il created_at nella sessiondataref
            const result = await db.query('sensors',
                `SELECT created_at FROM sessiondataref WHERE session_id = $1`,
                [sessionId]
            );
            since = result.rows[0]?.created_at?.toISOString() || '-30d';
        }

        const csv = await exportSessionCSV(sensorName, sessionId, since);

        if (!csv) {
            return res.status(404).json({ error: 'No data found for this session' });
        }

        res.setHeader('Content-Type', 'text/csv');
        res.setHeader('Content-Disposition', `attachment; filename="session_${sessionId}_${sensorName}.csv"`);
        res.send(csv);

    } catch (err) {
        console.error('Error exporting CSV:', err.message);
        res.status(500).json({ error: 'CSV export failed' });
    }
});

/**
 * GET /sessions/:id/details — Ottieni i dettagli della sessione corrente
 */
router.get('/:id/details', async (req, res) => {
    const sensorName = req.params.id;
    const sessionId = req.query.session || null;

    try {
        let result;
        if (sessionId) {
            result = await db.query('sensors',
                `SELECT * FROM sessiondataref WHERE session_id = $1`,
                [sessionId]
            );
        } else {
            // Ultima sessione per questo sensore
            result = await db.query('sensors',
                `SELECT * FROM sessiondataref WHERE sensor_name = $1 ORDER BY created_at DESC LIMIT 1`,
                [sensorName]
            );
        }

        if (result.rows.length === 0) {
            return res.status(404).json({ error: 'Session not found' });
        }

        res.json(result.rows[0]);
    } catch (err) {
        console.error('Error fetching session details:', err.message);
        res.status(500).json({ error: 'internal server error' });
    }
});

/**
 * PUT /sessions/:id/details — Aggiorna nome, descrizione o tags della sessione.
 * Body: { name?, description?, tags? }
 */
router.put('/:id/details', async (req, res) => {
    const sensorName = req.params.id;
    const { session: sessionId, name, description, tags } = req.body;

    if (!sessionId) {
        return res.status(400).json({ error: 'session id is required in body' });
    }

    try {
        const updates = [];
        const values = [];
        let idx = 1;

        if (name !== undefined) {
            updates.push(`name = $${idx++}`);
            values.push(name);
        }
        if (description !== undefined) {
            updates.push(`description = $${idx++}`);
            values.push(description);
        }
        if (tags !== undefined) {
            updates.push(`tags = $${idx++}`);
            values.push(tags);
        }

        if (updates.length === 0) {
            return res.status(400).json({ error: 'No fields to update' });
        }

        updates.push(`updated_at = NOW()`);
        values.push(sessionId);

        const result = await db.query('sensors',
            `UPDATE sessiondataref SET ${updates.join(', ')} WHERE session_id = $${idx} RETURNING *`,
            values
        );

        if (result.rows.length === 0) {
            return res.status(404).json({ error: 'Session not found' });
        }

        res.json(result.rows[0]);
    } catch (err) {
        console.error('Error updating session details:', err.message);
        res.status(500).json({ error: 'internal server error' });
    }
});

module.exports = router;
