/**
 * Pulse Integration Routes
 * 
 * Exposes Pulse sensor data through Veridian's API.
 */

import { FastifyInstance } from 'fastify';
import { PrismaClient } from '@prisma/client';
import { getPulseService, initPulseService } from '../services/pulse.service';

const prisma = new PrismaClient();

export async function pulseRoutes(fastify: FastifyInstance) {
    // Auth middleware
    fastify.addHook('onRequest', async (request) => {
        try {
            await request.jwtVerify();
        } catch (err) {
            throw err;
        }
    });

    /**
     * GET /pulse/status
     * Check Pulse API connection status
     */
    fastify.get('/status', {
        handler: async (request, reply) => {
            const pulse = getPulseService();

            if (!pulse) {
                return {
                    connected: false,
                    error: 'Pulse API key not configured',
                    hint: 'Set PULSE_API_KEY environment variable'
                };
            }

            const result = await pulse.testConnection();
            return {
                connected: result.success,
                deviceCount: result.deviceCount,
                error: result.error
            };
        }
    });

    /**
     * POST /pulse/configure
     * Configure Pulse API key (admin only)
     */
    fastify.post('/configure', {
        handler: async (request, reply) => {
            const { apiKey } = request.body as { apiKey: string };

            if (!apiKey) {
                return reply.status(400).send({ error: 'API key required' });
            }

            // Test the key before saving
            const testService = initPulseService(apiKey);
            const result = await testService.testConnection();

            if (!result.success) {
                return reply.status(400).send({
                    error: 'Invalid API key',
                    details: result.error
                });
            }

            // TODO: Store in database/env for persistence
            return {
                success: true,
                deviceCount: result.deviceCount,
                message: 'Pulse API configured successfully'
            };
        }
    });

    /**
     * GET /pulse/devices
     * List all Pulse devices
     */
    fastify.get('/devices', {
        handler: async (request, reply) => {
            const pulse = getPulseService();

            if (!pulse) {
                return reply.status(503).send({ error: 'Pulse not configured' });
            }

            try {
                const devices = await pulse.getDevices();
                return { devices };
            } catch (error: any) {
                fastify.log.error(error);
                return reply.status(500).send({ error: error.message });
            }
        }
    });

    /**
     * GET /pulse/readings
     * Get current readings from all devices
     */
    fastify.get('/readings', {
        handler: async (request, reply) => {
            const pulse = getPulseService();

            if (!pulse) {
                return reply.status(503).send({ error: 'Pulse not configured' });
            }

            try {
                const readings = await pulse.getCurrentReadings();

                // Check thresholds and persist alerts (for demo/failsafe)
                const alerts: any[] = [];
                for (const reading of readings) {
                    const deviceIdentifier = reading.deviceName || reading.deviceId;

                    if (reading.temperature !== undefined && pulseThresholds.temperature.max && reading.temperature > pulseThresholds.temperature.max) {
                        const alertType = 'TEMPERATURE_HIGH';

                        // Check if active alert exists
                        const activeAlert = await prisma.environmentAlert.findFirst({
                            where: {
                                type: alertType,
                                message: { contains: deviceIdentifier },
                                resolvedAt: null
                            }
                        });

                        if (!activeAlert) {
                            const newAlert = await prisma.environmentAlert.create({
                                data: {
                                    type: alertType,
                                    severity: 'WARNING',
                                    message: `${deviceIdentifier}: ${alertType.replace('_', ' ')} (${reading.temperature.toFixed(1)}°F > ${pulseThresholds.temperature.max}°F)`,
                                    value: reading.temperature,
                                    threshold: pulseThresholds.temperature.max,
                                    createdAt: new Date()
                                }
                            });
                            alerts.push(createAlert(reading, alertType, reading.temperature, pulseThresholds.temperature.max));
                            fastify.log.info(`🚨 Created new Pulse alert: ${newAlert.id}`);
                        }
                    } else if (reading.temperature !== undefined && pulseThresholds.temperature.max) {
                        // Temperature is within threshold - AUTO-RESOLVE any active alerts for this device
                        const resolvedAlerts = await prisma.environmentAlert.updateMany({
                            where: {
                                type: 'TEMPERATURE_HIGH',
                                message: { contains: deviceIdentifier },
                                resolvedAt: null
                            },
                            data: {
                                resolvedAt: new Date()
                            }
                        });

                        if (resolvedAlerts.count > 0) {
                            fastify.log.info(`✅ Auto-resolved ${resolvedAlerts.count} alerts for ${deviceIdentifier} (temp now ${reading.temperature.toFixed(1)}°F)`);
                        }
                    }
                }

                // Broadcast any new alerts
                if (alerts.length > 0) {
                    alerts.forEach(a => broadcastAlert(a));
                }

                return {
                    readings,
                    timestamp: new Date().toISOString()
                };
            } catch (error: any) {
                fastify.log.error(error);
                return reply.status(500).send({ error: error.message });
            }
        }
    });

    /**
     * GET /pulse/devices/:id/readings
     * Get current reading for a specific device
     */
    fastify.get('/devices/:id/readings', {
        handler: async (request, reply) => {
            const { id } = request.params as { id: string };
            const pulse = getPulseService();

            if (!pulse) {
                return reply.status(503).send({ error: 'Pulse not configured' });
            }

            try {
                const reading = await pulse.getDeviceReading(id);
                if (!reading) {
                    return reply.status(404).send({ error: 'Device not found' });
                }
                return { deviceId: id, ...reading };
            } catch (error: any) {
                fastify.log.error(error);
                return reply.status(500).send({ error: error.message });
            }
        }
    });

    /**
     * GET /pulse/sparklines
     * Get sparkline data for all devices
     */
    fastify.get('/sparklines', {
        handler: async (request, reply) => {
            const pulse = getPulseService();

            if (!pulse) {
                return reply.status(503).send({ error: 'Pulse not configured' });
            }

            try {
                const sparklines = await pulse.getSparklines();
                return { sparklines };
            } catch (error: any) {
                fastify.log.error(error);
                return reply.status(500).send({ error: error.message });
            }
        }
    });

    /**
     * GET /pulse/devices/:id/history
     * Get historical readings for a device
     */
    fastify.get('/devices/:id/history', {
        handler: async (request, reply) => {
            const { id } = request.params as { id: string };
            const { hours = 24 } = request.query as { hours?: number };
            const pulse = getPulseService();

            if (!pulse) {
                return reply.status(503).send({ error: 'Pulse not configured' });
            }

            try {
                const readings = await pulse.getHistory(id, hours);
                return {
                    deviceId: id,
                    hours,
                    count: readings.length,
                    readings
                };
            } catch (error: any) {
                fastify.log.error(error);
                return reply.status(500).send({ error: error.message });
            }
        }
    });

    /**
     * GET /pulse/thresholds
     * Get current threshold configuration
     */
    fastify.get('/thresholds', {
        handler: async (request, reply) => {
            return {
                thresholds: pulseThresholds,
                lastUpdated: thresholdsLastUpdated?.toISOString() || null
            };
        }
    });

    /**
     * POST /pulse/thresholds
     * Set threshold alerts for Pulse sensors
     */
    fastify.post('/thresholds', {
        handler: async (request, reply) => {
            const config = request.body as {
                temperature?: { min: number; max: number };
                humidity?: { min: number; max: number };
                vpd?: { min: number; max: number };
                co2?: { min: number; max: number };
            };

            if (config.temperature) {
                pulseThresholds.temperature = config.temperature;
            }
            if (config.humidity) {
                pulseThresholds.humidity = config.humidity;
            }
            if (config.vpd) {
                pulseThresholds.vpd = config.vpd;
            }
            if (config.co2) {
                pulseThresholds.co2 = config.co2;
            }

            thresholdsLastUpdated = new Date();

            fastify.log.info({ event: 'pulse_thresholds_updated', thresholds: pulseThresholds });

            return {
                success: true,
                thresholds: pulseThresholds,
                message: 'Thresholds updated successfully'
            };
        }
    });

    /**
     * POST /pulse/check
     * Check current readings against thresholds and broadcast alerts
     */
    fastify.post('/check', {
        handler: async (request, reply) => {
            const pulse = getPulseService();

            if (!pulse) {
                return reply.status(503).send({ error: 'Pulse not configured' });
            }

            try {
                const readings = await pulse.getCurrentReadings();
                const alerts: any[] = [];

                for (const reading of readings) {
                    // Temperature check
                    if (reading.temperature !== undefined) {
                        if (pulseThresholds.temperature.max && reading.temperature > pulseThresholds.temperature.max) {
                            alerts.push(createAlert(reading, 'TEMPERATURE_HIGH', reading.temperature, pulseThresholds.temperature.max));
                        }
                        if (pulseThresholds.temperature.min && reading.temperature < pulseThresholds.temperature.min) {
                            alerts.push(createAlert(reading, 'TEMPERATURE_LOW', reading.temperature, pulseThresholds.temperature.min));
                        }
                    }

                    // Humidity check
                    if (reading.humidity !== undefined) {
                        if (pulseThresholds.humidity.max && reading.humidity > pulseThresholds.humidity.max) {
                            alerts.push(createAlert(reading, 'HUMIDITY_HIGH', reading.humidity, pulseThresholds.humidity.max));
                        }
                        if (pulseThresholds.humidity.min && reading.humidity < pulseThresholds.humidity.min) {
                            alerts.push(createAlert(reading, 'HUMIDITY_LOW', reading.humidity, pulseThresholds.humidity.min));
                        }
                    }

                    // VPD check
                    if (reading.vpd !== undefined) {
                        if (pulseThresholds.vpd.max && reading.vpd > pulseThresholds.vpd.max) {
                            alerts.push(createAlert(reading, 'VPD_HIGH', reading.vpd, pulseThresholds.vpd.max));
                        }
                        if (pulseThresholds.vpd.min && reading.vpd < pulseThresholds.vpd.min) {
                            alerts.push(createAlert(reading, 'VPD_LOW', reading.vpd, pulseThresholds.vpd.min));
                        }
                    }

                    // CO2 check
                    if (reading.co2 !== undefined) {
                        if (pulseThresholds.co2.max && reading.co2 > pulseThresholds.co2.max) {
                            alerts.push(createAlert(reading, 'CO2_HIGH', reading.co2, pulseThresholds.co2.max));
                        }
                        if (pulseThresholds.co2.min && reading.co2 < pulseThresholds.co2.min) {
                            alerts.push(createAlert(reading, 'CO2_LOW', reading.co2, pulseThresholds.co2.min));
                        }
                    }
                }

                // Broadcast alerts via WebSocket
                for (const alert of alerts) {
                    broadcastAlert(alert);
                }

                return {
                    devicesChecked: readings.length,
                    alertsTriggered: alerts.length,
                    alerts,
                    timestamp: new Date().toISOString()
                };
            } catch (error: any) {
                fastify.log.error(error);
                return reply.status(500).send({ error: error.message });
            }
        }
    });
}

// In-memory threshold storage (would be persisted to DB in production)
const pulseThresholds = {
    temperature: { min: 65, max: 82 },  // °F
    humidity: { min: 40, max: 70 },     // %
    vpd: { min: 0.8, max: 1.2 },        // kPa
    co2: { min: 400, max: 1500 }        // ppm
};

let thresholdsLastUpdated: Date | null = null;

// Import broadcast function
import { broadcastAlert } from '../plugins/websocket';

function createAlert(reading: any, type: string, value: number, threshold: number) {
    return {
        id: `pulse-${Date.now()}-${Math.random().toString(36).slice(2)}`,
        type,
        sensorName: reading.deviceName || `Device ${reading.deviceId}`,
        value,
        threshold,
        message: `${reading.deviceName || 'Pulse Sensor'}: ${type.replace('_', ' ')} (${value.toFixed(1)} vs threshold ${threshold})`,
        timestamp: new Date().toISOString()
    };
}

