<?php
/**
 * RegistrationLogger - Centralized logging system for registration-related activities
 * Provides comprehensive audit trail for all registration management operations
 */

class RegistrationLogger {
    private $conn;
    private $userId;
    private $userName;
    private $userRole;
    private $ipAddress;
    private $userAgent;
    private $sessionId;
    
    public function __construct($database, $user = null) {
        $this->conn = $database;
        
        if ($user) {
            $this->userId = $user['id'];
            $this->userName = $user['name'] ?? $user['username'] ?? 'Unknown';
            $this->userRole = $user['role'] ?? 'user';
        }
        
        $this->ipAddress = $_SERVER['REMOTE_ADDR'] ?? null;
        $this->userAgent = $_SERVER['HTTP_USER_AGENT'] ?? null;
        $this->sessionId = session_id() ?: null;
    }
    
    
    /**
     * Log payment status changes
     */
    public function logPaymentStatusUpdate($registrationId, $registrationNumber, $oldStatus, $newStatus, $totalAmount) {
        $statusText = ucfirst($newStatus);
        $description = "Payment status changed from '{$oldStatus}' to '{$newStatus}' for registration {$registrationNumber} (\${$totalAmount})";
        
        // Determine severity based on status change
        $severity = 'medium';
        if ($newStatus === 'paid' && $oldStatus !== 'paid') {
            $severity = 'high'; // Payment confirmation is important
        } elseif ($newStatus === 'failed' || $newStatus === 'expired') {
            $severity = 'medium';
        }
        
        return $this->log([
            'activity_type' => 'payment_status_update',
            'registration_id' => $registrationId,
            'action_description' => $description,
            'old_values' => json_encode(['payment_status' => $oldStatus]),
            'new_values' => json_encode(['payment_status' => $newStatus, 'amount' => $totalAmount]),
            'severity' => $severity,
            'tags' => json_encode(['payment', 'status', 'admin_update'])
        ]);
    }
    
    /**
     * Log stock confirmation when payment is marked as paid
     */
    public function logStockConfirmation($registrationId, $registrationNumber, $confirmedCount) {
        return $this->log([
            'activity_type' => 'stock_confirmation',
            'registration_id' => $registrationId,
            'action_description' => "Auto-confirmed {$confirmedCount} product stock items for registration {$registrationNumber}",
            'new_values' => json_encode(['confirmed_items' => $confirmedCount]),
            'affected_count' => $confirmedCount,
            'severity' => 'medium',
            'tags' => json_encode(['stock', 'confirmation', 'auto'])
        ]);
    }
    
    /**
     * Log contact information updates
     */
    public function logContactUpdate($registrationId, $registrationNumber, $oldData, $newData) {
        $changes = $this->getChanges($oldData, $newData);
        $changeDescription = $this->formatChanges($changes);
        
        return $this->log([
            'activity_type' => 'contact_update',
            'registration_id' => $registrationId,
            'action_description' => "Updated contact information for registration {$registrationNumber}: {$changeDescription}",
            'old_values' => json_encode($oldData),
            'new_values' => json_encode($newData),
            'severity' => 'medium',
            'tags' => json_encode(['contact', 'update', 'personal_data'])
        ]);
    }
    
    /**
     * Log admin notes updates
     */
    public function logAdminNotesUpdate($registrationId, $registrationNumber, $oldNotes, $newNotes) {
        $hasOldNotes = !empty(trim($oldNotes));
        $hasNewNotes = !empty(trim($newNotes));
        
        if (!$hasOldNotes && $hasNewNotes) {
            $action = "Added admin notes";
        } elseif ($hasOldNotes && !$hasNewNotes) {
            $action = "Removed admin notes";
        } else {
            $action = "Updated admin notes";
        }
        
        return $this->log([
            'activity_type' => 'admin_notes_update',
            'registration_id' => $registrationId,
            'action_description' => "{$action} for registration {$registrationNumber}",
            'old_values' => json_encode(['admin_notes' => $oldNotes]),
            'new_values' => json_encode(['admin_notes' => $newNotes]),
            'severity' => 'low',
            'tags' => json_encode(['admin_notes', 'update', 'documentation'])
        ]);
    }
    
    /**
     * Log email sending operations
     */
    public function logEmailSent($registrationId, $registrationNumber, $emailType, $recipient, $subject, $emailLogId = null) {
        $emailTypeNames = [
            'pending_registration' => 'Pending Registration',
            'registration_confirmation' => 'Registration Confirmation',
            'payment_failure' => 'Payment Failed',
            'payment_reminder_24h' => 'Payment Reminder (24h)',
            'payment_reminder_48h' => 'Payment Reminder (48h)',
            'payment_reminder_7d' => 'Payment Reminder (7 days)',
            'admin_notification' => 'Admin Notification'
        ];
        
        $emailTypeName = $emailTypeNames[$emailType] ?? ucwords(str_replace('_', ' ', $emailType));
        
        return $this->log([
            'activity_type' => 'email_sent',
            'registration_id' => $registrationId,
            'email_log_id' => $emailLogId,
            'action_description' => "Sent {$emailTypeName} email to {$recipient} for registration {$registrationNumber}",
            'new_values' => json_encode([
                'email_type' => $emailType,
                'recipient' => $recipient,
                'subject' => $subject
            ]),
            'severity' => 'low',
            'tags' => json_encode(['email', 'sent', $emailType])
        ]);
    }
    
    /**
     * Log email resending operations
     */
    public function logEmailResent($registrationId, $registrationNumber, $emailType, $recipient, $originalEmailId) {
        $emailTypeNames = [
            'pending_registration' => 'Pending Registration',
            'registration_confirmation' => 'Registration Confirmation',
            'payment_failure' => 'Payment Failed',
            'payment_reminder_24h' => 'Payment Reminder (24h)',
            'payment_reminder_48h' => 'Payment Reminder (48h)',
            'payment_reminder_7d' => 'Payment Reminder (7 days)',
            'admin_notification' => 'Admin Notification'
        ];
        
        $emailTypeName = $emailTypeNames[$emailType] ?? ucwords(str_replace('_', ' ', $emailType));
        
        return $this->log([
            'activity_type' => 'email_resent',
            'registration_id' => $registrationId,
            'email_log_id' => $originalEmailId,
            'action_description' => "Resent {$emailTypeName} email to {$recipient} for registration {$registrationNumber}",
            'new_values' => json_encode([
                'email_type' => $emailType,
                'recipient' => $recipient,
                'original_email_id' => $originalEmailId
            ]),
            'severity' => 'medium',
            'tags' => json_encode(['email', 'resent', $emailType])
        ]);
    }
    
    /**
     * Log email failures
     */
    public function logEmailFailure($registrationId, $registrationNumber, $emailType, $recipient, $errorMessage) {
        $emailTypeNames = [
            'pending_registration' => 'Pending Registration',
            'registration_confirmation' => 'Registration Confirmation',
            'payment_failure' => 'Payment Failed',
            'payment_reminder_24h' => 'Payment Reminder (24h)',
            'payment_reminder_48h' => 'Payment Reminder (48h)',
            'payment_reminder_7d' => 'Payment Reminder (7 days)',
            'admin_notification' => 'Admin Notification'
        ];
        
        $emailTypeName = $emailTypeNames[$emailType] ?? ucwords(str_replace('_', ' ', $emailType));
        
        return $this->log([
            'activity_type' => 'email_failure',
            'registration_id' => $registrationId,
            'action_description' => "Failed to send {$emailTypeName} email to {$recipient} for registration {$registrationNumber}: {$errorMessage}",
            'new_values' => json_encode([
                'email_type' => $emailType,
                'recipient' => $recipient,
                'error_message' => $errorMessage
            ]),
            'severity' => 'high',
            'tags' => json_encode(['email', 'failure', $emailType])
        ]);
    }
    
    /**
     * Log invoice generation
     */
    public function logInvoiceGeneration($registrationId, $registrationNumber, $invoiceType = 'admin') {
        $typeText = $invoiceType === 'public' ? 'Public invoice' : 'Admin invoice';
        
        return $this->log([
            'activity_type' => 'invoice_generation',
            'registration_id' => $registrationId,
            'action_description' => "{$typeText} generated for registration {$registrationNumber}",
            'new_values' => json_encode(['invoice_type' => $invoiceType]),
            'severity' => 'low',
            'tags' => json_encode(['invoice', 'generation', $invoiceType])
        ]);
    }
    
    /**
     * Log data export operations
     */
    public function logDataExport($registrationId, $registrationNumber, $exportType, $exportFormat = 'pdf') {
        return $this->log([
            'activity_type' => 'data_export',
            'registration_id' => $registrationId,
            'action_description' => "Exported {$exportType} data for registration {$registrationNumber} ({$exportFormat})",
            'new_values' => json_encode([
                'export_type' => $exportType,
                'format' => $exportFormat
            ]),
            'severity' => 'low',
            'tags' => json_encode(['export', $exportType, $exportFormat])
        ]);
    }
    
    /**
     * Log delegate information updates
     */
    public function logDelegateUpdate($registrationId, $registrationNumber, $delegateId, $oldData, $newData) {
        $changes = $this->getChanges($oldData, $newData);
        $changeDescription = $this->formatChanges($changes);
        
        return $this->log([
            'activity_type' => 'delegate_update',
            'registration_id' => $registrationId,
            'delegate_id' => $delegateId,
            'action_description' => "Updated delegate information for registration {$registrationNumber}: {$changeDescription}",
            'old_values' => json_encode($oldData),
            'new_values' => json_encode($newData),
            'severity' => 'medium',
            'tags' => json_encode(['delegate', 'update', 'personal_data'])
        ]);
    }
    
    /**
     * Log bulk operations on registrations
     */
    public function logBulkOperation($operationType, $affectedCount, $description, $registrationIds = []) {
        return $this->log([
            'activity_type' => 'bulk_operation',
            'action_description' => $description,
            'new_values' => json_encode(['registration_ids' => $registrationIds]),
            'affected_count' => $affectedCount,
            'severity' => 'high',
            'tags' => json_encode(['bulk', $operationType])
        ]);
    }
    
    /**
     * Log registration deletion
     */
    public function logRegistrationDeletion($registrationId, $registrationNumber, $contactEmail, $totalAmount) {
        return $this->log([
            'activity_type' => 'registration_deletion',
            'registration_id' => $registrationId,
            'action_description' => "Deleted registration {$registrationNumber} (Contact: {$contactEmail}, Amount: \${$totalAmount})",
            'old_values' => json_encode([
                'registration_number' => $registrationNumber,
                'contact_email' => $contactEmail,
                'total_amount' => $totalAmount
            ]),
            'severity' => 'high',
            'tags' => json_encode(['registration', 'deletion', 'admin_action'])
        ]);
    }

    /**
     * Log system events related to registrations
     */
    public function logSystemEvent($eventType, $registrationId, $registrationNumber, $description, $severity = 'medium') {
        return $this->log([
            'activity_type' => 'system_event',
            'registration_id' => $registrationId,
            'action_description' => "System event for registration {$registrationNumber}: {$description}",
            'new_values' => json_encode(['event_type' => $eventType]),
            'severity' => $severity,
            'tags' => json_encode(['system', $eventType])
        ]);
    }
    
    /**
     * Core logging method
     */
    private function log($data) {
        try {
            $sql = "INSERT INTO registration_activity_log (
                activity_type, registration_id, delegate_id, payment_transaction_id, email_log_id,
                user_id, user_name, user_role, action_description, old_values, new_values,
                ip_address, user_agent, session_id, affected_count, severity, tags
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
            
            $stmt = $this->conn->prepare($sql);
            return $stmt->execute([
                $data['activity_type'],
                $data['registration_id'] ?? null,
                $data['delegate_id'] ?? null,
                $data['payment_transaction_id'] ?? null,
                $data['email_log_id'] ?? null,
                $this->userId,
                $this->userName,
                $this->userRole,
                $data['action_description'],
                $data['old_values'] ?? null,
                $data['new_values'] ?? null,
                $this->ipAddress,
                $this->userAgent,
                $this->sessionId,
                $data['affected_count'] ?? 1,
                $data['severity'] ?? 'medium',
                $data['tags'] ?? null
            ]);
        } catch (Exception $e) {
            error_log("RegistrationLogger Error: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Get recent activities
     */
    public function getRecentActivities($limit = 50, $filters = []) {
        $sql = "SELECT * FROM recent_registration_activities WHERE 1=1";
        $params = [];
        
        if (!empty($filters['activity_type'])) {
            $sql .= " AND activity_type = ?";
            $params[] = $filters['activity_type'];
        }
        
        if (!empty($filters['registration_id'])) {
            $sql .= " AND registration_id = ?";
            $params[] = $filters['registration_id'];
        }
        
        if (!empty($filters['user_id'])) {
            $sql .= " AND user_id = ?";
            $params[] = $filters['user_id'];
        }
        
        if (!empty($filters['severity'])) {
            $sql .= " AND severity = ?";
            $params[] = $filters['severity'];
        }
        
        if (!empty($filters['date_from'])) {
            $sql .= " AND created_at >= ?";
            $params[] = $filters['date_from'];
        }
        
        if (!empty($filters['date_to'])) {
            $sql .= " AND created_at <= ?";
            $params[] = $filters['date_to'];
        }
        
        $sql .= " ORDER BY created_at DESC LIMIT ?";
        $params[] = $limit;
        
        $stmt = $this->conn->prepare($sql);
        $stmt->execute($params);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    
    /**
     * Get activity statistics
     */
    public function getActivityStats($registrationId = null, $days = 30) {
        $sql = "SELECT 
                    activity_type,
                    COUNT(*) as count,
                    MAX(created_at) as last_activity
                FROM registration_activity_log 
                WHERE created_at >= DATE_SUB(NOW(), INTERVAL ? DAY)";
        
        $params = [$days];
        
        if ($registrationId) {
            $sql .= " AND registration_id = ?";
            $params[] = $registrationId;
        }
        
        $sql .= " GROUP BY activity_type ORDER BY count DESC";
        
        $stmt = $this->conn->prepare($sql);
        $stmt->execute($params);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    
    /**
     * Helper methods
     */
    private function getChanges($oldData, $newData) {
        $changes = [];
        foreach ($newData as $key => $value) {
            if (!isset($oldData[$key]) || $oldData[$key] != $value) {
                $changes[$key] = [
                    'old' => $oldData[$key] ?? null,
                    'new' => $value
                ];
            }
        }
        return $changes;
    }
    
    private function formatChanges($changes) {
        $formatted = [];
        foreach ($changes as $field => $change) {
            $oldVal = $change['old'] ?: '(empty)';
            $newVal = $change['new'] ?: '(empty)';
            $formatted[] = "{$field}: '{$oldVal}' → '{$newVal}'";
        }
        return implode(', ', $formatted);
    }
    
    /**
     * Log product changes for registrations
     */
    public function logProductChange($registrationId, $registrationNumber, $registrationProductId, $changeDetails) {
        $oldProduct = $changeDetails['old_product'];
        $newProduct = $changeDetails['new_product'];
        $priceDifference = $changeDetails['price_difference'];
        $reason = $changeDetails['reason'];
        
        $description = "Product changed for registration {$registrationNumber}: " .
                      "'{$oldProduct['name']}' (Qty: {$oldProduct['quantity']}, \${$oldProduct['total_price']}) " .
                      "→ '{$newProduct['name']}' (Qty: {$newProduct['quantity']}, \${$newProduct['total_price']})";
        
        if ($priceDifference != 0) {
            $diffText = $priceDifference > 0 ? "+\${$priceDifference}" : "-\$" . abs($priceDifference);
            $description .= " | Price difference: {$diffText}";
        }
        
        $description .= " | Reason: {$reason}";
        
        return $this->log([
            'activity_type' => 'product_change',
            'registration_id' => $registrationId,
            'action_description' => $description,
            'old_values' => json_encode($oldProduct),
            'new_values' => json_encode($newProduct),
            'metadata' => json_encode([
                'registration_product_id' => $registrationProductId,
                'price_difference' => $priceDifference,
                'reason' => $reason,
                'category' => $oldProduct['category']
            ]),
            'severity' => 'medium',
            'tags' => json_encode(['product_change', 'bank_transfer', 'admin_action'])
        ]);
    }
}
