import { Response } from 'express';
import prisma from '../lib/prisma.js';
import { AuthRequest, ApiResponse } from '../types/index.js';
import * as appSettingService from '../services/appSetting.service.js';
import { sendAlertEmail, sendDigest } from '../services/securityAlert.service.js';
import type { SecurityEventType, SecuritySeverity } from '@prisma/client';

/**
 * GET /api/monitoring/events
 * Liste der Security-Events mit Filter + Pagination.
 */
export async function listEvents(req: AuthRequest, res: Response): Promise<void> {
  try {
    const page = parseInt((req.query.page as string) || '1');
    const limit = Math.min(parseInt((req.query.limit as string) || '50'), 200);
    const type = req.query.type as SecurityEventType | undefined;
    const severity = req.query.severity as SecuritySeverity | undefined;
    const search = req.query.search as string | undefined;
    const since = req.query.since as string | undefined;
    const ip = req.query.ip as string | undefined;

    const where: any = {};
    if (type) where.type = type;
    if (severity) where.severity = severity;
    if (ip) where.ipAddress = ip;
    if (since) where.createdAt = { gte: new Date(since) };
    if (search) {
      where.OR = [
        { message: { contains: search } },
        { userEmail: { contains: search } },
        { endpoint: { contains: search } },
      ];
    }

    const [events, total, byType, bySeverity] = await Promise.all([
      prisma.securityEvent.findMany({
        where,
        orderBy: { createdAt: 'desc' },
        take: limit,
        skip: (page - 1) * limit,
      }),
      prisma.securityEvent.count({ where }),
      prisma.securityEvent.groupBy({
        by: ['type'],
        where: since ? { createdAt: { gte: new Date(since) } } : {},
        _count: true,
      }),
      prisma.securityEvent.groupBy({
        by: ['severity'],
        where: since ? { createdAt: { gte: new Date(since) } } : {},
        _count: true,
      }),
    ]);

    res.json({
      success: true,
      data: events,
      pagination: { page, limit, total, totalPages: Math.ceil(total / limit) },
      stats: {
        byType: Object.fromEntries(byType.map((r: any) => [r.type, r._count])),
        bySeverity: Object.fromEntries(bySeverity.map((r: any) => [r.severity, r._count])),
      },
    } as any);
  } catch (error) {
    console.error('listEvents error:', error);
    res.status(500).json({ success: false, error: 'Fehler beim Laden der Security-Events' } as ApiResponse);
  }
}

/**
 * GET /api/monitoring/settings
 */
export async function getMonitoringSettings(_req: AuthRequest, res: Response): Promise<void> {
  try {
    const alertEmail = await appSettingService.getSetting('monitoringAlertEmail');
    const digestEnabled = await appSettingService.getSettingBool('monitoringDigestEnabled');
    const lastDigest = await appSettingService.getSetting('monitoringLastDigestAt');
    res.json({
      success: true,
      data: {
        alertEmail: alertEmail || '',
        digestEnabled,
        lastDigestAt: lastDigest || null,
      },
    } as ApiResponse);
  } catch (error) {
    res.status(500).json({ success: false, error: 'Fehler beim Laden' } as ApiResponse);
  }
}

/**
 * PUT /api/monitoring/settings
 */
export async function updateMonitoringSettings(req: AuthRequest, res: Response): Promise<void> {
  try {
    const { alertEmail, digestEnabled } = req.body || {};
    if (typeof alertEmail === 'string') {
      // Email-Validierung minimal: muss @ enthalten oder leer sein
      if (alertEmail !== '' && !alertEmail.includes('@')) {
        res.status(400).json({ success: false, error: 'Ungültige E-Mail-Adresse' } as ApiResponse);
        return;
      }
      await appSettingService.setSetting('monitoringAlertEmail', alertEmail);
    }
    if (typeof digestEnabled === 'boolean') {
      await appSettingService.setSetting('monitoringDigestEnabled', digestEnabled ? 'true' : 'false');
    }
    res.json({ success: true, message: 'Einstellungen gespeichert' } as ApiResponse);
  } catch (error) {
    res.status(500).json({ success: false, error: 'Fehler beim Speichern' } as ApiResponse);
  }
}

/**
 * POST /api/monitoring/test-alert
 * Versendet eine Test-Alert-Mail an die konfigurierte Adresse.
 */
export async function testAlert(_req: AuthRequest, res: Response): Promise<void> {
  try {
    const alertEmail = await appSettingService.getSetting('monitoringAlertEmail');
    if (!alertEmail) {
      res.status(400).json({
        success: false,
        error: 'Keine Alert-E-Mail konfiguriert',
      } as ApiResponse);
      return;
    }
    const result = await sendAlertEmail(alertEmail, {
      subject: '[OpenCRM] Test-Alert',
      events: [{
        type: 'SUSPICIOUS' as any,
        severity: 'INFO' as any,
        message: 'Dies ist eine Test-Mail vom Monitoring-System. Alles in Ordnung.',
        createdAt: new Date(),
      } as any],
      isDigest: false,
    });
    if (result.success) {
      res.json({ success: true, message: `Test-Alert an ${alertEmail} versendet` } as ApiResponse);
    } else {
      res.status(500).json({ success: false, error: result.error || 'Versand fehlgeschlagen' } as ApiResponse);
    }
  } catch (error) {
    res.status(500).json({
      success: false,
      error: error instanceof Error ? error.message : 'Test-Alert fehlgeschlagen',
    } as ApiResponse);
  }
}

/**
 * DELETE /api/monitoring/events
 * Löscht alle SecurityEvents (oder optional nur älter als ?olderThanDays).
 * Alert-versendete CRITICAL-Events werden vorher noch geloggt, damit der
 * Audit-Trail erhalten bleibt.
 */
export async function clearEvents(req: AuthRequest, res: Response): Promise<void> {
  try {
    const olderThanDays = req.query.olderThanDays
      ? parseInt(req.query.olderThanDays as string)
      : undefined;

    const where: any = {};
    if (olderThanDays && olderThanDays > 0) {
      const cutoff = new Date(Date.now() - olderThanDays * 24 * 60 * 60 * 1000);
      where.createdAt = { lt: cutoff };
    }

    const result = await prisma.securityEvent.deleteMany({ where });

    // Audit-Spur: Wer hat geleert
    const user = (req as any).user;
    await prisma.securityEvent.create({
      data: {
        type: 'PERMISSION_CHANGED',
        severity: 'INFO',
        message: `Security-Log geleert: ${result.count} Einträge gelöscht${olderThanDays ? ` (älter als ${olderThanDays} Tage)` : ''}`,
        userId: user?.userId || null,
        userEmail: user?.email || null,
        ipAddress: req.ip || 'unknown',
        endpoint: 'DELETE /api/monitoring/events',
      },
    });

    res.json({
      success: true,
      message: `${result.count} Events gelöscht`,
      data: { deletedCount: result.count },
    } as any);
  } catch (error) {
    console.error('clearEvents error:', error);
    res.status(500).json({ success: false, error: 'Löschen fehlgeschlagen' } as ApiResponse);
  }
}

/**
 * POST /api/monitoring/run-digest (manueller Trigger für den Hourly-Digest)
 */
export async function runDigestNow(_req: AuthRequest, res: Response): Promise<void> {
  try {
    const result = await sendDigest({ force: true });
    res.json({ success: true, data: result } as ApiResponse);
  } catch (error) {
    res.status(500).json({
      success: false,
      error: error instanceof Error ? error.message : 'Digest fehlgeschlagen',
    } as ApiResponse);
  }
}
