/**
 * Audit Service
 * Centralized logging for all user activities and system events.
 */

const Database = require('better-sqlite3');
const { v4: uuidv4 } = require('uuid');
const path = require('path');

const dbPath = process.env.DB_PATH || path.join(__dirname, '../../data/school.db');
let db;

const getDb = () => {
  if (!db) {
    db = new Database(dbPath);
    db.pragma('foreign_keys = ON');
  }
  return db;
};

class AuditService {
  /**
   * Log an action to the audit_logs table.
   * 
   * @param {Object} req - Express request object (optional, for extracting user and metadata)
   * @param {string} action - The action being performed (e.g., 'LOGIN', 'CREATE_USER', 'UPDATE_PAYMENT')
   * @param {Object} details - Additional details for the log
   * @param {string} details.entityType - Type of entity affected (e.g., 'user', 'payment', 'inventory')
   * @param {string} details.entityId - ID or UID of the entity affected
   * @param {Object} details.oldData - Previous state of the data
   * @param {Object} details.newData - New state of the data
   * @param {number} details.userId - Override for user_id (if req is not provided)
   * @param {string} details.userEmail - Override for user_email (if req is not provided)
   */
  static async log(req, action, details = {}) {
    const { entityType, entityId, oldData, newData, userId, userEmail, db: passedDb } = details;
    const db = passedDb || getDb();
    const uid = uuidv4();

    // Extract user info
    const finalUserId = userId || req?.user?.id || null;
    const finalUserEmail = userEmail || req?.user?.email || null;

    // Extract metadata
    const ipAddress = req?.ip || req?.headers?.['x-forwarded-for'] || null;
    const userAgent = req?.headers?.['user-agent'] || null;

    try {
      db.prepare(`
        INSERT INTO audit_logs (
          uid, user_id, user_email, action, entity_type, entity_id, 
          old_data, new_data, ip_address, user_agent
        )
        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
      `).run(
        uid,
        finalUserId,
        finalUserEmail,
        action,
        entityType || null,
        entityId || null,
        oldData ? JSON.stringify(oldData) : null,
        newData ? JSON.stringify(newData) : null,
        ipAddress,
        userAgent
      );
    } catch (error) {
      console.error('Failed to write audit log:', error);
    }
  }

  /**
   * Specifically log a login attempt.
   */
  static async logLogin(req, success, email) {
    const action = success ? 'LOGIN_SUCCESS' : 'LOGIN_FAILED';
    await this.log(req, action, {
      userEmail: email,
      entityType: 'auth',
      newData: success ? { status: 'success' } : { status: 'failed', reason: 'Invalid credentials' }
    });
  }
}

module.exports = AuditService;
