const AuditLog = require('../models/AuditLog');
const logger = require('../utils/logger');

/**
 * Get all audit logs with pagination and filtering
 */
const getAuditLogs = async (req, res) => {
  try {
    const page = Math.max(1, parseInt(req.query.page) || 1);
    const limit = Math.min(100, Math.max(1, parseInt(req.query.limit) || 50));
    const skip = (page - 1) * limit;

    // Build filter
    const filter = {};
    if (req.query.action) {
      filter.action = req.query.action;
    }
    if (req.query.resource) {
      filter.resource = req.query.resource;
    }
    if (req.query.adminUsername) {
      filter.adminUsername = req.query.adminUsername;
    }
    if (req.query.success !== undefined) {
      filter.success = req.query.success === 'true';
    }
    
    // Date range filter
    if (req.query.startDate || req.query.endDate) {
      filter.createdAt = {};
      if (req.query.startDate) {
        filter.createdAt.$gte = new Date(req.query.startDate);
      }
      if (req.query.endDate) {
        filter.createdAt.$lte = new Date(req.query.endDate);
      }
    }

    const [logs, total] = await Promise.all([
      AuditLog.find(filter)
        .sort({ createdAt: -1 })
        .skip(skip)
        .limit(limit)
        .populate('adminId', 'username')
        .select('-__v'),
      AuditLog.countDocuments(filter)
    ]);

    res.json({
      success: true,
      data: logs,
      pagination: {
        page,
        limit,
        total,
        pages: Math.ceil(total / limit)
      }
    });
  } catch (error) {
    logger.error('Fehler beim Abrufen der Audit-Logs:', error);
    res.status(500).json({
      success: false,
      message: 'Fehler beim Abrufen der Audit-Logs'
    });
  }
};

/**
 * Get audit logs for a specific resource
 */
const getResourceAuditLogs = async (req, res) => {
  try {
    const { resource, resourceId } = req.params;

    const logs = await AuditLog.find({ resource, resourceId })
      .sort({ createdAt: -1 })
      .limit(50)
      .populate('adminId', 'username')
      .select('-__v');

    res.json({
      success: true,
      data: logs,
      count: logs.length
    });
  } catch (error) {
    logger.error('Fehler beim Abrufen der Resource-Audit-Logs:', error);
    res.status(500).json({
      success: false,
      message: 'Fehler beim Abrufen der Resource-Audit-Logs'
    });
  }
};

/**
 * Get admin activity summary
 */
const getAdminActivity = async (req, res) => {
  try {
    const { adminId } = req.params;

    const stats = await AuditLog.aggregate([
      { $match: { adminId: require('mongoose').Types.ObjectId(adminId) } },
      {
        $group: {
          _id: '$action',
          count: { $sum: 1 }
        }
      },
      { $sort: { count: -1 } }
    ]);

    const recentActivity = await AuditLog.find({ adminId })
      .sort({ createdAt: -1 })
      .limit(20)
      .select('-__v');

    res.json({
      success: true,
      data: {
        stats,
        recentActivity
      }
    });
  } catch (error) {
    logger.error('Fehler beim Abrufen der Admin-Aktivität:', error);
    res.status(500).json({
      success: false,
      message: 'Fehler beim Abrufen der Admin-Aktivität'
    });
  }
};

/**
 * Aggregate statistics: counts by action, resource, admin, success/fail, daily activity
 */
const getAuditStats = async (req, res) => {
  try {
    const days = Math.min(365, Math.max(1, parseInt(req.query.days) || 30));
    const since = new Date(Date.now() - days * 24 * 60 * 60 * 1000);

    const [byAction, byAdmin, byResource, bySuccess, dailyActivity] = await Promise.all([
      AuditLog.aggregate([
        { $match: { createdAt: { $gte: since } } },
        { $group: { _id: '$action', count: { $sum: 1 } } },
        { $sort: { count: -1 } }
      ]),
      AuditLog.aggregate([
        { $match: { createdAt: { $gte: since } } },
        { $group: { _id: '$adminUsername', count: { $sum: 1 } } },
        { $sort: { count: -1 } },
        { $limit: 10 }
      ]),
      AuditLog.aggregate([
        { $match: { createdAt: { $gte: since } } },
        { $group: { _id: '$resource', count: { $sum: 1 } } },
        { $sort: { count: -1 } }
      ]),
      AuditLog.aggregate([
        { $match: { createdAt: { $gte: since } } },
        { $group: { _id: '$success', count: { $sum: 1 } } }
      ]),
      AuditLog.aggregate([
        { $match: { createdAt: { $gte: since } } },
        { $group: {
          _id: { $dateToString: { format: '%Y-%m-%d', date: '$createdAt' } },
          count: { $sum: 1 },
          failed: { $sum: { $cond: [{ $eq: ['$success', false] }, 1, 0] } }
        }},
        { $sort: { _id: 1 } }
      ])
    ]);

    const total  = byAction.reduce((s, a) => s + a.count, 0);
    const failed = bySuccess.find(s => s._id === false)?.count || 0;

    res.json({
      success: true,
      data: {
        total,
        failed,
        days,
        since,
        byAction:      byAction.map(a => ({ action: a._id, count: a.count })),
        byAdmin:       byAdmin.map(a => ({ admin: a._id || 'unknown', count: a.count })),
        byResource:    byResource.map(a => ({ resource: a._id, count: a.count })),
        dailyActivity: dailyActivity.map(a => ({ date: a._id, count: a.count, failed: a.failed }))
      }
    });
  } catch (error) {
    logger.error('Fehler beim Abrufen der Audit-Statistiken:', error);
    res.status(500).json({ success: false, message: 'Fehler beim Abrufen der Audit-Statistiken' });
  }
};

/**
 * Export audit logs as CSV (respects same filters as getAuditLogs)
 */
const exportAuditLogs = async (req, res) => {
  try {
    const filter = {};
    if (req.query.action)        filter.action = req.query.action;
    if (req.query.resource)      filter.resource = req.query.resource;
    if (req.query.adminUsername) filter.adminUsername = req.query.adminUsername;
    if (req.query.success !== undefined) filter.success = req.query.success === 'true';
    if (req.query.startDate || req.query.endDate) {
      filter.createdAt = {};
      if (req.query.startDate) filter.createdAt.$gte = new Date(req.query.startDate);
      if (req.query.endDate)   filter.createdAt.$lte = new Date(req.query.endDate);
    }

    const logs = await AuditLog.find(filter)
      .sort({ createdAt: -1 })
      .limit(10000)
      .lean();

    const escapeCell = (val) => {
      if (val == null) return '';
      const str = String(val);
      return str.includes(',') || str.includes('"') || str.includes('\n')
        ? `"${str.replace(/"/g, '""')}"` : str;
    };

    const header = [
      'Zeitstempel', 'Aktion', 'Ressource', 'Ressourcen-Name', 'Admin',
      'IP-Adresse', 'Methode', 'Pfad', 'Status-Code', 'Dauer (ms)',
      'Erfolgreich', 'Fehlermeldung', 'Geänderte Felder', 'Metadaten'
    ].join(',');

    const rows = logs.map(log => [
      escapeCell(new Date(log.createdAt).toLocaleString('de-DE')),
      escapeCell(log.action),
      escapeCell(log.resource),
      escapeCell(log.resourceName),
      escapeCell(log.adminUsername),
      escapeCell(log.ipAddress),
      escapeCell(log.requestMethod),
      escapeCell(log.requestPath),
      escapeCell(log.statusCode),
      escapeCell(log.duration),
      log.success ? 'Ja' : 'Nein',
      escapeCell(log.errorMessage),
      escapeCell(log.changes ? Object.keys(log.changes).join(', ') : ''),
      escapeCell(log.metadata ? JSON.stringify(log.metadata) : '')
    ].join(','));

    const filename = `audit-logs_${new Date().toISOString().slice(0, 10)}.csv`;
    res.setHeader('Content-Type', 'text/csv; charset=utf-8');
    res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
    res.send('\uFEFF' + [header, ...rows].join('\n'));
  } catch (error) {
    logger.error('Fehler beim Exportieren der Audit-Logs:', error);
    res.status(500).json({ success: false, message: 'Fehler beim Exportieren der Audit-Logs' });
  }
};

module.exports = {
  getAuditLogs,
  getResourceAuditLogs,
  getAdminActivity,
  getAuditStats,
  exportAuditLogs
};
