/**
 * Audit Controller
 * Exposes audit logs to administrators for monitoring and incident response.
 */

const express = require('express');
const router = express.Router();
const path = require('path');
const Database = require('better-sqlite3');

const dbPath = process.env.DB_PATH || path.join(__dirname, '../../data/school.db');
const db = new Database(dbPath);
db.pragma('foreign_keys = ON');

// Auth middleware
const auth = (req, res, next) => {
  const token = req.headers.authorization?.split(' ')[1];
  if (!token) return res.status(401).json({ error: 'No token provided' });
  try {
    const jwt = require('jsonwebtoken');
    const { jwtSecret: JWT_SECRET } = require('../config');
    req.user = jwt.verify(token, JWT_SECRET);
    next();
  } catch (err) {
    res.status(401).json({ error: 'Invalid token' });
  }
};

// Admin only middleware (matches the "Administrator access required"
// contract: systems_admin or school_admin only, principal intentionally
// excluded because audit logs surface privileged data).
const { requireStrictAdmin: adminOnly } = require('../middleware/requireRole');

/**
 * @openapi
 * /api/audit:
 *   get:
 *     summary: List audit log entries
 *     description: |
 *       Returns paginated audit logs. Only accessible to `school_admin` or
 *       `systems_admin`. Supports filtering by user, action, entity type,
 *       and date range.
 *     tags:
 *       - Audit
 *     security:
 *       - bearerAuth: []
 *     parameters:
 *       - in: query
 *         name: user_email
 *         schema:
 *           type: string
 *         description: Substring match on actor email
 *       - in: query
 *         name: action
 *         schema:
 *           type: string
 *         description: Exact action name (e.g. `LOGIN`, `REGISTER_USER`, `UPDATE_USER`)
 *       - in: query
 *         name: entity_type
 *         schema:
 *           type: string
 *         description: Entity name filter (e.g. `user`, `payment`)
 *       - in: query
 *         name: start_date
 *         schema:
 *           type: string
 *           format: date-time
 *       - in: query
 *         name: end_date
 *         schema:
 *           type: string
 *           format: date-time
 *       - in: query
 *         name: limit
 *         schema:
 *           type: integer
 *           default: 100
 *       - in: query
 *         name: offset
 *         schema:
 *           type: integer
 *           default: 0
 *     responses:
 *       200:
 *         description: Paginated audit log entries
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 logs:
 *                   type: array
 *                   items:
 *                     type: object
 *                 pagination:
 *                   type: object
 *                   properties:
 *                     total: { type: integer }
 *                     limit: { type: integer }
 *                     offset: { type: integer }
 *       401: { description: Unauthorized }
 *       403: { description: Admin role required }
 */
router.get('/', auth, adminOnly, (req, res) => {
  const { user_email, action, entity_type, start_date, end_date, limit = 100, offset = 0 } = req.query;
  
  let query = 'SELECT * FROM audit_logs WHERE 1=1';
  const params = [];
  
  if (user_email) {
    query += ' AND user_email LIKE ?';
    params.push(`%${user_email}%`);
  }
  
  if (action) {
    query += ' AND action = ?';
    params.push(action);
  }
  
  if (entity_type) {
    query += ' AND entity_type = ?';
    params.push(entity_type);
  }
  
  if (start_date) {
    query += ' AND created_at >= ?';
    params.push(start_date);
  }
  
  if (end_date) {
    query += ' AND created_at <= ?';
    params.push(end_date);
  }
  
  query += ' ORDER BY created_at DESC LIMIT ? OFFSET ?';
  params.push(parseInt(limit), parseInt(offset));
  
  try {
    const logs = db.prepare(query).all(...params);
    
    // Get total count for pagination
    let countQuery = 'SELECT COUNT(*) as total FROM audit_logs WHERE 1=1';
    const countParams = params.slice(0, -2); // Remove limit and offset
    
    if (user_email) countQuery += ' AND user_email LIKE ?';
    if (action) countQuery += ' AND action = ?';
    if (entity_type) countQuery += ' AND entity_type = ?';
    if (start_date) countQuery += ' AND created_at >= ?';
    if (end_date) countQuery += ' AND created_at <= ?';
    
    const total = db.prepare(countQuery).get(...countParams).total;
    
    res.json({
      logs,
      pagination: {
        total,
        limit: parseInt(limit),
        offset: parseInt(offset)
      }
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

/**
 * @openapi
 * /api/audit/{id}:
 *   get:
 *     summary: Get a single audit log entry
 *     description: Returns one audit log entry by numeric id, with `old_data` and `new_data` JSON-decoded.
 *     tags:
 *       - Audit
 *     security:
 *       - bearerAuth: []
 *     parameters:
 *       - in: path
 *         name: id
 *         required: true
 *         schema:
 *           type: integer
 *     responses:
 *       200:
 *         description: Audit log entry
 *       401: { description: Unauthorized }
 *       403: { description: Admin role required }
 *       404: { description: Audit log not found }
 */
router.get('/:id', auth, adminOnly, (req, res) => {
  try {
    const log = db.prepare('SELECT * FROM audit_logs WHERE id = ?').get(req.params.id);
    if (!log) return res.status(404).json({ error: 'Audit log not found' });
    
    // Parse JSON data for easier consumption
    if (log.old_data) log.old_data = JSON.parse(log.old_data);
    if (log.new_data) log.new_data = JSON.parse(log.new_data);
    
    res.json(log);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

module.exports = router;
