<?php
/**
 * Common Functions
 * OBGYN Research & Collaboration Platform
 */

/**
 * Sanitize input data
 */
function sanitize($data) {
    if (is_array($data)) {
        return array_map('sanitize', $data);
    }
    return htmlspecialchars(strip_tags(trim($data)), ENT_QUOTES, 'UTF-8');
}

/**
 * Validate email
 */
function isValidEmail($email) {
    return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}

/**
 * Generate random token
 */
function generateToken($length = 32) {
    return bin2hex(random_bytes($length));
}

/**
 * Hash password
 */
function hashPassword($password) {
    return password_hash($password, HASH_ALGO, ['cost' => HASH_COST]);
}

/**
 * Verify password
 */
function verifyPassword($password, $hash) {
    return password_verify($password, $hash);
}

/**
 * Generate slug from string
 */
function generateSlug($string) {
    $string = strtolower(trim($string));
    $string = preg_replace('/[^a-z0-9-]/', '-', $string);
    $string = preg_replace('/-+/', '-', $string);
    return trim($string, '-');
}

/**
 * Format date
 */
function formatDate($date, $format = 'M d, Y') {
    if (empty($date)) return '';
    return date($format, strtotime($date));
}

/**
 * Format datetime
 */
function formatDateTime($datetime, $format = 'M d, Y H:i') {
    if (empty($datetime)) return '';
    return date($format, strtotime($datetime));
}

/**
 * Time ago function
 */
function timeAgo($datetime) {
    $timestamp = strtotime($datetime);
    $difference = time() - $timestamp;
    
    if ($difference < 60) {
        return 'just now';
    } elseif ($difference < 3600) {
        $minutes = floor($difference / 60);
        return $minutes . ' minute' . ($minutes > 1 ? 's' : '') . ' ago';
    } elseif ($difference < 86400) {
        $hours = floor($difference / 3600);
        return $hours . ' hour' . ($hours > 1 ? 's' : '') . ' ago';
    } elseif ($difference < 604800) {
        $days = floor($difference / 86400);
        return $days . ' day' . ($days > 1 ? 's' : '') . ' ago';
    } elseif ($difference < 2592000) {
        $weeks = floor($difference / 604800);
        return $weeks . ' week' . ($weeks > 1 ? 's' : '') . ' ago';
    } elseif ($difference < 31536000) {
        $months = floor($difference / 2592000);
        return $months . ' month' . ($months > 1 ? 's' : '') . ' ago';
    } else {
        $years = floor($difference / 31536000);
        return $years . ' year' . ($years > 1 ? 's' : '') . ' ago';
    }
}

/**
 * Format file size
 */
function formatFileSize($bytes) {
    if ($bytes >= 1073741824) {
        return number_format($bytes / 1073741824, 2) . ' GB';
    } elseif ($bytes >= 1048576) {
        return number_format($bytes / 1048576, 2) . ' MB';
    } elseif ($bytes >= 1024) {
        return number_format($bytes / 1024, 2) . ' KB';
    } else {
        return $bytes . ' bytes';
    }
}

/**
 * Redirect to URL
 */
function redirect($url) {
    header("Location: " . $url);
    exit();
}

/**
 * Set flash message
 */
function setFlashMessage($type, $message) {
    $_SESSION['flash_message'] = [
        'type' => $type,
        'message' => $message
    ];
}

/**
 * Get and clear flash message
 */
function getFlashMessage() {
    if (isset($_SESSION['flash_message'])) {
        $message = $_SESSION['flash_message'];
        unset($_SESSION['flash_message']);
        return $message;
    }
    return null;
}

/**
 * Check if user is logged in
 */
function isLoggedIn() {
    return isset($_SESSION['user_id']) && !empty($_SESSION['user_id']);
}

/**
 * Get current user ID
 */
function getCurrentUserId() {
    return $_SESSION['user_id'] ?? null;
}

/**
 * Get current user role
 */
function getCurrentUserRole() {
    // Check session first
    if (isset($_SESSION['user_role'])) {
        return $_SESSION['user_role'];
    }
    
    // If not in session but user is logged in, fetch from database
    if (isset($_SESSION['user_id'])) {
        try {
            $db = getDB();
            $stmt = $db->prepare("SELECT role_id FROM users WHERE id = ?");
            $stmt->execute([$_SESSION['user_id']]);
            $user = $stmt->fetch();
            
            if ($user) {
                // Store in session for future use
                $_SESSION['user_role'] = $user['role_id'];
                return $user['role_id'];
            }
        } catch (Exception $e) {
            error_log("Get current user role error: " . $e->getMessage());
        }
    }
    
    return null;
}

/**
 * Require login
 */
function requireLogin() {
    if (!isLoggedIn()) {
        setFlashMessage('error', 'Please login to access this page.');
        redirect(SITE_URL . '/login.php');
    }
}

/**
 * Require role
 */
function requireRole($role) {
    requireLogin();
    if (getCurrentUserRole() != $role) {
        setFlashMessage('error', 'You do not have permission to access this page.');
        redirect(SITE_URL . '/index.php');
    }
}

/**
 * Upload file
 */
function uploadFile($file, $destination, $allowedTypes = null) {
    if (!isset($file) || $file['error'] !== UPLOAD_ERR_OK) {
        return ['success' => false, 'message' => 'File upload error.'];
    }
    
    // Check file size
    if ($file['size'] > MAX_FILE_SIZE) {
        return ['success' => false, 'message' => 'File size exceeds maximum allowed size.'];
    }
    
    // Get file extension
    $fileExtension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
    
    // Check file type
    $allowedTypes = $allowedTypes ?? ALLOWED_FILE_TYPES;
    if (!in_array($fileExtension, $allowedTypes)) {
        return ['success' => false, 'message' => 'File type not allowed.'];
    }
    
    // Generate unique filename
    $newFileName = uniqid() . '_' . time() . '.' . $fileExtension;
    $targetPath = $destination . '/' . $newFileName;
    
    // Create directory if it doesn't exist
    if (!file_exists($destination)) {
        mkdir($destination, 0755, true);
    }
    
    // Move uploaded file
    if (move_uploaded_file($file['tmp_name'], $targetPath)) {
        return [
            'success' => true,
            'filename' => $newFileName,
            'path' => $targetPath,
            'size' => $file['size'],
            'type' => $fileExtension
        ];
    }
    
    return ['success' => false, 'message' => 'Failed to move uploaded file.'];
}

/**
 * Delete file
 */
function deleteFile($filePath) {
    if (file_exists($filePath)) {
        return unlink($filePath);
    }
    return false;
}

/**
 * Paginate results
 */
function paginate($totalItems, $itemsPerPage, $currentPage = 1) {
    $totalPages = ceil($totalItems / $itemsPerPage);
    $currentPage = max(1, min($currentPage, $totalPages));
    $offset = ($currentPage - 1) * $itemsPerPage;
    
    return [
        'total_items' => $totalItems,
        'total_pages' => $totalPages,
        'current_page' => $currentPage,
        'items_per_page' => $itemsPerPage,
        'offset' => $offset,
        'has_previous' => $currentPage > 1,
        'has_next' => $currentPage < $totalPages
    ];
}

/**
 * Generate pagination HTML
 */
function generatePaginationHTML($pagination, $baseUrl) {
    if ($pagination['total_pages'] <= 1) {
        return '';
    }
    
    $html = '<nav aria-label="Page navigation"><ul class="pagination justify-content-center">';
    
    // Previous button
    if ($pagination['has_previous']) {
        $prevPage = $pagination['current_page'] - 1;
        $html .= '<li class="page-item"><a class="page-link" href="' . $baseUrl . '?page=' . $prevPage . '">Previous</a></li>';
    } else {
        $html .= '<li class="page-item disabled"><span class="page-link">Previous</span></li>';
    }
    
    // Page numbers
    $startPage = max(1, $pagination['current_page'] - 2);
    $endPage = min($pagination['total_pages'], $pagination['current_page'] + 2);
    
    if ($startPage > 1) {
        $html .= '<li class="page-item"><a class="page-link" href="' . $baseUrl . '?page=1">1</a></li>';
        if ($startPage > 2) {
            $html .= '<li class="page-item disabled"><span class="page-link">...</span></li>';
        }
    }
    
    for ($i = $startPage; $i <= $endPage; $i++) {
        if ($i == $pagination['current_page']) {
            $html .= '<li class="page-item active"><span class="page-link">' . $i . '</span></li>';
        } else {
            $html .= '<li class="page-item"><a class="page-link" href="' . $baseUrl . '?page=' . $i . '">' . $i . '</a></li>';
        }
    }
    
    if ($endPage < $pagination['total_pages']) {
        if ($endPage < $pagination['total_pages'] - 1) {
            $html .= '<li class="page-item disabled"><span class="page-link">...</span></li>';
        }
        $html .= '<li class="page-item"><a class="page-link" href="' . $baseUrl . '?page=' . $pagination['total_pages'] . '">' . $pagination['total_pages'] . '</a></li>';
    }
    
    // Next button
    if ($pagination['has_next']) {
        $nextPage = $pagination['current_page'] + 1;
        $html .= '<li class="page-item"><a class="page-link" href="' . $baseUrl . '?page=' . $nextPage . '">Next</a></li>';
    } else {
        $html .= '<li class="page-item disabled"><span class="page-link">Next</span></li>';
    }
    
    $html .= '</ul></nav>';
    
    return $html;
}

/**
 * Send email (basic function - can be enhanced with PHPMailer)
 */
function sendEmail($to, $subject, $message, $headers = []) {
    $defaultHeaders = [
        'From: ' . MAIL_FROM_NAME . ' <' . MAIL_FROM_EMAIL . '>',
        'Reply-To: ' . MAIL_FROM_EMAIL,
        'X-Mailer: PHP/' . phpversion(),
        'MIME-Version: 1.0',
        'Content-type: text/html; charset=UTF-8'
    ];
    
    $headers = array_merge($defaultHeaders, $headers);
    $headerString = implode("\r\n", $headers);
    
    return mail($to, $subject, $message, $headerString);
}

/**
 * Log activity to audit log
 */
function logActivity($action, $tableName = null, $recordId = null, $oldValues = null, $newValues = null) {
    try {
        $db = getDB();
        $userId = getCurrentUserId();
        $ipAddress = $_SERVER['REMOTE_ADDR'] ?? null;
        $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? null;
        
        $stmt = $db->prepare("
            INSERT INTO audit_logs (user_id, action, table_name, record_id, old_values, new_values, ip_address, user_agent)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?)
        ");
        
        $stmt->execute([
            $userId,
            $action,
            $tableName,
            $recordId,
            $oldValues ? json_encode($oldValues) : null,
            $newValues ? json_encode($newValues) : null,
            $ipAddress,
            $userAgent
        ]);
        
        return true;
    } catch (Exception $e) {
        error_log("Failed to log activity: " . $e->getMessage());
        return false;
    }
}

/**
 * Create notification
 */
function createNotification($userId, $type, $title, $message, $link = null) {
    try {
        $db = getDB();
        $stmt = $db->prepare("
            INSERT INTO notifications (user_id, type, title, message, link)
            VALUES (?, ?, ?, ?, ?)
        ");
        
        $stmt->execute([$userId, $type, $title, $message, $link]);
        return true;
    } catch (Exception $e) {
        error_log("Failed to create notification: " . $e->getMessage());
        return false;
    }
}

/**
 * Get unread notifications count
 */
function getUnreadNotificationsCount($userId) {
    try {
        $db = getDB();
        $stmt = $db->prepare("SELECT COUNT(*) FROM notifications WHERE user_id = ? AND is_read = 0");
        $stmt->execute([$userId]);
        return $stmt->fetchColumn();
    } catch (Exception $e) {
        return 0;
    }
}

/**
 * Truncate text
 */
function truncateText($text, $length = 100, $suffix = '...') {
    if (strlen($text) <= $length) {
        return $text;
    }
    return substr($text, 0, $length) . $suffix;
}

/**
 * Get setting value
 */
function getSetting($key, $default = null) {
    try {
        $db = getDB();
        $stmt = $db->prepare("SELECT value FROM settings WHERE key_name = ? LIMIT 1");
        $stmt->execute([$key]);
        $value = $stmt->fetchColumn();
        return $value !== false ? $value : $default;
    } catch (Exception $e) {
        return $default;
    }
}

/**
 * Update setting value
 */
function updateSetting($key, $value) {
    try {
        $db = getDB();
        $stmt = $db->prepare("
            INSERT INTO settings (key_name, value) VALUES (?, ?)
            ON DUPLICATE KEY UPDATE value = ?
        ");
        $stmt->execute([$key, $value, $value]);
        return true;
    } catch (Exception $e) {
        error_log("Failed to update setting: " . $e->getMessage());
        return false;
    }
}

/**
 * Escape output for HTML
 */
function e($string) {
    if ($string === null || $string === '') {
        return '';
    }
    return htmlspecialchars((string)$string, ENT_QUOTES, 'UTF-8');
}

/**
 * Check if request is AJAX
 */
function isAjaxRequest() {
    return !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && 
           strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
}

/**
 * Return JSON response
 */
function jsonResponse($data, $statusCode = 200) {
    http_response_code($statusCode);
    header('Content-Type: application/json');
    echo json_encode($data);
    exit();
}

/**
 * Get all contact information (centralized)
 */
function getContactInfo() {
    static $contactInfo = null;
    
    if ($contactInfo === null) {
        try {
            $db = getDB();
            $stmt = $db->prepare("SELECT key_name, value FROM settings WHERE category = 'contact'");
            $stmt->execute();
            $contactInfo = [];
            while ($row = $stmt->fetch()) {
                $contactInfo[$row['key_name']] = $row['value'];
            }
        } catch (Exception $e) {
            $contactInfo = [];
        }
    }
    
    return $contactInfo;
}

/**
 * Get specific contact info field
 */
function getContactField($field, $default = '') {
    $contactInfo = getContactInfo();
    return $contactInfo[$field] ?? $default;
}

/**
 * Get all social media links (centralized)
 */
function getSocialMediaLinks() {
    static $socialMedia = null;
    
    if ($socialMedia === null) {
        try {
            $db = getDB();
            $stmt = $db->prepare("SELECT key_name, value FROM settings WHERE category = 'social_media' AND value != ''");
            $stmt->execute();
            $socialMedia = [];
            while ($row = $stmt->fetch()) {
                $socialMedia[$row['key_name']] = $row['value'];
            }
        } catch (Exception $e) {
            $socialMedia = [];
        }
    }
    
    return $socialMedia;
}

/**
 * Get social media link
 */
function getSocialLink($platform, $default = '') {
    $socialMedia = getSocialMediaLinks();
    return $socialMedia[$platform] ?? $default;
}

/**
 * Display social media icons
 */
function displaySocialMediaIcons($class = 'fs-4') {
    $socialMedia = getSocialMediaLinks();
    $icons = [
        'facebook' => ['icon' => 'fab fa-facebook', 'color' => 'text-primary'],
        'twitter' => ['icon' => 'fab fa-twitter', 'color' => 'text-info'],
        'linkedin' => ['icon' => 'fab fa-linkedin', 'color' => 'text-primary'],
        'instagram' => ['icon' => 'fab fa-instagram', 'color' => 'text-danger'],
        'youtube' => ['icon' => 'fab fa-youtube', 'color' => 'text-danger'],
        'researchgate' => ['icon' => 'fab fa-researchgate', 'color' => 'text-success'],
        'orcid' => ['icon' => 'fab fa-orcid', 'color' => 'text-success']
    ];
    
    $html = '';
    foreach ($socialMedia as $platform => $url) {
        if (!empty($url) && isset($icons[$platform])) {
            $html .= '<a href="' . e($url) . '" target="_blank" class="me-3 ' . $icons[$platform]['color'] . '" title="' . ucfirst($platform) . '">';
            $html .= '<i class="' . $icons[$platform]['icon'] . ' ' . $class . '"></i>';
            $html .= '</a>';
        }
    }
    
    return $html;
}

/**
 * Get branding information (logo, site name, etc.)
 */
function getBrandingInfo() {
    static $branding = null;
    
    if ($branding === null) {
        try {
            $db = getDB();
            $stmt = $db->prepare("SELECT key_name, value FROM settings WHERE category = 'branding'");
            $stmt->execute();
            $branding = [];
            while ($row = $stmt->fetch()) {
                $branding[$row['key_name']] = $row['value'];
            }
        } catch (Exception $e) {
            $branding = [];
        }
    }
    
    return $branding;
}

/**
 * Get site name (from CMS or config)
 */
function getSiteName() {
    $branding = getBrandingInfo();
    if (!empty($branding['site_name'])) {
        return $branding['site_name'];
    }
    // Check contact info as fallback
    $contact = getContactInfo();
    if (!empty($contact['site_name'])) {
        return $contact['site_name'];
    }
    return SITE_NAME;
}

/**
 * Get logo URL
 */
function getLogoUrl() {
    $branding = getBrandingInfo();
    if (!empty($branding['logo_path'])) {
        return SITE_URL . '/assets/uploads/branding/' . $branding['logo_path'];
    }
    return null;
}

/**
 * Display formatted address
 */
function displayAddress($format = 'full') {
    $contact = getContactInfo();
    
    if ($format === 'full') {
        $parts = array_filter([
            $contact['address_line1'] ?? '',
            $contact['address_line2'] ?? '',
            $contact['city'] ?? '',
            $contact['state'] ?? '',
            $contact['postal_code'] ?? '',
            $contact['country'] ?? ''
        ]);
        return implode(', ', $parts);
    } elseif ($format === 'short') {
        $parts = array_filter([
            $contact['city'] ?? '',
            $contact['country'] ?? ''
        ]);
        return implode(', ', $parts);
    }
    
    return '';
}

/**
 * Get menu by location
 */
function getMenuByLocation($location = 'header') {
    static $menus = [];
    
    if (!isset($menus[$location])) {
        try {
            $db = getDB();
            $stmt = $db->prepare("SELECT * FROM cms_menus WHERE location = ? AND status = 'active' LIMIT 1");
            $stmt->execute([$location]);
            $menus[$location] = $stmt->fetch();
        } catch (Exception $e) {
            $menus[$location] = null;
        }
    }
    
    return $menus[$location];
}

/**
 * Get menu items by menu ID
 */
function getMenuItems($menuId, $parentId = null) {
    static $allItems = [];
    
    // Cache all items for this menu
    if (!isset($allItems[$menuId])) {
        try {
            $db = getDB();
            $stmt = $db->prepare("
                SELECT * FROM cms_menu_items 
                WHERE menu_id = ? AND status = 'active'
                ORDER BY order_num ASC, id ASC
            ");
            $stmt->execute([$menuId]);
            $allItems[$menuId] = $stmt->fetchAll();
        } catch (Exception $e) {
            $allItems[$menuId] = [];
        }
    }
    
    // Filter by parent_id
    $items = [];
    foreach ($allItems[$menuId] as $item) {
        if ($parentId === null && $item['parent_id'] === null) {
            $items[] = $item;
        } elseif ($item['parent_id'] == $parentId) {
            $items[] = $item;
        }
    }
    
    return $items;
}

/**
 * Check if menu item is visible to current user
 */
function isMenuItemVisible($item) {
    $visibility = $item['visibility'] ?? 'public';
    
    switch ($visibility) {
        case 'logged_in':
            return isLoggedIn();
        case 'logged_out':
            return !isLoggedIn();
        case 'admin':
            return isLoggedIn() && (getCurrentUserRole() === 'super_admin' || getCurrentUserRole() === 'institution_admin');
        case 'public':
        default:
            return true;
    }
}

/**
 * Render menu items (recursive for nested menus)
 */
function renderMenuItems($menuId, $parentId = null, $class = 'navbar-nav', $depth = 0) {
    $items = getMenuItems($menuId, $parentId);
    
    if (empty($items)) {
        return '';
    }
    
    $html = '';
    $listClass = $depth === 0 ? $class : 'dropdown-menu';
    
    if ($depth === 0) {
        $html .= '<ul class="' . $listClass . ' ms-auto">';
    } else {
        $html .= '<ul class="' . $listClass . '">';
    }
    
    foreach ($items as $item) {
        // Check visibility
        if (!isMenuItemVisible($item)) {
            continue;
        }
        
        // Check if item has children
        $children = getMenuItems($menuId, $item['id']);
        $hasChildren = !empty($children);
        
        // Build item classes
        $itemClass = $depth === 0 ? 'nav-item' : 'dropdown-item';
        if ($hasChildren) {
            $itemClass .= $depth === 0 ? ' dropdown' : ' dropdown-submenu';
        }
        if (!empty($item['css_class'])) {
            $itemClass .= ' ' . $item['css_class'];
        }
        
        $html .= '<li class="' . $itemClass . '">';
        
        // Build link
        $linkClass = $depth === 0 ? 'nav-link' : 'dropdown-item';
        if ($hasChildren && $depth === 0) {
            $linkClass .= ' dropdown-toggle';
        }
        
        $url = $item['url'] ?? '#';
        $target = $item['target'] ?? '_self';
        $icon = !empty($item['icon']) ? '<i class="' . e($item['icon']) . ' me-1"></i>' : '';
        
        if ($hasChildren && $depth === 0) {
            $html .= '<a class="' . $linkClass . '" href="' . e($url) . '" role="button" data-bs-toggle="dropdown" aria-expanded="false">';
        } else {
            $html .= '<a class="' . $linkClass . '" href="' . e($url) . '" target="' . e($target) . '">';
        }
        
        $html .= $icon . e($item['title']);
        $html .= '</a>';
        
        // Render children if any
        if ($hasChildren) {
            $html .= renderMenuItems($menuId, $item['id'], $class, $depth + 1);
        }
        
        $html .= '</li>';
    }
    
    $html .= '</ul>';
    
    return $html;
}

/**
 * Display menu by location
 */
function displayMenu($location = 'header', $class = 'navbar-nav') {
    $menu = getMenuByLocation($location);
    
    if (!$menu) {
        return '';
    }
    
    return renderMenuItems($menu['id'], null, $class);
}
