const express = require('express');
const cors = require('cors');
const { PrismaClient } = require('@prisma/client');
const http = require('http');
const { Server } = require('socket.io');

const app = express();
const prisma = new PrismaClient();

app.use(cors());
app.use(express.json());

const server = http.createServer(app);
const io = new Server(server, {
  cors: {
    origin: "*",
    methods: ["GET", "POST"]
  }
});

// Hello World
app.get('/', (req, res) => {
  res.send('ALPR Backend Running');
});

// Plates CRUD
app.get('/api/plates', async (req, res) => {
  try {
    const plates = await prisma.plate.findMany();
    res.json(plates);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.post('/api/plates', async (req, res) => {
  const { number, owner, status } = req.body;
  try {
    const plate = await prisma.plate.create({
      data: { number, owner, status: status || 'ALLOWED' }
    });
    res.json(plate);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

// History Endpoint
app.get('/api/history', async (req, res) => {
  const { date } = req.query; // Format: YYYY-MM-DD
  if (!date) {
    return res.status(400).json({ error: 'Date is required' });
  }

  const startDate = new Date(date);
  startDate.setHours(0, 0, 0, 0);

  const endDate = new Date(date);
  endDate.setHours(23, 59, 59, 999);

  try {
    const logs = await prisma.accessLog.findMany({
      where: {
        timestamp: {
          gte: startDate,
          lte: endDate
        }
      },
      orderBy: {
        timestamp: 'desc'
      }
    });
    res.json(logs);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

// Recent Scans Endpoint (Last 5 Hours)
app.get('/api/recent', async (req, res) => {
  try {
    const fiveHoursAgo = new Date(Date.now() - 5 * 60 * 60 * 1000);
    const logs = await prisma.accessLog.findMany({
      where: {
        timestamp: {
          gte: fiveHoursAgo
        }
      },
      orderBy: {
        timestamp: 'desc'
      }
    });
    res.json(logs);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

// Detection Endpoint (from Python)
app.post('/api/detect', async (req, res) => {
  const { plate_number } = req.body;
  console.log(`Detected: ${plate_number}`);

  const DUPLICATE_COOLDOWN_MS = 30000; // 30 seconds

  try {
    // Check for recent duplicate
    const lastLog = await prisma.accessLog.findFirst({
      where: { plateNumber: plate_number },
      orderBy: { timestamp: 'desc' }
    });

    if (lastLog) {
      const timeDiff = new Date() - new Date(lastLog.timestamp);
      if (timeDiff < DUPLICATE_COOLDOWN_MS) {
        console.log(`Duplicate detection ignored for ${plate_number} (${timeDiff}ms since last)`);
        return res.json({ message: 'Duplicate detection ignored', ignored: true, accessStatus: lastLog.accessStatus });
      }
    }

    // Check if plate exists
    let plate = await prisma.plate.findUnique({
      where: { number: plate_number }
    });

    let accessStatus = 'DENIED';

    if (plate && plate.status === 'ALLOWED') {
      accessStatus = 'GRANTED';
    }

    if (!plate) {
      // Optional: Auto-create unknown plates?
      // For now, treat as UNKNOWN (Denied)
      accessStatus = 'UNKNOWN';
    }

    // Log the access attempt
    const log = await prisma.accessLog.create({
      data: {
        plateNumber: plate_number,
        accessStatus,
        timestamp: new Date()
      }
    });

    // Notify Frontend via WebSocket
    io.emit('new_detection', {
      plate: plate_number,
      status: accessStatus,
      timestamp: log.timestamp
    });

    res.json({ message: 'Processed', accessStatus });

  } catch (err) {
    console.error(err);
    res.status(500).json({ error: err.message });
  }
});

const PORT = process.env.PORT || 3000;
server.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});
