<?php

class Logger {
    private $conn;
    private $userId;
    private $username;
    private $userRole;
    private $ipAddress;
    private $userAgent;
    private $sessionId;

    public function __construct($conn, $userId = null, $username = null, $userRole = null) {
        $this->conn = $conn;
        $this->userId = $userId ?: 0;
        $this->username = $username ?: 'system';
        $this->userRole = $userRole ?: 'unknown';
        $this->ipAddress = $this->getClientIP();
        $this->userAgent = $_SERVER['HTTP_USER_AGENT'] ?? 'unknown';
        $this->sessionId = session_id() ?: 'no_session';
    }

    private function getClientIP() {
        $ipHeaders = [
            'HTTP_CF_CONNECTING_IP',
            'HTTP_CLIENT_IP',
            'HTTP_X_FORWARDED_FOR',
            'HTTP_X_FORWARDED',
            'HTTP_X_CLUSTER_CLIENT_IP',
            'HTTP_FORWARDED_FOR',
            'HTTP_FORWARDED',
            'REMOTE_ADDR'
        ];

        foreach ($ipHeaders as $header) {
            if (!empty($_SERVER[$header])) {
                $ip = $_SERVER[$header];
                if (strpos($ip, ',') !== false) {
                    $ipParts = explode(',', $ip);
                    $ip = trim($ipParts[0]);
                }
                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
                    return $ip;
                }
            }
        }

        return $_SERVER['REMOTE_ADDR'] ?? 'unknown';
    }

    public function log($action, $module, $details, $affectedRecordId = null, $affectedTable = null, $oldValues = null, $newValues = null) {
        if (!$this->conn) {
            error_log("Logger: No database connection available");
            return false;
        }

        try {
            $sql = "INSERT INTO system_logs
                    (user_id, username, user_role, action, module, details, ip_address, affected_record_id, affected_table, old_values, new_values, session_id, user_agent)
                    VALUES
                    (:user_id, :username, :user_role, :action, :module, :details, :ip_address, :affected_record_id, :affected_table, :old_values, :new_values, :session_id, :user_agent)";

            $stmt = $this->conn->prepare($sql);

            $oldValuesJson = json_encode($oldValues);
            $newValuesJson = json_encode($newValues);

            $stmt->bindValue(':user_id', $this->userId, PDO::PARAM_INT);
            $stmt->bindValue(':username', $this->username, PDO::PARAM_STR);
            $stmt->bindValue(':user_role', $this->userRole, PDO::PARAM_STR);
            $stmt->bindValue(':action', $action, PDO::PARAM_STR);
            $stmt->bindValue(':module', $module, PDO::PARAM_STR);
            $stmt->bindValue(':details', $details, PDO::PARAM_STR);
            $stmt->bindValue(':ip_address', $this->ipAddress, PDO::PARAM_STR);
            $stmt->bindValue(':affected_record_id', $affectedRecordId, PDO::PARAM_INT);
            $stmt->bindValue(':affected_table', $affectedTable, PDO::PARAM_STR);
            $stmt->bindValue(':old_values', $oldValuesJson, PDO::PARAM_STR);
            $stmt->bindValue(':new_values', $newValuesJson, PDO::PARAM_STR);
            $stmt->bindValue(':session_id', $this->sessionId, PDO::PARAM_STR);
            $stmt->bindValue(':user_agent', $this->userAgent, PDO::PARAM_STR);

            $result = $stmt->execute();

            if ($result) {
                error_log("Activity logged: {$action} by {$this->username} ({$this->userRole}) - UserID: {$this->userId}");
            } else {
                $errorInfo = $stmt->errorInfo();
                error_log("Logger: Failed to execute query for action {$action}. Error: " . json_encode($errorInfo));
            }

            return $result;

        } catch (Exception $e) {
            error_log("Logger error for action {$action}: " . $e->getMessage());
            error_log("Logger debug - UserID: {$this->userId}, Username: {$this->username}, Action: {$action}");
            return false;
        }
    }

    public function logAuth($event, $success = true, $additionalInfo = '') {
        $details = $success ? "Successful {$event}" : "Failed {$event}";
        if ($additionalInfo) {
            $details .= ": {$additionalInfo}";
        }

        return $this->log($event, 'authentication', $details);
    }

    public function logCRUD($operation, $module, $recordId, $tableName, $oldValues = null, $newValues = null) {
        $details = '';
        switch (strtolower($module)) {
            case 'inventory':
                $details = $this->buildInventoryDetails($operation, $newValues, $oldValues);
                break;
            case 'expenses':
                $details = $this->buildExpenseDetails($operation, $newValues, $oldValues);
                break;
            case 'shipments':
                $details = $this->buildShipmentDetails($operation, $newValues, $oldValues);
                break;
            case 'quotations':
                $details = $this->buildQuotationDetails($operation, $newValues, $oldValues);
                break;
            case 'sales':
                $details = $this->buildSaleDetails($operation, $newValues, $oldValues);
                break;
            case 'loans_laybuys':
                $details = $this->buildLoanLaybuyDetails($operation, $newValues, $oldValues);
                break;
            case 'deposits':
                $details = $this->buildDepositDetails($operation, $newValues, $oldValues);
                break;
            case 'branches':
                $details = $this->buildBranchDetails($operation, $newValues, $oldValues);
                break;
            default:
                $details = "{$operation} operation on {$tableName}";
                if ($operation === 'UPDATE' && $oldValues && $newValues) {
                    $changes = [];
                    foreach ($newValues as $key => $value) {
                        if (isset($oldValues[$key]) && $oldValues[$key] != $value) {
                            $changes[] = "{$key}: '{$oldValues[$key]}' → '{$value}'";
                        }
                    }
                    if ($changes) {
                        $details .= " - Changes: " . implode(', ', $changes);
                    }
                } elseif ($operation === 'CREATE' && $newValues) {
                    $details .= " - New record created";
                } elseif ($operation === 'DELETE') {
                    $details .= " - Record deleted";
                }
        }

        return $this->log($operation . '_' . strtoupper($tableName), $module, $details, $recordId, $tableName, $oldValues, $newValues);
    }

    public function logAdmin($action, $details, $affectedRecordId = null) {
        return $this->log('ADMIN_' . $action, 'administration', $details, $affectedRecordId);
    }

    public function logSystem($event, $details) {
        $tempUserId = $this->userId;
        $tempUsername = $this->username;
        $tempUserRole = $this->userRole;

        $this->userId = 0;
        $this->username = 'system';
        $this->userRole = 'system';

        $result = $this->log('SYSTEM_' . $event, 'system', $details);

        $this->userId = $tempUserId;
        $this->username = $tempUsername;
        $this->userRole = $tempUserRole;

        return $result;
    }

    public function setUser($userId, $username, $userRole) {
        $this->userId = $userId ?: 0;
        $this->username = $username ?: 'system';
        $this->userRole = $userRole ?: 'unknown';
    }

    public function getUserLogs($userId, $limit = 50) {
        try {
            $sql = "SELECT * FROM system_logs WHERE user_id = :user_id ORDER BY timestamp DESC LIMIT :limit";
            $stmt = $this->conn->prepare($sql);
            $stmt->bindParam(':user_id', $userId, PDO::PARAM_INT);
            $stmt->bindParam(':limit', $limit, PDO::PARAM_INT);
            $stmt->execute();
            return $stmt->fetchAll(PDO::FETCH_ASSOC);
        } catch (Exception $e) {
            error_log("Error fetching user logs: " . $e->getMessage());
            return [];
        }
    }

    public function getModuleLogs($module, $limit = 100) {
        try {
            $sql = "SELECT * FROM system_logs WHERE module = :module ORDER BY timestamp DESC LIMIT :limit";
            $stmt = $this->conn->prepare($sql);
            $stmt->bindParam(':module', $module, PDO::PARAM_STR);
            $stmt->bindParam(':limit', $limit, PDO::PARAM_INT);
            $stmt->execute();
            return $stmt->fetchAll(PDO::FETCH_ASSOC);
        } catch (Exception $e) {
            error_log("Error fetching module logs: " . $e->getMessage());
            return [];
        }
    }

    public function logSale($operation, $saleId, $saleData = null, $oldData = null) {
        $details = $this->buildSaleDetails($operation, $saleData, $oldData);
        return $this->log($operation . '_SOLD_ITEMS', 'sales', $details, $saleId, 'sold_items', $oldData, $saleData);
    }

    public function logInventory($operation, $itemId, $itemData = null, $oldData = null) {
        $details = $this->buildInventoryDetails($operation, $itemData, $oldData);
        return $this->log($operation . '_ITEMS', 'inventory', $details, $itemId, 'items', $oldData, $itemData);
    }

    public function logExpense($operation, $expenseId, $expenseData = null, $oldData = null) {
        $details = $this->buildExpenseDetails($operation, $expenseData, $oldData);
        return $this->log($operation . '_OPERATIONAL_EXPENSES', 'expenses', $details, $expenseId, 'operational_expenses', $oldData, $expenseData);
    }

    public function logOrder($operation, $orderId, $orderData = null, $oldData = null) {
        $details = $this->buildOrderDetails($operation, $orderData, $oldData);
        return $this->log($operation . '_ORDERS', 'orders', $details, $orderId, 'orders', $oldData, $orderData);
    }

    public function logQuotation($operation, $quotationId, $quotationData = null, $oldData = null) {
        $details = $this->buildQuotationDetails($operation, $quotationData, $oldData);
        return $this->log($operation . '_QUOTATIONS', 'quotations', $details, $quotationId, 'quotations', $oldData, $quotationData);
    }

    public function logInvoice($operation, $invoiceId, $invoiceData = null, $oldData = null) {
        $details = $this->buildInvoiceDetails($operation, $invoiceData, $oldData);
        return $this->log($operation . '_INVOICES', 'invoices', $details, $invoiceId, 'invoices', $oldData, $invoiceData);
    }


     public function logRequest($operation, $requestId, $requestData = null, $oldData = null) {
        $details = $this->buildQuotationDetails($operation, $requestData, $oldData);
        return $this->log($operation . '_REQUEST', 'request', $details, $requestId, 'request', $oldData, $requestData);
    }

    public function logShipment($operation, $shipmentId, $shipmentData = null, $oldData = null) {
        $details = $this->buildShipmentDetails($operation, $shipmentData, $oldData);
        return $this->log($operation . '_SHIPMENTS', 'shipments', $details, $shipmentId, 'shipments', $oldData, $shipmentData);
    }

    public function logLoanLaybuy($operation, $recordId, $recordData = null, $oldData = null) {
        $details = $this->buildLoanLaybuyDetails($operation, $recordData, $oldData);
        return $this->log($operation . '_LOANS_LAYBUYS', 'loans_laybuys', $details, $recordId, 'loans_laybuys', $oldData, $recordData);
    }

    public function logDeposit($operation, $depositId, $depositData = null, $oldData = null) {
        $details = $this->buildDepositDetails($operation, $depositData, $oldData);
        return $this->log($operation . '_DEPOSITS', 'deposits', $details, $depositId, 'deposits', $oldData, $depositData);
    }

    public function logBranch($operation, $branchId, $branchData = null, $oldData = null) {
        $details = $this->buildBranchDetails($operation, $branchData, $oldData);
        return $this->log($operation . '_BRANCHES', 'branches', $details, $branchId, 'branches', $oldData, $branchData);
    }

    public function logUser($operation, $userId, $userData = null, $oldData = null) {
        $details = $this->buildUserDetails($operation, $userData, $oldData);
        return $this->log($operation . '_USERS', 'users', $details, $userId, 'users', $oldData, $userData);
    }

    private function buildUserDetails($operation, $data, $oldData) {
        if (!$data) return '';

        switch ($operation) {
            case 'CREATE':
                return "Created new user account: " . ($data['username'] ?? 'Unknown') .
                        " (Role: " . ($data['role'] ?? 'N/A') . ")";
            case 'UPDATE':
                $changes = [];
                if ($oldData && $data) {
                    foreach ($data as $key => $value) {
                        if (isset($oldData[$key]) && $oldData[$key] != $value) {
                            if ($key === 'password') {
                                $changes[] = "Password changed";
                            } else {
                                $changes[] = "{$key}: '{$oldData[$key]}' → '{$value}'";
                            }
                        }
                    }
                }
                $changeStr = $changes ? " - Changes: " . implode(', ', $changes) : "";
                return "Updated user account: " . ($data['username'] ?? $oldData['username'] ?? 'Unknown') . $changeStr;
            case 'DELETE':
                $username = $oldData['username'] ?? 'Unknown User';
                return "Deleted user account: {$username}";
            default:
                return $operation . " operation on users";
        }
    }

    public function logBatch($operations) {
        $results = [];
        foreach ($operations as $operation) {
            $method = 'log' . ucfirst(strtolower($operation['type']));
            if (method_exists($this, $method)) {
                $results[] = call_user_func_array([$this, $method], $operation['params']);
            } else {
                $results[] = $this->log(
                    $operation['action'],
                    $operation['module'],
                    $operation['details'],
                    $operation['recordId'] ?? null,
                    $operation['table'] ?? null,
                    $operation['oldData'] ?? null,
                    $operation['newData'] ?? null
                );
            }
        }
        return $results;
    }

    private function buildSaleDetails($operation, $data, $oldData) {
        if (!$data && $operation !== 'DELETE') return '';

        switch ($operation) {
            case 'CREATE':
                return "Created sale for item: " . ($data['item_name'] ?? 'Unknown') .
                        " (Code: " . ($data['unique_code'] ?? 'N/A') . ")" .
                        " Amount: $" . ($data['total_price'] ?? '0.00') .
                        " Customer: " . ($data['customer_name'] ?? 'N/A');
            case 'UPDATE':
                return "Updated sale details";
            case 'DELETE':
                return "Deleted sale record";
            case 'CONVERT_QUOTATION':
                return "Converted quotation to sale";
            default:
                return $operation . " operation on sale";
        }
    }

    private function buildInventoryDetails($operation, $data, $oldData) {
        if (!$data && $operation !== 'DELETE') return '';

        switch ($operation) {
            case 'CREATE':
                if (isset($data['items_count']) && $data['items_count'] > 1) {
                    $itemType = 'item';
                    if (isset($data['technical_specs']) && !empty($data['technical_specs']) && $data['technical_specs'] !== 'No technical specifications provided') {
                        $itemType = 'detailed item';
                    } elseif (isset($data['serial_number']) && !empty($data['serial_number'])) {
                        $itemType = 'detailed item';
                    } elseif (isset($data['warranty_months']) && !empty($data['warranty_months'])) {
                        $itemType = 'detailed item';
                    } elseif ((isset($data['brand']) && !empty($data['brand'])) || (isset($data['model']) && !empty($data['model']))) {
                        $itemType = 'detailed item';
                    } else {
                        $itemType = 'simple item';
                    }

                    return "Added {$data['items_count']} {$itemType}s to warehouse inventory";
                } else {
                    $itemType = 'item';
                    if (isset($data['technical_specs']) && !empty($data['technical_specs']) && $data['technical_specs'] !== 'No technical specifications provided') {
                        $itemType = 'detailed item';
                    } elseif (isset($data['serial_number']) && !empty($data['serial_number'])) {
                        $itemType = 'detailed item';
                    } elseif (isset($data['warranty_months']) && !empty($data['warranty_months'])) {
                        $itemType = 'detailed item';
                    } elseif ((isset($data['brand']) && !empty($data['brand'])) || (isset($data['model']) && !empty($data['model']))) {
                        $itemType = 'detailed item';
                    } else {
                        $itemType = 'simple item';
                    }

                    return "Added new {$itemType}: " . ($data['item_name'] ?? 'Unknown') .
                            " (Code: " . ($data['unique_code'] ?? 'N/A') . ")" .
                            " Price: MWK" . number_format(($data['unit_price'] ?? 0), 2);
                }
            case 'UPDATE':
                $changes = [];
                if ($oldData && $data) {
                    foreach ($data as $key => $value) {
                        if (isset($oldData[$key]) && $oldData[$key] != $value) {
                            $changes[] = "{$key}: '{$oldData[$key]}' → '{$value}'";
                        }
                    }
                }
                $changeStr = $changes ? " - Changes: " . implode(', ', $changes) : "";
                return "Updated item: " . ($data['item_name'] ?? $oldData['item_name'] ?? 'Unknown') . $changeStr;
            case 'DELETE':
                $itemName = $oldData['item_name'] ?? 'Unknown Item';
                $itemCode = $oldData['unique_code'] ?? 'N/A';
                $branchName = $this->getBranchName($oldData['current_location_id'] ?? null);
                return "Deleted item: {$itemName} (Code: {$itemCode}) from {$branchName}";
            case 'IMPORT':
                return "Bulk imported items to inventory";
            default:
                return $operation . " operation on inventory";
        }
    }

    private function buildExpenseDetails($operation, $data, $oldData) {
        if (!$data && $operation !== 'DELETE') return '';

        switch ($operation) {
            case 'CREATE':
                $amount = $data['amount'] ?? 0;
                $category = $data['category_name'] ?? 'N/A';
                $description = $data['description'] ?? 'No description';
                return "Recorded expense: {$description} - Amount: MWK" . number_format($amount, 2) . " - Category: {$category}";
            case 'UPDATE':
                $changes = [];
                if ($oldData && $data) {
                    foreach ($data as $key => $value) {
                        if (isset($oldData[$key]) && $oldData[$key] != $value) {
                            if ($key === 'amount') {
                                $changes[] = "Amount: MWK" . number_format($oldData[$key], 2) . " → MWK" . number_format($value, 2);
                            } else {
                                $changes[] = "{$key}: '{$oldData[$key]}' → '{$value}'";
                            }
                        }
                    }
                }
                $changeStr = $changes ? " - Changes: " . implode(', ', $changes) : "";
                return "Updated expense record{$changeStr}";
            case 'DELETE':
                $amount = $oldData['amount'] ?? 0;
                $category = $oldData['category_name'] ?? 'N/A';
                $description = $oldData['description'] ?? 'No description';
                return "Deleted expense: {$description} - Amount: MWK" . number_format($amount, 2) . " - Category: {$category}";
            default:
                return $operation . " operation on expenses";
        }
    }

    private function buildOrderDetails($operation, $data, $oldData) {
        if (!$data && $operation !== 'DELETE') return '';

        switch ($operation) {
            case 'CREATE':
                return "Created order: " . ($data['item_name'] ?? 'Unknown') .
                        " Amount: $" . ($data['price'] ?? '0.00') .
                        " Customer: " . ($data['customer_name'] ?? 'N/A');
            case 'UPDATE':
                return "Updated order details";
            case 'DELETE':
                return "Cancelled/deleted order";
            default:
                return $operation . " operation on orders";
        }
    }

    private function buildQuotationDetails($operation, $data, $oldData) {
        if (!$data && $operation !== 'DELETE') return '';

        switch ($operation) {
            case 'CREATE':
                $customer = $data['customer_name'] ?? 'Unknown Customer';
                $total = $data['total_amount'] ?? 0;
                $itemsCount = $data['items_count'] ?? 1;
                $quotationNumber = $data['quotation_number'] ?? 'N/A';
                return "Created quotation #{$quotationNumber} for {$customer} - {$itemsCount} item(s) - Total: MWK" . number_format($total, 2);
            case 'UPDATE':
                $changes = [];
                if ($oldData && $data) {
                    foreach ($data as $key => $value) {
                        if (isset($oldData[$key]) && $oldData[$key] != $value) {
                            if ($key === 'total_amount') {
                                $changes[] = "Total: MWK" . number_format($oldData[$key], 2) . " → MWK" . number_format($value, 2);
                            } else {
                                $changes[] = "{$key}: '{$oldData[$key]}' → '{$value}'";
                            }
                        }
                    }
                }
                $changeStr = $changes ? " - Changes: " . implode(', ', $changes) : "";
                return "Updated quotation details{$changeStr}";
            case 'DELETE':
                $quotationNumber = $oldData['quotation_number'] ?? 'N/A';
                $customer = $oldData['customer_name'] ?? 'Unknown Customer';
                $total = $oldData['total_amount'] ?? 0;
                return "Deleted quotation #{$quotationNumber} for {$customer} - Total: MWK" . number_format($total, 2);
            case 'CONVERT_TO_SALE':
                $quotationNumber = $data['quotation_number'] ?? 'N/A';
                $transactionId = $data['transaction_id'] ?? 'N/A';
                $total = $data['total_amount'] ?? 0;
                return "Converted quotation #{$quotationNumber} to sale (Transaction: {$transactionId}) - Total: MWK" . number_format($total, 2);
            case 'DRAFT_SAVE':
                $customer = $data['customer_name'] ?? 'Unknown Customer';
                $total = $data['total_amount'] ?? 0;
                $quotationNumber = $data['quotation_number'] ?? 'N/A';
                return "Saved quotation #{$quotationNumber} for {$customer} as a draft - Total: MWK" . number_format($total, 2);
            default:
                return $operation . " operation on quotations";
        }
    }

    private function buildInvoiceDetails($operation, $data, $oldData) {
        if (!$data && $operation !== 'DELETE') return '';

        switch ($operation) {
            case 'CREATE':
                $customer = $data['customer_name'] ?? 'Unknown Customer';
                $total = $data['total_amount'] ?? 0;
                $itemsCount = $data['items_count'] ?? 1;
                $invoiceNumber = $data['invoice_number'] ?? 'N/A';
                return "Created invoice #{$invoiceNumber} for {$customer} - {$itemsCount} item(s) - Total: MWK" . number_format($total, 2);
            case 'UPDATE':
                $changes = [];
                if ($oldData && $data) {
                    foreach ($data as $key => $value) {
                        if (isset($oldData[$key]) && $oldData[$key] != $value) {
                            if ($key === 'total_amount') {
                                $changes[] = "Total: MWK" . number_format($oldData[$key], 2) . " → MWK" . number_format($value, 2);
                            } else {
                                $changes[] = "{$key}: '{$oldData[$key]}' → '{$value}'";
                            }
                        }
                    }
                }
                $changeStr = $changes ? " - Changes: " . implode(', ', $changes) : "";
                return "Updated invoice details{$changeStr}";
            case 'DELETE':
                $invoiceNumber = $oldData['invoice_number'] ?? 'N/A';
                $customer = $oldData['customer_name'] ?? 'Unknown Customer';
                $total = $oldData['total_amount'] ?? 0;
                return "Deleted invoice #{$invoiceNumber} for {$customer} - Total: MWK" . number_format($total, 2);
            case 'CONVERT_TO_SALE':
                $invoiceNumber = $data['invoice_number'] ?? 'N/A';
                $transactionId = $data['transaction_id'] ?? 'N/A';
                $total = $data['total_amount'] ?? 0;
                return "Converted invoice #{$invoiceNumber} to sale (Transaction: {$transactionId}) - Total: MWK" . number_format($total, 2);
            case 'DRAFT_SAVE':
                $customer = $data['customer_name'] ?? 'Unknown Customer';
                $total = $data['total_amount'] ?? 0;
                $invoiceNumber = $data['invoice_number'] ?? 'N/A';
                return "Saved invoice #{$invoiceNumber} for {$customer} as a draft - Total: MWK" . number_format($total, 2);
            default:
                return $operation . " operation on invoices";
        }
    }

    private function buildShipmentDetails($operation, $data, $oldData) {
        if (!$data) return '';

        switch ($operation) {
            case 'CREATE':
                $fromBranchName = $data['from_branch_name'] ?? $this->getBranchName($data['from_branch_id'] ?? null);
                $toBranchName = $data['to_branch_name'] ?? $this->getBranchName($data['to_branch_id'] ?? null);
                $itemsCount = $data['items_count'] ?? 1;

                return "Created shipment: {$itemsCount} item(s) from {$fromBranchName} to {$toBranchName}";
                break;
            case 'UPDATE':
                return "Updated shipment status to: " . ($data['status'] ?? 'Unknown');
                break;
            case 'UPDATE_STATUS':
                $oldStatus = $oldData['status'] ?? 'Unknown';
                $newStatus = $data['status'] ?? 'Unknown';
                return "Changed shipment status from '{$oldStatus}' to '{$newStatus}'";
                break;
            case 'VERIFY_ITEM':
                $itemName = $data['item_name'] ?? 'Unknown Item';
                $itemCode = $data['unique_code'] ?? 'N/A';
                $discrepancy = $data['discrepancy_reported'] ? ' (with discrepancy)' : '';
                return "Verified shipment item: {$itemName} (Code: {$itemCode}){$discrepancy}";
                break;
            case 'COMPLETE':
                $itemsCount = $data['items_count'] ?? 1;
                $verifiedItems = $data['verified_items'] ?? $itemsCount;
                $discrepancyItems = $data['discrepancy_items'] ?? 0;

                $message = "Completed shipment verification: {$verifiedItems} of {$itemsCount} items verified";
                if ($discrepancyItems > 0) {
                    $message .= " ({$discrepancyItems} with discrepancies)";
                }
                return $message;
                break;
            default:
                return $operation . " operation on shipments";
        }
    }

    private function getBranchName($branchId) {
        if (!$branchId) {
            return 'Headquarters';
        }

        try {
            $sql = "SELECT branch_name FROM branches WHERE branch_id = :branch_id";
            $stmt = $this->conn->prepare($sql);
            $stmt->bindParam(':branch_id', $branchId, PDO::PARAM_INT);
            $stmt->execute();
            $result = $stmt->fetch(PDO::FETCH_ASSOC);
            return $result ? $result['branch_name'] : 'Unknown Branch';
        } catch (Exception $e) {
            error_log("Error fetching branch name for ID {$branchId}: " . $e->getMessage());
            return 'Unknown Branch';
        }
    }

    private function buildLoanLaybuyDetails($operation, $data, $oldData) {
        if (!$data && $operation !== 'DELETE') return '';

        switch ($operation) {
            case 'CREATE':
                return "Created laybuy record for: " . ($data['item_name'] ?? 'Unknown') .
                        " Amount: $" . ($data['amount'] ?? '0.00') .
                        " Customer: " . ($data['customer_name'] ?? 'N/A');
            case 'UPDATE':
                return "Updated laybuy record";
            case 'DELETE':
                return "Deleted laybuy record";
            default:
                return $operation . " operation on laybuys";
        }
    }

    private function buildDepositDetails($operation, $data, $oldData) {
        if (!$data && $operation !== 'DELETE') return '';

        switch ($operation) {
            case 'CREATE':
                return "Recorded deposit of $" . ($data['amount'] ?? '0.00') .
                        " on " . ($data['deposit_date'] ?? 'Unknown date');
            case 'UPDATE':
                return "Updated deposit record";
            case 'DELETE':
                return "Deleted deposit record";
            default:
                return $operation . " operation on deposits";
        }
    }

    private function buildBranchDetails($operation, $data, $oldData) {
        if (!$data && $operation !== 'DELETE') return '';

        switch ($operation) {
            case 'CREATE':
                return "Created new branch: " . ($data['branch_name'] ?? 'Unknown') .
                        " Location: " . ($data['branch_address'] ?? 'N/A');
            case 'UPDATE':
                return "Updated branch information: " . ($data['branch_name'] ?? 'Unknown');
            case 'DELETE':
                return "Deleted branch: " . ($oldData['branch_name'] ?? 'Unknown');
            default:
                return $operation . " operation on branches";
        }
    }
}
?>