<?php
// src/core/functions.php
// ไฟล์นี้รวบรวมฟังก์ชันช่วยเหลือต่างๆ ที่ใช้ในระบบ

// ตรวจสอบและเรียกใช้ Database.php ก่อน เพื่อให้คลาส Database พร้อมใช้งาน
if (file_exists(__DIR__ . '/Database.php')) {
    require_once __DIR__ . '/Database.php';
} else {
    die('ข้อผิดพลาดร้ายแรง: ไม่พบไฟล์ src/core/Database.php กรุณาตรวจสอบการตั้งค่าโปรเจกต์');
}

// เริ่ม session ถ้ายังไม่ได้เริ่ม และ headers ยังไม่ถูกส่ง
if (session_status() == PHP_SESSION_NONE && !headers_sent()) {
    session_start();
}

// --- ฟังก์ชันพื้นฐาน ---
function redirect($url_path) {
    $final_url = $url_path;
    if (!(strpos($url_path, 'http://') === 0 || strpos($url_path, 'https://') === 0)) {
        if (defined('BASE_URL')) {
            $final_url = rtrim(BASE_URL, '/') . '/' . ltrim($url_path, '/');
        } else {
            $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http";
            $host = $_SERVER['HTTP_HOST'];
            $script_dir = rtrim(dirname($_SERVER['SCRIPT_NAME']), '/\\');
            $final_url = $protocol . "://" . $host . $script_dir . '/' . ltrim($url_path, '/');
        }
    }
    header('Location: ' . $final_url);
    exit();
}

function esc($string) {
    return htmlspecialchars((string)$string, ENT_QUOTES, 'UTF-8');
}

function isLoggedIn() {
    return isset($_SESSION['user_id']);
}

function asset($path) {
    if (defined('BASE_URL')) {
        return rtrim(BASE_URL, '/') . '/' . ltrim($path, '/');
    }
    return '/' . ltrim($path, '/');
}

function url($path = '') {
    if (defined('BASE_URL')) {
        return rtrim(BASE_URL, '/') . '/' . ltrim($path, '/');
    }
    $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http";
    $host = $_SERVER['HTTP_HOST'];
    $script_name_path = dirname($_SERVER['SCRIPT_NAME']);
    $script_dir = ($script_name_path === '/' || $script_name_path === '\\') ? '' : rtrim($script_name_path, '/\\');
    return $protocol . "://" . $host . $script_dir . '/' . ltrim($path, '/');
}


// --- CSRF Protection Functions (IMPROVED) ---
function generate_csrf_token() {
    if (empty($_SESSION['csrf_token'])) {
        $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    }
    return $_SESSION['csrf_token'];
}

/**
 * IMPROVED: ปรับปรุงฟังก์ชัน validate_csrf_token ให้จัดการการลบ token เอง
 * @param string $submitted_token Token ที่ส่งมาจากฟอร์ม
 * @param bool $one_time_use ถ้าเป็น true, token จะถูกลบหลังจากตรวจสอบผ่าน (ปลอดภัยกว่า)
 * @return bool
 */
function validate_csrf_token($submitted_token, $one_time_use = true) {
    if (isset($_SESSION['csrf_token']) && hash_equals($_SESSION['csrf_token'], (string)$submitted_token)) {
        if ($one_time_use) {
            unset($_SESSION['csrf_token']);
        }
        return true;
    }
    return false;
}

function csrf_input_field() {
    $token = generate_csrf_token();
    return '<input type="hidden" name="csrf_token" value="' . esc($token) . '">';
}

function csrf_input_field_for_js() {
    $token = generate_csrf_token();
    $escaped_token = esc($token);
    return "const csrfInputJs = document.createElement('input'); csrfInputJs.type = 'hidden'; csrfInputJs.name = 'csrf_token'; csrfInputJs.value = '" . $escaped_token . "'; if(typeof form !== 'undefined' && form instanceof HTMLFormElement) { form.appendChild(csrfInputJs); } else { console.warn('CSRF JS Helper: form variable not found or not a form element for CSRF token.'); }";
}

function check_csrf_token_and_redirect($redirect_url = 'dashboard.php', $method = 'POST') {
    $token_valid = false;
    $submitted_token = null;
    $is_post = strtoupper($method) === 'POST';

    if ($is_post && isset($_POST['csrf_token'])) {
        $submitted_token = $_POST['csrf_token'];
    } elseif (!$is_post && isset($_GET['csrf_token'])) {
        $submitted_token = $_GET['csrf_token'];
    }
    
    // IMPROVED: ปรับการเรียกใช้ให้สอดคล้องกับฟังก์ชันใหม่
    // สำหรับ POST, token จะเป็น one-time use. สำหรับ GET อาจจะอนุญาตให้ใช้ซ้ำได้
    $token_valid = validate_csrf_token($submitted_token, $is_post);

    if (!$token_valid) {
        $_SESSION['alert'] = ['type' => 'error', 'title' => 'การดำเนินการไม่ถูกต้อง', 'text' => 'CSRF token ไม่ถูกต้อง หรือหมดอายุ กรุณาลองอีกครั้ง'];
        redirect(url($redirect_url));
    }
}

// --- Notification Functions (IMPROVED FOR PERFORMANCE) ---
/**
 * IMPROVED: สร้างการแจ้งเตือนโดยรับ Database object เข้ามาเพื่อลดการเชื่อมต่อซ้ำซ้อน
 * @param Database $db Object ของคลาส Database ที่เชื่อมต่อแล้ว
 * @param int $user_id ID ของผู้ใช้
 * @param string $message ข้อความ
 * @return bool
 */
function create_notification(Database $db, $user_id, $message, $link = null, $type = null, $related_id = null) {
    if (empty($user_id) || empty($message)) {
        return false;
    }
    try {
        $db->query("INSERT INTO notifications (user_id, message, link, type, related_id, is_read, created_at) 
                    VALUES (:user_id, :message, :link, :type, :related_id, FALSE, CURRENT_TIMESTAMP)");
        $db->bind(':user_id', (int)$user_id);
        $db->bind(':message', $message);
        $db->bind(':link', $link);
        $db->bind(':type', $type);
        $db->bind(':related_id', $related_id ? (int)$related_id : null);
        return $db->execute();
    } catch (Exception $e) {
        error_log("Error creating notification for user {$user_id}: " . $e->getMessage());
        return false;
    }
}

/**
 * IMPROVED: ดึงการแจ้งเตือนโดยรับ Database object
 * @param Database $db Object ของคลาส Database
 * @param int $user_id ID ของผู้ใช้
 * @return array
 */
function get_unread_notifications(Database $db, $user_id, $limit = 7) {
    if (empty($user_id)) return [];
    try {
        $db->query("SELECT * FROM notifications WHERE user_id = :user_id AND is_read = FALSE ORDER BY created_at DESC LIMIT :limit_val");
        $db->bind(':user_id', (int)$user_id);
        $db->bind(':limit_val', (int)$limit);
        return $db->resultSet();
    } catch (Exception $e) {
        error_log("Error fetching unread notifications for user {$user_id}: " . $e->getMessage());
        return [];
    }
}

/**
 * IMPROVED: นับการแจ้งเตือนโดยรับ Database object
 * @param Database $db Object ของคลาส Database
 * @param int $user_id ID ของผู้ใช้
 * @return int
 */
function count_unread_notifications(Database $db, $user_id) {
    if (empty($user_id)) return 0;
    try {
        $db->query("SELECT COUNT(id) as unread_count FROM notifications WHERE user_id = :user_id AND is_read = FALSE");
        $db->bind(':user_id', (int)$user_id);
        $result = $db->single();
        return $result ? (int)$result['unread_count'] : 0;
    } catch (Exception $e) {
        error_log("Error counting unread notifications for user {$user_id}: " . $e->getMessage());
        return 0;
    }
}

// --- Menu Helper Functions (IMPROVED WITH COMMENTS) ---
if (!function_exists('isActiveMenu')) {
    /**
     * ตรวจสอบว่าเมนูที่กำหนดควรจะแสดงเป็น 'active' หรือไม่
     * @param string $link_identifier Key ของเมนู หรือชื่อไฟล์ .php
     * @param string $context 'sidebar' หรือ 'navbar' เพื่อกำหนด class ที่จะใช้
     * @return string CSS class สำหรับสถานะ active หรือ inactive
     */
    function isActiveMenu($link_identifier, $context = 'sidebar') {
        $current_page_filename = basename($_SERVER['SCRIPT_FILENAME']);
        $active_class = ($context === 'navbar') ? "bg-blue-700 text-white" : "bg-gray-700 text-white";
        $inactive_class = ($context === 'navbar') ? 'text-blue-100 hover:bg-blue-500 hover:text-white' : 'hover:bg-gray-600 hover:text-white';

        // IMPROVEMENT: เพิ่ม Comment อธิบาย Logic ที่ซับซ้อน
        // 1. ตรวจสอบจากกลุ่มเมนูที่กำหนดไว้ (สำหรับเมนูแม่ที่มีเมนูย่อยหลายหน้า)
        $menu_page_groups = [
            'data_management_parent' => ['departments_list.php', 'department_add.php', 'department_edit.php', /* ... etc ... */ 'import_materials.php'],
            'approval_stock_parent' => ['stock_management.php', 'material_requests_approval.php', /* ... etc ... */ 'maintenance_requests_process.php'],
            'user_actions_parent' => ['create_material_request.php', 'material_request_history.php', /* ... etc ... */ 'view_maintenance_request.php'],
            'reports_parent' => ['report_material_stock.php', 'report_material_disbursement.php', /* ... etc ... */ 'report_maintenance_requests.php'],
            'account_parent' => ['edit_profile.php', 'change_password.php', /* ... etc ... */ 'users_deleted_list.php']
        ];
        if (isset($menu_page_groups[$link_identifier]) && in_array($current_page_filename, $menu_page_groups[$link_identifier])) {
            return $active_class;
        }
        
        // 2. ตรวจสอบชื่อไฟล์ตรงๆ
        if ($link_identifier === $current_page_filename) {
            return $active_class;
        }

        // 3. ตรวจสอบหน้าที่เกี่ยวข้อง (เช่น _add, _edit, _process จาก list)
        $base_identifier = strtok($link_identifier, '.');
        $crud_suffixes = ['_list.php', '_add.php', '_edit.php', '_process.php', '_view.php', '_history.php', '_deleted_list.php'];
        foreach ($crud_suffixes as $crud_suffix) {
            if ($current_page_filename === $base_identifier . $crud_suffix) {
                return $active_class;
            }
        }
        
        // 4. ตรวจสอบกรณีพิเศษอื่นๆ
        if (strpos($link_identifier, '_parent') === false && strpos($current_page_filename, $base_identifier) === 0) {
            if (strlen($base_identifier) > 2 && (substr($current_page_filename, strlen($base_identifier), 1) === '_' || $current_page_filename === $base_identifier . 's.php')) {
                return $active_class;
            } elseif ($current_page_filename === $base_identifier . '.php') {
                return $active_class;
            }
        }

        return $inactive_class;
    }
}
// ส่วนที่เหลือของ Menu Helper และ Badge Helper Functions ไม่มีการเปลี่ยนแปลงเนื่องจากดีอยู่แล้ว...
if (!function_exists('render_navbar_menu_item')) {
    function render_navbar_menu_item($text, $url, $icon_class, $active_segment_key, $sub_items = []) {
        $isActiveClasses = isActiveMenu($active_segment_key, 'navbar'); 
        $hasSubItems = !empty($sub_items);
        $base_link_classes = "px-3 py-2 rounded-md text-sm font-medium transition-colors duration-150 ease-in-out flex items-center";
        $link_classes = $base_link_classes . " " . $isActiveClasses;
        
        $is_directly_active = (strpos($isActiveClasses, 'bg-blue-700') !== false);
        $arrow_color_class = $is_directly_active ? 'text-white' : 'text-blue-200 group-hover:text-white';

        if ($hasSubItems) {
            $html = '<div class="relative group navbar-parent-group">';
            $html .= '<button type="button" class="' . $link_classes . ' navbar-dropdown-toggle">';
            $html .= ($icon_class ? '<i class="' . $icon_class . ' mr-1 md:mr-2 text-base"></i>' : '');
            $html .= '<span class="hidden lg:inline">' . esc($text) . '</span>';
            $html .= '<span class="hidden md:inline lg:hidden">' . esc(mb_strimwidth($text,0,3,"..")) . '</span>'; 
            $html .= '<svg class="ml-1 h-5 w-5 ' . $arrow_color_class . '" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" /></svg>';
            $html .= '</button>';
            $html .= '<div class="navbar-submenu absolute left-0 mt-2 w-64 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 opacity-0 scale-95 invisible group-hover:opacity-100 group-hover:scale-100 group-hover:visible transition-all ease-out duration-100 transform z-30">';
            $html .= '<div class="py-1" role="menu" aria-orientation="vertical">';
            foreach ($sub_items as $sub_item) {
                if (isset($sub_item['roles']) && !in_array($_SESSION['role'] ?? null, $sub_item['roles'])) continue;
                
                $subIsActiveClasses = isActiveMenu($sub_item['active_segment'], 'navbar');
                $isSubItemActive = (strpos($subIsActiveClasses, 'bg-blue-50') !== false);
                $sub_link_classes = "block px-4 py-2 text-sm " . ($isSubItemActive ? "bg-blue-50 text-blue-700 font-semibold" : "text-gray-700 hover:bg-gray-100 hover:text-gray-900");

                $html .= '<a href="' . url($sub_item['url']) . '" class="' . $sub_link_classes . ' flex items-center" role="menuitem">';
                $html .= ($sub_item['icon_class'] ? '<i class="' . $sub_item['icon_class'] . ' fa-fw mr-2 w-4 text-center"></i>' : '<span class="w-4 mr-2"></span>') . esc($sub_item['text']);
                $html .= '</a>';
            }
            $html .= '</div></div></div>';
            return $html;
        } else { 
            $html = '<a href="' . url($url) . '" class="' . $link_classes . '">';
            $html .= ($icon_class ? '<i class="' . $icon_class . ' mr-1 md:mr-2 text-base"></i>' : '');
            $html .= '<span class="hidden lg:inline">' . esc($text) . '</span>';
            $html .= '<span class="hidden md:inline lg:hidden">' . esc(mb_strimwidth($text,0,3,"..")) . '</span>';
            $html .= '</a>';
            return $html;
        }
    }
}

// --- Badge Helper Functions ---
if (!function_exists('getMaterialRequestStatusBadge')) {
    function getMaterialRequestStatusBadge($status) {
        $base_class = "px-2 inline-flex text-xs leading-5 font-semibold rounded-full";
        $status_text = ''; $color_classes = '';
        switch (strtolower($status ?? '')) {
            case 'pending': $status_text = 'รออนุมัติ'; $color_classes = 'bg-yellow-100 text-yellow-800'; break;
            case 'approved_by_officer': $status_text = 'อนุมัติแล้ว'; $color_classes = 'bg-blue-100 text-blue-800'; break;
            case 'rejected_by_officer': $status_text = 'ไม่อนุมัติ'; $color_classes = 'bg-red-100 text-red-800'; break;
            case 'disbursed': $status_text = 'จ่ายของแล้ว'; $color_classes = 'bg-green-100 text-green-800'; break;
            case 'cancelled': $status_text = 'ยกเลิก'; $color_classes = 'bg-gray-200 text-gray-700'; break;
            default: $status_text = esc(ucfirst(str_replace('_', ' ', $status ?? 'ไม่ทราบ'))); $color_classes = 'bg-gray-300 text-gray-800'; break;
        }
        return "<span class=\"{$base_class} {$color_classes}\">{$status_text}</span>";
    }
}
if (!function_exists('getEquipmentLoanStatusBadge')) {
    function getEquipmentLoanStatusBadge($status, $endDate = null) {
        $base_class = "px-2 inline-flex text-xs leading-5 font-semibold rounded-full";
        $status_text = ''; $color_classes = '';
        if ($status === 'loaned_out' && $endDate && strtotime($endDate) < strtotime(date('Y-m-d'))) {
             return "<span class=\"{$base_class} bg-red-200 text-red-900\">เกินกำหนดคืน</span>";
        }
        switch (strtolower($status ?? '')) {
            case 'pending': $status_text = 'รออนุมัติ'; $color_classes = 'bg-yellow-100 text-yellow-800'; break;
            case 'approved': $status_text = 'อนุมัติแล้ว (รอรับของ)'; $color_classes = 'bg-blue-100 text-blue-800'; break;
            case 'rejected': $status_text = 'ไม่อนุมัติ'; $color_classes = 'bg-red-100 text-red-800'; break;
            case 'loaned_out': $status_text = 'ยืมอยู่'; $color_classes = 'bg-purple-100 text-purple-800'; break;
            case 'returned': $status_text = 'คืนแล้ว'; $color_classes = 'bg-green-100 text-green-800'; break;
            case 'overdue': $status_text = 'เกินกำหนด'; $color_classes = 'bg-orange-100 text-orange-800'; break; 
            case 'cancelled': $status_text = 'ยกเลิก'; $color_classes = 'bg-gray-200 text-gray-700'; break;
            default: $status_text = esc(ucfirst(str_replace('_', ' ', $status ?? 'ไม่ทราบ'))); $color_classes = 'bg-gray-300 text-gray-800'; break;
        }
        return "<span class=\"{$base_class} {$color_classes}\">{$status_text}</span>";
    }
}
if (!function_exists('getEquipmentStatusBadge')) {
    function getEquipmentStatusBadge($status, $endDateForLoanContext = null) {
        $base_class = "px-2 inline-flex text-xs leading-5 font-semibold rounded-full";
        $status_text = ''; $color_classes = '';
        if ($status === 'on_loan' && $endDateForLoanContext && strtotime($endDateForLoanContext) < strtotime(date('Y-m-d'))) {
             return "<span class=\"{$base_class} bg-red-200 text-red-900\">ถูกยืม (เกินกำหนด)</span>";
        }
        switch (strtolower($status ?? '')) {
            case 'available': $status_text = 'พร้อมใช้งาน'; $color_classes = 'bg-green-100 text-green-800'; break;
            case 'on_loan': $status_text = 'ถูกยืม'; $color_classes = 'bg-blue-100 text-blue-800'; break;
            case 'damaged': $status_text = 'ชำรุด'; $color_classes = 'bg-yellow-100 text-yellow-800'; break;
            case 'lost': $status_text = 'สูญหาย'; $color_classes = 'bg-red-100 text-red-800'; break;
            case 'under_maintenance': $status_text = 'ซ่อมบำรุง'; $color_classes = 'bg-purple-100 text-purple-800'; break;
            case 'disposed': $status_text = 'จำหน่ายแล้ว'; $color_classes = 'bg-gray-400 text-gray-700'; break;
            default: $status_text = esc(ucfirst(str_replace('_', ' ', $status ?? 'ไม่ทราบ'))); $color_classes = 'bg-gray-300 text-gray-800'; break;
        }
        return "<span class=\"{$base_class} {$color_classes}\">{$status_text}</span>";
    }
}
if (!function_exists('getMaintenanceStatusBadge')) {
    function getMaintenanceStatusBadge($status) {
        $base_class = "px-2 inline-flex text-xs leading-5 font-semibold rounded-full";
        $status_text = ''; $color_classes = '';
        switch (strtolower($status ?? '')) {
            case 'pending_repair': $status_text = 'รอซ่อม'; $color_classes = 'bg-yellow-100 text-yellow-800'; break;
            case 'in_progress': $status_text = 'กำลังดำเนินการ'; $color_classes = 'bg-blue-100 text-blue-800'; break;
            case 'completed': $status_text = 'ซ่อมเสร็จแล้ว'; $color_classes = 'bg-green-100 text-green-800'; break;
            case 'cannot_repair': $status_text = 'ซ่อมไม่ได้'; $color_classes = 'bg-red-100 text-red-800'; break;
            case 'cancelled': $status_text = 'ยกเลิก'; $color_classes = 'bg-gray-200 text-gray-700'; break;
            default: $status_text = esc(ucfirst(str_replace('_', ' ', $status ?? 'ไม่ทราบสถานะ'))); $color_classes = 'bg-gray-300 text-gray-800'; break;
        }
        return "<span class=\"{$base_class} {$color_classes}\">{$status_text}</span>";
    }
}
?>