<?php
/**
 * OTP Manager Class
 * Handles OTP generation, sending, and verification
 */

class OTPManager {
    private $db;
    private $config;
    
    public function __construct($db) {
        $this->db = $db;
        $this->config = require __DIR__ . '/../config/email_config.php';
        
        // Override config with database settings if available
        $this->loadDatabaseSettings();
    }
    
    /**
     * Load email settings from database
     */
    private function loadDatabaseSettings() {
        try {
            $settings = [
                'email_mode' => 'mode',
                'mail_host' => 'smtp_host',
                'mail_port' => 'smtp_port',
                'mail_encryption' => 'smtp_secure',
                'mail_username' => 'smtp_username',
                'mail_from_email' => 'from_email',
                'mail_from_name' => 'from_name'
            ];
            
            foreach ($settings as $dbKey => $configKey) {
                $setting = $this->db->fetch(
                    'SELECT setting_value FROM admin_settings WHERE setting_key = ?',
                    [$dbKey]
                );
                
                if ($setting && !empty($setting['setting_value'])) {
                    $this->config[$configKey] = $setting['setting_value'];
                }
            }
            
            // Load encrypted password
            $passwordSetting = $this->db->fetch(
                'SELECT setting_value FROM admin_settings WHERE setting_key = ?',
                ['mail_password_encrypted']
            );
            
            if ($passwordSetting && !empty($passwordSetting['setting_value'])) {
                $this->config['smtp_password'] = base64_decode($passwordSetting['setting_value']);
            }
            
            // Force php_mail for Razorhost compatibility
            $this->config['mode'] = 'php_mail';
            
        } catch (Exception $e) {
            error_log('Failed to load email settings from database: ' . $e->getMessage());
            // Force php_mail as fallback
            $this->config['mode'] = 'php_mail';
        }
    }
    
    /**
     * Generate and send OTP to email
     */
    public function generateAndSendOTP($email, $name = '') {
        try {
            // Generate 6-digit OTP
            $otp = str_pad(random_int(0, 999999), 6, '0', STR_PAD_LEFT);
            
            // Use database NOW() for consistency across timezones
            // Get current database timestamp in the correct format
            $timeResult = $this->db->fetch('SELECT NOW() as current_time');
            $currentTime = $timeResult['current_time'];
            
            // Calculate expiry time using DATE_ADD in database query
            $expiryResult = $this->db->fetch(
                'SELECT DATE_ADD(NOW(), INTERVAL ? MINUTE) as expiry_time',
                [$this->config['otp_expiry_minutes']]
            );
            $expiryTime = $expiryResult['expiry_time'];
            
            // Check if OTP already exists for this email
            $existingOTP = $this->db->fetch(
                'SELECT id FROM email_otps WHERE email = ? AND expires_at > NOW()',
                [$email]
            );
            
            if ($existingOTP) {
                // Delete old OTP
                $this->db->query('DELETE FROM email_otps WHERE email = ?', [$email]);
            }
            
            // Store OTP in database
            $this->db->insert('email_otps', [
                'email' => $email,
                'otp' => $otp,
                'attempts' => 0,
                'created_at' => $currentTime,
                'expires_at' => $expiryTime
            ]);
            
            // Send OTP email and check if successful
            $emailSent = $this->sendOTPEmail($email, $otp, $name);
            
            if (!$emailSent) {
                error_log("Failed to send OTP email to $email via mail() function. Check server mail configuration.");
                return ['success' => false, 'message' => 'Failed to send OTP email. Please check your email address and try again.'];
            }
            
            return ['success' => true, 'message' => 'OTP sent to ' . $email];
        } catch (Exception $e) {
            error_log('OTP Generation Error: ' . $e->getMessage());
            return ['success' => false, 'message' => 'Failed to send OTP: ' . $e->getMessage()];
        }
    }
    
    /**
     * Send OTP via Email - Uses Brevo if available, otherwise php_mail
     */
    private function sendOTPEmail($email, $otp, $name = '') {
        // Check if Brevo API key is configured
        $brevoApiKey = getenv('BREVO_API_KEY');
        $brevoEnabled = getenv('BREVO_ENABLED');
        
        // If Brevo is configured and enabled, use it
        if (!empty($brevoApiKey) && $brevoApiKey !== 'xkeysib-' && $brevoEnabled) {
            return $this->sendViaBrevo($email, $otp, $name, $brevoApiKey);
        }
        
        // Fallback to php_mail
        return $this->sendViaPhpMail($email, $otp, $name);
    }
    
    /**
     * Send OTP via Brevo API
     */
    private function sendViaBrevo($email, $otp, $name, $apiKey) {
        $subject = 'Your OTP Verification Code - ' . APP_NAME;
        
        $htmlContent = "
            <html>
                <head>
                    <style>
                        body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: #f5f5f5; }
                        .container { background: white; max-width: 500px; margin: 30px auto; padding: 40px; border-radius: 10px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); }
                        .header { text-align: center; margin-bottom: 30px; }
                        .logo { font-size: 24px; font-weight: bold; color: #667eea; }
                        .content { text-align: center; }
                        .otp-box { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px; border-radius: 8px; margin: 20px 0; font-size: 32px; font-weight: bold; letter-spacing: 5px; }
                        .info { color: #666; margin: 15px 0; font-size: 14px; }
                        .warning { background: #fff3cd; color: #856404; padding: 10px; border-radius: 5px; margin: 15px 0; font-size: 13px; }
                        .footer { text-align: center; color: #999; font-size: 12px; margin-top: 30px; border-top: 1px solid #eee; padding-top: 15px; }
                    </style>
                </head>
                <body>
                    <div class='container'>
                        <div class='header'>
                            <div class='logo'>🔐 " . APP_NAME . "</div>
                        </div>
                        
                        <div class='content'>
                            <h2>Email Verification</h2>
                            <p>Hi " . htmlspecialchars($name) . ",</p>
                            <p>Your OTP verification code is:</p>
                            
                            <div class='otp-box'>" . $otp . "</div>
                            
                            <div class='info'>
                                <p>This code will expire in 5 minutes</p>
                            </div>
                            
                            <div class='warning'>
                                ⚠️ Never share this code with anyone. We will never ask for your OTP.
                            </div>
                            
                            <p style='color: #666; margin-top: 20px;'>
                                If you didn't request this code, please ignore this email.
                            </p>
                        </div>
                        
                        <div class='footer'>
                            <p>&copy; " . date('Y') . " " . APP_NAME . ". All rights reserved.</p>
                        </div>
                    </div>
                </body>
            </html>
        ";
        
        $payload = [
            'sender' => [
                'name' => $this->config['from_name'] ?? APP_NAME,
                'email' => $this->config['from_email'] ?? ADMIN_EMAIL
            ],
            'to' => [
                [
                    'email' => $email,
                    'name' => $name
                ]
            ],
            'subject' => $subject,
            'htmlContent' => $htmlContent,
            'textContent' => "Your OTP: $otp. This code expires in 5 minutes."
        ];
        
        try {
            $curl = curl_init();
            curl_setopt_array($curl, [
                CURLOPT_URL => 'https://api.brevo.com/v3/smtp/email',
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_TIMEOUT => 10,
                CURLOPT_CUSTOMREQUEST => 'POST',
                CURLOPT_POSTFIELDS => json_encode($payload),
                CURLOPT_HTTPHEADER => [
                    'Accept: application/json',
                    'Content-Type: application/json',
                    'api-key: ' . $apiKey
                ]
            ]);
            
            $response = curl_exec($curl);
            $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
            curl_close($curl);
            
            if ($httpCode >= 200 && $httpCode < 300) {
                error_log("OTP sent via Brevo to $email - Success");
                return true;
            } else {
                error_log("Brevo OTP failed to $email - HTTP $httpCode - Response: $response");
                return false;
            }
        } catch (Exception $e) {
            error_log("Brevo OTP error: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Send OTP via PHP mail() function (Fallback)
     */
    private function sendViaPhpMail($email, $otp, $name = '') {
        $subject = 'Your OTP Verification Code - ' . APP_NAME;
        
        $htmlContent = "
            <html>
                <head>
                    <style>
                        body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: #f5f5f5; }
                        .container { background: white; max-width: 500px; margin: 30px auto; padding: 40px; border-radius: 10px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); }
                        .header { text-align: center; margin-bottom: 30px; }
                        .logo { font-size: 24px; font-weight: bold; color: #667eea; }
                        .content { text-align: center; }
                        .otp-box { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px; border-radius: 8px; margin: 20px 0; font-size: 32px; font-weight: bold; letter-spacing: 5px; }
                        .info { color: #666; margin: 15px 0; font-size: 14px; }
                        .warning { background: #fff3cd; color: #856404; padding: 10px; border-radius: 5px; margin: 15px 0; font-size: 13px; }
                        .footer { text-align: center; color: #999; font-size: 12px; margin-top: 30px; border-top: 1px solid #eee; padding-top: 15px; }
                    </style>
                </head>
                <body>
                    <div class='container'>
                        <div class='header'>
                            <div class='logo'>🔐 " . APP_NAME . "</div>
                        </div>
                        
                        <div class='content'>
                            <h2>Email Verification</h2>
                            <p>Hi " . htmlspecialchars($name) . ",</p>
                            <p>Your OTP verification code is:</p>
                            
                            <div class='otp-box'>" . $otp . "</div>
                            
                            <div class='info'>
                                <p>This code will expire in 5 minutes</p>
                            </div>
                            
                            <div class='warning'>
                                ⚠️ Never share this code with anyone. We will never ask for your OTP.
                            </div>
                            
                            <p style='color: #666; margin-top: 20px;'>
                                If you didn't request this code, please ignore this email.
                            </p>
                        </div>
                        
                        <div class='footer'>
                            <p>&copy; " . date('Y') . " " . APP_NAME . ". All rights reserved.</p>
                        </div>
                    </div>
                </body>
            </html>
        ";
        
        $headers = "MIME-Version: 1.0\r\n";
        $headers .= "Content-type: text/html; charset=UTF-8\r\n";
        $headers .= "From: " . $this->config['from_name'] . " <" . $this->config['from_email'] . ">\r\n";
        $headers .= "Reply-To: " . $this->config['from_email'] . "\r\n";
        $headers .= "X-Mailer: PHP/" . phpversion() . "\r\n";
        $headers .= "Return-Path: " . $this->config['from_email'] . "\r\n";
        $headers .= "Content-Transfer-Encoding: 8bit\r\n";
        
        error_log("OTP: Attempting to send to $email via php_mail");
        
        $result = @mail($email, $subject, $htmlContent, $headers);
        
        if ($result) {
            error_log("OTP sent via php_mail to $email - Success");
        } else {
            error_log("OTP failed to send via php_mail to $email");
        }
        
        return $result;
    }
    
    /**
     * Verify OTP
     */
    public function verifyOTP($email, $otp) {
        try {
            // Trim whitespace from OTP
            $otp = trim($otp);
            
            // Check if OTP exists and is valid
            $otpRecord = $this->db->fetch(
                'SELECT id, otp, attempts, expires_at, created_at FROM email_otps WHERE email = ?',
                [$email]
            );
            
            if (!$otpRecord) {
                return ['success' => false, 'message' => 'OTP not found. Please request a new one.'];
            }
            
            // Check if OTP has expired using database time comparison (more reliable)
            // Let database handle timezone, just compare timestamps
            $expiredCheck = $this->db->fetch(
                'SELECT id FROM email_otps WHERE email = ? AND expires_at > NOW()',
                [$email]
            );
            
            if (!$expiredCheck) {
                // OTP has expired, delete it
                $this->db->query('DELETE FROM email_otps WHERE id = ?', [$otpRecord['id']]);
                return ['success' => false, 'message' => '❌ OTP has expired. Please register again to get a new OTP.'];
            }
            
            // Check attempts
            if ($otpRecord['attempts'] >= $this->config['otp_max_attempts']) {
                return ['success' => false, 'message' => 'Too many incorrect attempts. Please request a new OTP.'];
            }
            
            // Verify OTP
            if ($otpRecord['otp'] !== $otp) {
                // Increment attempts
                $this->db->update('email_otps',
                    ['attempts' => $otpRecord['attempts'] + 1],
                    'id = ?',
                    ['id' => $otpRecord['id']]
                );
                return ['success' => false, 'message' => 'Invalid OTP. Please try again.'];
            }
            
            // OTP is correct - delete it
            $this->db->query('DELETE FROM email_otps WHERE id = ?', [$otpRecord['id']]);
            
            return ['success' => true, 'message' => 'OTP verified successfully'];
        } catch (Exception $e) {
            error_log('OTP Verification Error: ' . $e->getMessage());
            return ['success' => false, 'message' => 'Verification failed: ' . $e->getMessage()];
        }
    }
    
    /**
     * Resend OTP
     */
    public function resendOTP($email) {
        try {
            // Delete old OTP
            $this->db->query('DELETE FROM email_otps WHERE email = ?', [$email]);
            
            // Generate new OTP
            $otp = str_pad(random_int(0, 999999), 6, '0', STR_PAD_LEFT);
            
            // Use database NOW() for consistency across timezones
            $timeResult = $this->db->fetch('SELECT NOW() as current_time');
            $currentTime = $timeResult['current_time'];
            
            // Calculate expiry time using DATE_ADD in database query
            $expiryResult = $this->db->fetch(
                'SELECT DATE_ADD(NOW(), INTERVAL ? MINUTE) as expiry_time',
                [$this->config['otp_expiry_minutes']]
            );
            $expiryTime = $expiryResult['expiry_time'];
            
            // Store new OTP
            $this->db->insert('email_otps', [
                'email' => $email,
                'otp' => $otp,
                'attempts' => 0,
                'created_at' => $currentTime,
                'expires_at' => $expiryTime
            ]);
            
            // Send email and check if successful
            $emailSent = $this->sendOTPEmail($email, $otp);
            
            if (!$emailSent) {
                error_log("Failed to resend OTP email to $email. Check mail() function.");
                return ['success' => false, 'message' => 'Failed to send OTP email. Please try again.'];
            }
            
            return ['success' => true, 'message' => 'New OTP sent to ' . $email];
        } catch (Exception $e) {
            error_log('Resend OTP Error: ' . $e->getMessage());
            return ['success' => false, 'message' => 'Failed to resend OTP'];
        }
    }
    
    /**
     * Get remaining OTP time
     */
    public function getRemainingTime($email) {
        $otpRecord = $this->db->fetch(
            'SELECT expires_at FROM email_otps WHERE email = ? AND expires_at > NOW()',
            [$email]
        );
        
        if (!$otpRecord) {
            return 0;
        }
        
        // Use database to calculate remaining time (more reliable)
        $result = $this->db->fetch(
            'SELECT TIMESTAMPDIFF(SECOND, NOW(), expires_at) as remaining FROM email_otps WHERE email = ? AND expires_at > NOW()',
            [$email]
        );
        
        if (!$result || $result['remaining'] < 0) {
            return 0;
        }
        
        return max(0, (int)$result['remaining']);
    }
}
?>
