<?php
/**
 * Email Service Class
 * Handles email sending, templating, and queue management
 */

require_once 'config/email.php';

class EmailService {
    private $config;
    private $conn;
    private $templates;
    
    public function __construct() {
        global $conn;
        $this->conn = $conn;
        $this->config = new EmailConfig();
        $this->templates = [];
    }
    
    /**
     * Send email using PHPMailer-like functionality
     */
    public function sendEmail($to, $subject, $body, $isHTML = true, $attachments = [], $replyTo = null) {
        try {
            if (!$this->config->isEnabled()) {
                throw new Exception("Email service is disabled");
            }
            
            $this->config->validate();
            
            // Log email attempt
            $logId = $this->logEmail($to, $subject, 'pending');
            
            // Check rate limit
            if (!$this->checkRateLimit()) {
                throw new Exception("Rate limit exceeded");
            }
            
            // Prepare email data
            $emailData = [
                'to' => $to,
                'subject' => $subject,
                'body' => $body,
                'isHTML' => $isHTML,
                'attachments' => $attachments,
                'replyTo' => $replyTo
            ];
            
            // Send email
            $result = $this->sendEmailDirect($emailData);
            
            if ($result) {
                $this->updateEmailLog($logId, 'sent');
                $this->logActivity('email_sent', "Email sent to {$to}: {$subject}");
                return true;
            } else {
                $this->updateEmailLog($logId, 'failed', 'Failed to send email');
                return false;
            }
            
        } catch (Exception $e) {
            $this->updateEmailLog($logId ?? null, 'failed', $e->getMessage());
            $this->logActivity('email_failed', "Email failed to {$to}: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Send email using template
     */
    public function sendTemplate($templateName, $data, $to, $subject = null, $attachments = []) {
        try {
            $template = $this->loadTemplate($templateName);
            
            if (!$template) {
                throw new Exception("Template not found: {$templateName}");
            }
            
            // Use template subject if not provided
            if (!$subject) {
                $subject = $template['subject'];
            }
            
            // Process template variables
            $body = $this->processTemplate($template['content'], $data);
            $subject = $this->processTemplate($subject, $data);
            
            return $this->sendEmail($to, $subject, $body, true, $attachments);
            
        } catch (Exception $e) {
            $this->logActivity('template_error', "Template error for {$templateName}: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Send bulk email
     */
    public function sendBulkEmail($recipients, $subject, $body, $templateName = null, $templateData = []) {
        $sent = 0;
        $failed = 0;
        
        foreach ($recipients as $recipient) {
            $email = is_array($recipient) ? $recipient['email'] : $recipient;
            $personalData = is_array($recipient) ? $recipient : [];
            
            if ($templateName) {
                $mergedData = array_merge($templateData, $personalData);
                $result = $this->sendTemplate($templateName, $mergedData, $email, $subject);
            } else {
                $personalizedBody = $this->processTemplate($body, $personalData);
                $personalizedSubject = $this->processTemplate($subject, $personalData);
                $result = $this->sendEmail($email, $personalizedSubject, $personalizedBody);
            }
            
            if ($result) {
                $sent++;
            } else {
                $failed++;
            }
            
            // Add delay to prevent overwhelming the server
            usleep(100000); // 0.1 second delay
        }
        
        $this->logActivity('bulk_email', "Bulk email sent: {$sent} success, {$failed} failed");
        
        return [
            'sent' => $sent,
            'failed' => $failed,
            'total' => count($recipients)
        ];
    }
    
    /**
     * Add email to queue
     */
    public function queueEmail($to, $subject, $body, $templateName = null, $templateData = [], $priority = 'normal', $scheduleTime = null) {
        $stmt = $this->conn->prepare("
            INSERT INTO email_queue (to_email, subject, body, template_name, template_data, priority, scheduled_for, created_at) 
            VALUES (?, ?, ?, ?, ?, ?, ?, NOW())
        ");
        
        $templateDataJson = json_encode($templateData);
        $scheduleTime = $scheduleTime ?? date('Y-m-d H:i:s');
        
        $stmt->bind_param("sssssss", $to, $subject, $body, $templateName, $templateDataJson, $priority, $scheduleTime);
        
        return $stmt->execute();
    }
    
    /**
     * Process email queue
     */
    public function processQueue($batchSize = null) {
        $batchSize = $batchSize ?? $this->config->get('batch_size', 50);
        
        $stmt = $this->conn->prepare("
            SELECT * FROM email_queue 
            WHERE status = 'pending' 
            AND scheduled_for <= NOW() 
            AND retry_count < ? 
            ORDER BY priority DESC, created_at ASC 
            LIMIT ?
        ");
        
        $maxRetry = $this->config->get('max_retry', 3);
        $stmt->bind_param("ii", $maxRetry, $batchSize);
        $stmt->execute();
        $result = $stmt->get_result();
        
        $processed = 0;
        $sent = 0;
        $failed = 0;
        
        while ($row = $result->fetch_assoc()) {
            $processed++;
            
            if ($row['template_name']) {
                $templateData = json_decode($row['template_data'], true) ?? [];
                $success = $this->sendTemplate($row['template_name'], $templateData, $row['to_email'], $row['subject']);
            } else {
                $success = $this->sendEmail($row['to_email'], $row['subject'], $row['body']);
            }
            
            if ($success) {
                $sent++;
                $this->updateQueueStatus($row['id'], 'sent');
            } else {
                $failed++;
                $this->updateQueueStatus($row['id'], 'failed', $row['retry_count'] + 1);
            }
        }
        
        $this->logActivity('queue_processed', "Queue processed: {$processed} emails, {$sent} sent, {$failed} failed");
        
        return [
            'processed' => $processed,
            'sent' => $sent,
            'failed' => $failed
        ];
    }
    
    /**
     * Load email template
     */
    private function loadTemplate($templateName) {
        // Check cache first
        if (isset($this->templates[$templateName])) {
            return $this->templates[$templateName];
        }
        
        // Load from database
        $stmt = $this->conn->prepare("SELECT * FROM email_templates WHERE name = ? AND is_active = 1");
        $stmt->bind_param("s", $templateName);
        $stmt->execute();
        $result = $stmt->get_result();
        
        if ($template = $result->fetch_assoc()) {
            $this->templates[$templateName] = $template;
            return $template;
        }
        
        // Load from file if not in database
        $templatePath = __DIR__ . "/templates/email/{$templateName}.html";
        if (file_exists($templatePath)) {
            $content = file_get_contents($templatePath);
            $template = [
                'name' => $templateName,
                'subject' => $this->extractSubjectFromTemplate($content),
                'content' => $content
            ];
            $this->templates[$templateName] = $template;
            return $template;
        }
        
        return null;
    }
    
    /**
     * Process template variables
     */
    private function processTemplate($template, $data) {
        // Replace variables like {{variable_name}}
        $processed = preg_replace_callback('/\{\{([^}]+)\}\}/', function($matches) use ($data) {
            $key = trim($matches[1]);
            return $data[$key] ?? $matches[0];
        }, $template);
        
        // Replace organization variables
        $orgData = $this->getOrganizationData();
        $processed = preg_replace_callback('/\{\{org\.([^}]+)\}\}/', function($matches) use ($orgData) {
            $key = trim($matches[1]);
            return $orgData[$key] ?? $matches[0];
        }, $processed);
        
        return $processed;
    }
    
    /**
     * Send email directly (simulated PHPMailer functionality)
     */
    private function sendEmailDirect($emailData) {
        // In a real implementation, you would use PHPMailer here
        // For now, we'll simulate the email sending
        
        $config = $this->config->getAll();
        
        // Validate email address
        if (!filter_var($emailData['to'], FILTER_VALIDATE_EMAIL)) {
            throw new Exception("Invalid email address: " . $emailData['to']);
        }
        
        // Prepare headers
        $headers = [
            'MIME-Version: 1.0',
            'Content-Type: ' . ($emailData['isHTML'] ? 'text/html' : 'text/plain') . '; charset=UTF-8',
            'From: ' . $config['from_name'] . ' <' . $config['from_email'] . '>',
            'Reply-To: ' . ($emailData['replyTo'] ?? $config['from_email']),
            'X-Mailer: KSO Email System',
            'X-Priority: 3',
            'Return-Path: ' . $config['from_email']
        ];
        
        // Add additional headers
        if ($emailData['isHTML']) {
            $headers[] = 'Content-Transfer-Encoding: quoted-printable';
        }
        
        // Use PHP mail function (in production, use PHPMailer)
        $success = mail(
            $emailData['to'],
            $emailData['subject'],
            $emailData['body'],
            implode("\r\n", $headers)
        );
        
        return $success;
    }
    
    /**
     * Check rate limit
     */
    private function checkRateLimit() {
        $rateLimit = $this->config->get('rate_limit', 100);
        $hourAgo = date('Y-m-d H:i:s', strtotime('-1 hour'));
        
        $stmt = $this->conn->prepare("SELECT COUNT(*) as count FROM email_logs WHERE created_at >= ? AND status = 'sent'");
        $stmt->bind_param("s", $hourAgo);
        $stmt->execute();
        $result = $stmt->get_result();
        $count = $result->fetch_assoc()['count'];
        
        return $count < $rateLimit;
    }
    
    /**
     * Log email activity
     */
    private function logEmail($to, $subject, $status, $templateName = null, $errorMessage = null) {
        $stmt = $this->conn->prepare("
            INSERT INTO email_logs (to_email, subject, status, template_name, error_message, created_at) 
            VALUES (?, ?, ?, ?, ?, NOW())
        ");
        
        $stmt->bind_param("sssss", $to, $subject, $status, $templateName, $errorMessage);
        $stmt->execute();
        
        return $this->conn->insert_id;
    }
    
    /**
     * Update email log status
     */
    private function updateEmailLog($logId, $status, $errorMessage = null) {
        if (!$logId) return;
        
        $stmt = $this->conn->prepare("UPDATE email_logs SET status = ?, error_message = ?, updated_at = NOW() WHERE id = ?");
        $stmt->bind_param("ssi", $status, $errorMessage, $logId);
        $stmt->execute();
    }
    
    /**
     * Update queue status
     */
    private function updateQueueStatus($queueId, $status, $retryCount = null) {
        if ($retryCount !== null) {
            $stmt = $this->conn->prepare("UPDATE email_queue SET status = ?, retry_count = ?, updated_at = NOW() WHERE id = ?");
            $stmt->bind_param("sii", $status, $retryCount, $queueId);
        } else {
            $stmt = $this->conn->prepare("UPDATE email_queue SET status = ?, updated_at = NOW() WHERE id = ?");
            $stmt->bind_param("si", $status, $queueId);
        }
        $stmt->execute();
    }
    
    /**
     * Get organization data for templates
     */
    private function getOrganizationData() {
        static $orgData = null;
        
        if ($orgData === null) {
            $stmt = $this->conn->prepare("SELECT setting_key, setting_value FROM settings WHERE category = 'organization'");
            $stmt->execute();
            $result = $stmt->get_result();
            
            $orgData = [
                'name' => 'KSO Chandigarh',
                'email' => 'info@ksochandigarh.com',
                'phone' => '+91-XXXXXXXXXX',
                'address' => 'Chandigarh, India',
                'website' => 'https://ksochandigarh.com'
            ];
            
            while ($row = $result->fetch_assoc()) {
                $orgData[$row['setting_key']] = $row['setting_value'];
            }
        }
        
        return $orgData;
    }
    
    /**
     * Extract subject from template file
     */
    private function extractSubjectFromTemplate($content) {
        if (preg_match('/<title>([^<]+)<\/title>/', $content, $matches)) {
            return trim($matches[1]);
        }
        return 'KSO Chandigarh Notification';
    }
    
    /**
     * Log activity
     */
    private function logActivity($action, $description) {
        $stmt = $this->conn->prepare("INSERT INTO activity_logs (action, description, created_at) VALUES (?, ?, NOW())");
        $stmt->bind_param("ss", $action, $description);
        $stmt->execute();
    }
    
    /**
     * Get email statistics
     */
    public function getEmailStats($startDate = null, $endDate = null) {
        $startDate = $startDate ?? date('Y-m-d', strtotime('-30 days'));
        $endDate = $endDate ?? date('Y-m-d');
        
        $stmt = $this->conn->prepare("
            SELECT 
                COUNT(*) as total,
                SUM(CASE WHEN status = 'sent' THEN 1 ELSE 0 END) as sent,
                SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) as failed,
                SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) as pending
            FROM email_logs 
            WHERE DATE(created_at) BETWEEN ? AND ?
        ");
        
        $stmt->bind_param("ss", $startDate, $endDate);
        $stmt->execute();
        $result = $stmt->get_result();
        
        return $result->fetch_assoc();
    }
    
    /**
     * Get template usage statistics
     */
    public function getTemplateStats($startDate = null, $endDate = null) {
        $startDate = $startDate ?? date('Y-m-d', strtotime('-30 days'));
        $endDate = $endDate ?? date('Y-m-d');
        
        $stmt = $this->conn->prepare("
            SELECT 
                template_name,
                COUNT(*) as usage_count,
                SUM(CASE WHEN status = 'sent' THEN 1 ELSE 0 END) as sent_count
            FROM email_logs 
            WHERE template_name IS NOT NULL 
            AND DATE(created_at) BETWEEN ? AND ?
            GROUP BY template_name
            ORDER BY usage_count DESC
        ");
        
        $stmt->bind_param("ss", $startDate, $endDate);
        $stmt->execute();
        $result = $stmt->get_result();
        
        $stats = [];
        while ($row = $result->fetch_assoc()) {
            $stats[] = $row;
        }
        
        return $stats;
    }
    
    /**
     * Test email configuration
     */
    public function testEmailConfig($testEmail) {
        $testSubject = 'KSO Email System Test';
        $testBody = '<h2>Email Configuration Test</h2><p>This is a test email to verify that your email configuration is working correctly.</p><p>Sent at: ' . date('Y-m-d H:i:s') . '</p>';
        
        return $this->sendEmail($testEmail, $testSubject, $testBody);
    }
}
