const express = require('express');
const router = express.Router();
const db = require('../config/database');

const LOCATION_STATIC_API_KEY = 'GPSV2_STATIC_LOCATION_KEY_2025';

const authenticateLocationKey = (req, res, next) => {
  const apiKey = req.headers['x-api-key'];
  if (!apiKey || apiKey !== LOCATION_STATIC_API_KEY) {
    return res.status(401).json({ message: 'Invalid API key' });
  }
  next();
};

const toRad = (value) => (value * Math.PI) / 180;

const haversineDistanceMeters = (lat1, lon1, lat2, lon2) => {
  const R = 6371000;
  const dLat = toRad(lat2 - lat1);
  const dLon = toRad(lon2 - lon1);
  const a =
    Math.sin(dLat / 2) * Math.sin(dLat / 2) +
    Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  return R * c;
};

// Get last location for a device
router.get('/:deviceId/last', async (req, res) => {
  try {
    const { deviceId } = req.params;
    
    const query = `
      SELECT latitude, longitude, altitude, accuracy, speed, battery_level, address, timestamp
      FROM device_locations 
      WHERE device_id = ? 
      ORDER BY timestamp DESC 
      LIMIT 1
    `;
    
    const [rows] = await db.execute(query, [deviceId]);
    
    if (rows.length === 0) {
      return res.status(404).json({ message: 'No location data found for this device' });
    }
    
    res.json(rows[0]);
  } catch (error) {
    console.error('Error fetching location:', error);
    res.status(500).json({ message: 'Server error' });
  }
});

// Get location history for a device
router.get('/:deviceId/history', async (req, res) => {
  try {
    const { deviceId } = req.params;
    const { start, end } = req.query;
    
    const query = `
      SELECT latitude, longitude, altitude, accuracy, speed, battery_level, address, timestamp
      FROM device_locations 
      WHERE device_id = ? AND timestamp BETWEEN ? AND ?
      ORDER BY timestamp ASC
    `;
    
    const [rows] = await db.execute(query, [deviceId, start, end]);
    
    res.json(rows);
  } catch (error) {
    console.error('Error fetching location history:', error);
    res.status(500).json({ message: 'Server error' });
  }
});

router.post('/:deviceId', authenticateLocationKey, async (req, res) => {
  try {
    const { deviceId } = req.params;
    const {
      latitude,
      longitude,
      altitude = null,
      accuracy = null,
      battery_level = null,
      address = null,
      timestamp = null
    } = req.body || {};

    if (!deviceId || latitude === undefined || longitude === undefined) {
      return res.status(400).json({ message: 'deviceId, latitude and longitude are required' });
    }

    const newLat = Number(latitude);
    const newLng = Number(longitude);

    if (Number.isNaN(newLat) || Number.isNaN(newLng)) {
      return res.status(400).json({ message: 'latitude and longitude must be valid numbers' });
    }

    const [[prev]] = await db.execute(
      `
        SELECT latitude, longitude, timestamp
        FROM device_locations
        WHERE device_id = ?
        ORDER BY timestamp DESC
        LIMIT 1
      `,
      [deviceId]
    );

    const effectiveTimestamp = timestamp || new Date();
    const newTimeMs = new Date(effectiveTimestamp).getTime();
    if (Number.isNaN(newTimeMs)) {
      return res.status(400).json({ message: 'timestamp must be a valid datetime' });
    }

    let calculatedSpeed = null;
    if (prev && prev.latitude !== null && prev.longitude !== null && prev.timestamp) {
      const prevLat = Number(prev.latitude);
      const prevLng = Number(prev.longitude);
      const prevTimeMs = new Date(prev.timestamp).getTime();

      if (!Number.isNaN(prevLat) && !Number.isNaN(prevLng) && !Number.isNaN(prevTimeMs)) {
        const dtSeconds = (newTimeMs - prevTimeMs) / 1000;
        if (dtSeconds > 0) {
          const distanceMeters = haversineDistanceMeters(prevLat, prevLng, newLat, newLng);
          calculatedSpeed = (distanceMeters / dtSeconds) * 3.6;
          if (!Number.isFinite(calculatedSpeed)) {
            calculatedSpeed = null;
          }
        }
      }
    }

    const insertQuery = `
      INSERT INTO device_locations
        (device_id, latitude, longitude, altitude, accuracy, speed, battery_level, address, timestamp, created_at)
      VALUES
        (?, ?, ?, ?, ?, ?, ?, ?, COALESCE(?, NOW()), NOW())
    `;

    await db.execute(insertQuery, [
      deviceId,
      newLat,
      newLng,
      altitude,
      accuracy,
      calculatedSpeed,
      battery_level,
      address,
      timestamp
    ]);

    return res.json({ message: 'success' });
  } catch (error) {
    console.error('Error inserting device location:', error);
    return res.status(500).json({ message: 'Server error' });
  }
});

module.exports = router;