<?php

// AdminAuth class for admin authentication
// PHP 7.2 Compatible Version

class AdminAuth
{
    private $conn;
    
    public function __construct(mysqli $connection)
    {
        $this->conn = $connection;
    }
    
    /**
     * Authenticate admin user
     */
    public function authenticate($username, $password)
    {
        $stmt = $this->conn->prepare("SELECT id, username, password_hash, status, role, phone FROM admin_users WHERE username = ? AND status = 'active'");
        if (!$stmt) {
            return ['success' => false, 'error' => 'Database error'];
        }
        
        $stmt->bind_param("s", $username);
        $stmt->execute();
        $result = $stmt->get_result();
        
        if ($result->num_rows === 1) {
            $admin = $result->fetch_assoc();
            
            if (password_verify($password, $admin['password_hash'])) {
                // Update last login
                $this->updateLastLogin($admin['id']);
                
                // Log successful login
                $this->logLogin($admin['id'], $username, 'success');
                
                // Send SMS notification for admin login
                $this->sendAdminLoginNotification($admin);
                
                return [
                    'success' => true,
                    'admin' => [
                        'id' => $admin['id'],
                        'username' => $admin['username'],
                        'role' => $admin['role']
                    ]
                ];
            } else {
                $this->logLogin(null, $username, 'failed', 'Invalid password');
                return ['success' => false, 'error' => 'Invalid credentials'];
            }
        } else {
            $this->logLogin(null, $username, 'failed', 'User not found');
            return ['success' => false, 'error' => 'Invalid credentials'];
        }
    }
    
    /**
     * Check if admin is authenticated
     */
    public function isAuthenticated()
    {
        return isset($_SESSION['admin_logged_in']) && 
               $_SESSION['admin_logged_in'] === true &&
               isset($_SESSION['admin_id']);
    }
    
    /**
     * Require authentication (redirect if not authenticated)
     */
    public function requireAuth($redirectTo = 'admin/admin_login.php')
    {
        if (!$this->isAuthenticated()) {
            header("Location: $redirectTo");
            exit();
        }
        
        // Check session timeout (2 hours)
        if (isset($_SESSION['login_time']) && (time() - $_SESSION['login_time']) > 7200) {
            $this->logout();
            header("Location: $redirectTo?timeout=1");
            exit();
        }
    }
    
    /**
     * Create admin session
     */
    public function createSession($admin)
    {
        // Regenerate session ID for security
        session_regenerate_id(true);
        
        $_SESSION['admin_logged_in'] = true;
        $_SESSION['admin_id'] = $admin['id'];
        $_SESSION['admin_username'] = $admin['username'];
        $_SESSION['admin_role'] = $admin['role'];
        $_SESSION['login_time'] = time();
    }
    
    /**
     * Logout admin
     */
    public function logout()
    {
        if (isset($_SESSION['admin_username'])) {
            $this->logLogin(isset($_SESSION['admin_id']) ? $_SESSION['admin_id'] : null, $_SESSION['admin_username'], 'logout');
        }
        
        session_destroy();
    }
    
    /**
     * Update last login timestamp
     */
    private function updateLastLogin($adminId)
    {
        $stmt = $this->conn->prepare("UPDATE admin_users SET last_login = NOW() WHERE id = ?");
        if ($stmt) {
            $stmt->bind_param("i", $adminId);
            $stmt->execute();
            $stmt->close();
        }
    }
    
    /**
     * Log login attempts
     */
    private function logLogin($adminId, $username, $status, $reason = null)
    {
        $ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : 'unknown';
        $userAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'unknown';
        
        // Truncate user agent if too long (some browsers send very long user agents)
        if (strlen($userAgent) > 500) {
            $userAgent = substr($userAgent, 0, 500);
        }
        
        try {
            $stmt = $this->conn->prepare("INSERT INTO admin_login_logs (admin_id, username, ip_address, user_agent, login_status, failure_reason) VALUES (?, ?, ?, ?, ?, ?)");
            if ($stmt) {
                $stmt->bind_param("isssss", $adminId, $username, $ip, $userAgent, $status, $reason);
                $stmt->execute();
                $stmt->close();
            }
        } catch (mysqli_sql_exception $e) {
            // Log the error but don't break the login process
            error_log("AdminAuth: Failed to log login attempt - " . $e->getMessage());
        }
        
        // Also log to error log for monitoring
        error_log("Admin login: $status for $username from $ip" . ($reason ? " - $reason" : ""));
    }
    
    /**
     * Create new admin user
     */
    public function createAdmin($username, $password, $email = null, $fullName = null, $role = 'admin')
    {
        // Check if username already exists
        $stmt = $this->conn->prepare("SELECT id FROM admin_users WHERE username = ?");
        if (!$stmt) {
            return ['success' => false, 'error' => 'Database error'];
        }
        
        $stmt->bind_param("s", $username);
        $stmt->execute();
        
        if ($stmt->get_result()->num_rows > 0) {
            return ['success' => false, 'error' => 'Username already exists'];
        }
        
        // Hash password
        $passwordHash = password_hash($password, PASSWORD_DEFAULT);
        
        // Insert new admin
        $stmt = $this->conn->prepare("INSERT INTO admin_users (username, password_hash, email, full_name, role) VALUES (?, ?, ?, ?, ?)");
        if (!$stmt) {
            return ['success' => false, 'error' => 'Database error'];
        }
        
        $stmt->bind_param("sssss", $username, $passwordHash, $email, $fullName, $role);
        
        if ($stmt->execute()) {
            return ['success' => true, 'admin_id' => $this->conn->insert_id];
        } else {
            return ['success' => false, 'error' => 'Failed to create admin user'];
        }
    }
    
    /**
     * Change admin password
     */
    public function changePassword($adminId, $currentPassword, $newPassword)
    {
        // Verify current password
        $stmt = $this->conn->prepare("SELECT password_hash FROM admin_users WHERE id = ?");
        if (!$stmt) {
            return ['success' => false, 'error' => 'Database error'];
        }
        
        $stmt->bind_param("i", $adminId);
        $stmt->execute();
        $result = $stmt->get_result();
        
        if ($result->num_rows === 1) {
            $admin = $result->fetch_assoc();
            
            if (password_verify($currentPassword, $admin['password_hash'])) {
                // Update password
                $newPasswordHash = password_hash($newPassword, PASSWORD_DEFAULT);
                
                $updateStmt = $this->conn->prepare("UPDATE admin_users SET password_hash = ?, updated_at = NOW() WHERE id = ?");
                if ($updateStmt) {
                    $updateStmt->bind_param("si", $newPasswordHash, $adminId);
                    
                    if ($updateStmt->execute()) {
                        // Log password change for security
                        $this->logPasswordChange($adminId);
                        return ['success' => true];
                    } else {
                        return ['success' => false, 'error' => 'Failed to update password'];
                    }
                } else {
                    return ['success' => false, 'error' => 'Database error'];
                }
            } else {
                return ['success' => false, 'error' => 'Current password is incorrect'];
            }
        } else {
            return ['success' => false, 'error' => 'Admin not found'];
        }
    }
    
    /**
     * Log password change for security
     */
    private function logPasswordChange($adminId)
    {
        $ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : 'unknown';
        $userAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'unknown';
        
        $stmt = $this->conn->prepare("INSERT INTO admin_login_logs (admin_id, username, ip_address, user_agent, login_status, failure_reason) VALUES (?, ?, ?, ?, 'password_changed', 'Password changed successfully')");
        if ($stmt) {
            $username = isset($_SESSION['admin_username']) ? $_SESSION['admin_username'] : 'unknown';
            $stmt->bind_param("isss", $adminId, $username, $ip, $userAgent);
            $stmt->execute();
            $stmt->close();
        }
    }
    
    /**
     * Get admin info
     */
    public function getAdminInfo($adminId)
    {
        $stmt = $this->conn->prepare("SELECT id, username, email, full_name, role, status, last_login, created_at FROM admin_users WHERE id = ?");
        if (!$stmt) {
            return null;
        }
        
        $stmt->bind_param("i", $adminId);
        $stmt->execute();
        $result = $stmt->get_result();
        
        return $result->num_rows === 1 ? $result->fetch_assoc() : null;
    }
    
    /**
     * Get login logs
     */
    public function getLoginLogs($limit = 50)
    {
        $stmt = $this->conn->prepare("SELECT * FROM admin_login_logs ORDER BY created_at DESC LIMIT ?");
        if (!$stmt) {
            return [];
        }
        
        $stmt->bind_param("i", $limit);
        $stmt->execute();
        $result = $stmt->get_result();
        
        $logs = [];
        while ($row = $result->fetch_assoc()) {
            $logs[] = $row;
        }
        
        return $logs;
    }
    
    /**
     * Send SMS notification for admin login
     */
private function sendAdminLoginNotification($admin)
    {
        try {
            // Only send notification if admin has a phone number
            if (empty($admin['phone'])) {
                error_log("Admin login notification skipped: No phone number for admin " . $admin['username']);
                return;
            }
            
            // Load NotificationManager
            require_once __DIR__ . '/NotificationManager.php';
            $notificationManager = new NotificationManager($this->conn);
            
            // Prepare notification data
            $notificationData = [
                'username' => $admin['username'],
                'date' => date('Y-m-d H:i:s'),
                'ip_address' => $this->getClientIP(),
                'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown'
            ];
            
            // For admin users, we need to send notification directly since NotificationManager
            // expects agent user IDs. We'll use the direct SMS/Email sending methods.
            $this->sendDirectAdminNotification($admin, $notificationData);
            
        } catch (Exception $e) {
            // Log error but don't fail the login process
            error_log("Admin login notification error: " . $e->getMessage());
        }
    }
    
    /**
     * Send direct notification to admin (bypassing the agent-based NotificationManager)
     */
    private function sendDirectAdminNotification($admin, $notificationData)
    {
        try {
            // Get notification template for admin login
            $template = $this->getAdminNotificationTemplate('admin_login');
            if (!$template) {
                error_log("Admin login notification template not found");
                return;
            }
            
            // Process template with data
            $processedTemplate = $this->processAdminTemplate($template, $notificationData, $admin);
            
            // Send SMS if enabled and admin has phone number
            if ($this->isSMSEnabled() && !empty($admin['phone'])) {
                $smsResult = $this->sendDirectSMS($admin['phone'], $processedTemplate['sms']);
                if ($smsResult) {
                    error_log("Admin login SMS sent successfully to " . $admin['username']);
                } else {
                    error_log("Admin login SMS failed for " . $admin['username']);
                }
            }
            
            // Send Email if enabled and admin has email
            if ($this->isEmailEnabled() && !empty($admin['email'])) {
                $emailResult = $this->sendDirectEmail($admin['email'], $processedTemplate['email']['subject'], $processedTemplate['email']['body']);
                if ($emailResult) {
                    error_log("Admin login email sent successfully to " . $admin['username']);
                } else {
                    error_log("Admin login email failed for " . $admin['username']);
                }
            }
            
        } catch (Exception $e) {
            error_log("Direct admin notification error: " . $e->getMessage());
        }
    }
    
    /**
     * Get admin notification template
     */
    private function getAdminNotificationTemplate($type)
    {
        $templates = [
            'admin_login' => [
                'sms' => 'Admin Login Alert: {username} logged in at {date} from IP {ip_address}',
                'email' => [
                    'subject' => 'Admin Login Alert - D-Bundles Stores',
                    'body' => "Admin Login Alert\n\nUsername: {username}\nDate: {date}\nIP Address: {ip_address}\nUser Agent: {user_agent}\n\nThis is an automated security notification."
                ]
            ]
        ];
        
        return $templates[$type] ?? null;
    }
    
    /**
     * Process admin notification template
     */
    private function processAdminTemplate($template, $data, $admin)
    {
        $processed = $template;
        
        // Replace placeholders
        $replacements = [
            '{username}' => $admin['username'],
            '{date}' => $data['date'],
            '{ip_address}' => $data['ip_address'],
            '{user_agent}' => $data['user_agent']
        ];
        
        $processed['sms'] = str_replace(array_keys($replacements), array_values($replacements), $template['sms']);
        $processed['email']['subject'] = str_replace(array_keys($replacements), array_values($replacements), $template['email']['subject']);
        $processed['email']['body'] = str_replace(array_keys($replacements), array_values($replacements), $template['email']['body']);
        
        return $processed;
    }
    
    /**
     * Check if SMS is enabled
     */
    private function isSMSEnabled()
    {
        try {
            $result = mysqli_query($this->conn, "SELECT config_data FROM notification_config WHERE type = 'sms'");
            if ($result && mysqli_num_rows($result) > 0) {
                $data = mysqli_fetch_assoc($result);
                $config = json_decode($data['config_data'], true);
                return isset($config['enabled']) && $config['enabled'];
            }
        } catch (Exception $e) {
            error_log("Error checking SMS config: " . $e->getMessage());
        }
        return false;
    }
    
    /**
     * Check if Email is enabled
     */
    private function isEmailEnabled()
    {
        try {
            $result = mysqli_query($this->conn, "SELECT config_data FROM notification_config WHERE type = 'email'");
            if ($result && mysqli_num_rows($result) > 0) {
                $data = mysqli_fetch_assoc($result);
                $config = json_decode($data['config_data'], true);
                return isset($config['enabled']) && $config['enabled'];
            }
        } catch (Exception $e) {
            error_log("Error checking email config: " . $e->getMessage());
        }
        return false;
    }
    
    /**
     * Send direct SMS
     */
    private function sendDirectSMS($phone, $message)
    {
        try {
            // Get SMS configuration
            $result = mysqli_query($this->conn, "SELECT config_data FROM notification_config WHERE type = 'sms'");
            if (!$result || mysqli_num_rows($result) == 0) {
                return false;
            }
            
            $data = mysqli_fetch_assoc($result);
            $config = json_decode($data['config_data'], true);
            
            if (!$config['enabled']) {
                return false;
            }
            
            // Here you would implement the actual SMS sending logic
            // For now, we'll just log it
            error_log("SMS would be sent to $phone: $message");
            return true;
            
        } catch (Exception $e) {
            error_log("SMS sending error: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Send direct email
     */
    private function sendDirectEmail($email, $subject, $body)
    {
        try {
            // Get email configuration
            $result = mysqli_query($this->conn, "SELECT config_data FROM notification_config WHERE type = 'email'");
            if (!$result || mysqli_num_rows($result) == 0) {
                return false;
            }
            
            $data = mysqli_fetch_assoc($result);
            $config = json_decode($data['config_data'], true);
            
            if (!$config['enabled']) {
                return false;
            }
            
            // Here you would implement the actual email sending logic
            // For now, we'll just log it
            error_log("Email would be sent to $email: $subject");
            return true;
            
        } catch (Exception $e) {
            error_log("Email sending error: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Get client IP address
     */
    private function getClientIP()
    {
        $ipKeys = ['HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'REMOTE_ADDR'];
        foreach ($ipKeys as $key) {
            if (array_key_exists($key, $_SERVER) === true) {
                foreach (explode(',', $_SERVER[$key]) as $ip) {
                    $ip = trim($ip);
                    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false) {
                        return $ip;
                    }
                }
            }
        }
        return $_SERVER['REMOTE_ADDR'] ?? 'Unknown';
    }
}
