<?php
/**
 * Helper Functions
 * LandSales Pro - Common utility functions used throughout the application
 */

if (!defined('APP_RUNNING')) {
    define('APP_RUNNING', true);
}

/**
 * Set a flash message to display on next page load
 */
function setFlashMessage($message, $type = 'success') {
    if (session_status() === PHP_SESSION_NONE) {
        session_start();
    }
    $_SESSION['flash_message'] = $message;
    $_SESSION['flash_type'] = $type;
}

/**
 * Get and clear flash message
 */
function getFlashMessage() {
    if (session_status() === PHP_SESSION_NONE) {
        session_start();
    }
    if (isset($_SESSION['flash_message'])) {
        $message = $_SESSION['flash_message'];
        $type = $_SESSION['flash_type'] ?? 'success';
        unset($_SESSION['flash_message'], $_SESSION['flash_type']);
        return ['message' => $message, 'type' => $type];
    }
    return null;
}

/**
 * Check if there's a flash message
 */
function hasFlashMessage() {
    return isset($_SESSION['flash_message']);
}

/**
 * Format currency amount
 */
function formatMoney($amount, $symbol = null) {
    $symbol = $symbol ?? APP_CURRENCY_SYMBOL;
    return $symbol . ' ' . number_format($amount, 0, '.', ',');
}

/**
 * Format date
 */
function formatDate($date, $format = null) {
    if (empty($date)) return '-';
    $format = $format ?? APP_DATE_FORMAT;
    return date($format, strtotime($date));
}

/**
 * Format datetime
 */
function formatDateTime($datetime, $format = null) {
    if (empty($datetime)) return '-';
    $format = $format ?? APP_DATETIME_FORMAT;
    return date($format, strtotime($datetime));
}

/**
 * Time ago format
 */
function timeAgo($datetime) {
    $time = strtotime($datetime);
    $diff = time() - $time;

    if ($diff < 60) {
        return 'Just now';
    } elseif ($diff < 3600) {
        $mins = floor($diff / 60);
        return $mins . ' minute' . ($mins > 1 ? 's' : '') . ' ago';
    } elseif ($diff < 86400) {
        $hours = floor($diff / 3600);
        return $hours . ' hour' . ($hours > 1 ? 's' : '') . ' ago';
    } elseif ($diff < 604800) {
        $days = floor($diff / 86400);
        return $days . ' day' . ($days > 1 ? 's' : '') . ' ago';
    } else {
        return formatDate($datetime);
    }
}

/**
 * Generate a slug from text
 */
function slugify($text) {
    $text = preg_replace('~[^\pL\d]+~u', '-', $text);
    $text = iconv('utf-8', 'us-ascii//TRANSLIT', $text);
    $text = preg_replace('~[^-\w]+~', '', $text);
    $text = trim($text, '-');
    $text = preg_replace('~-+~', '-', $text);
    $text = strtolower($text);
    return $text;
}

/**
 * Generate a unique reference number
 */
function generateReference($prefix = 'REF', $length = 8) {
    $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    $ref = $prefix . '-' . date('Ymd') . '-';
    for ($i = 0; $i < $length; $i++) {
        $ref .= $chars[random_int(0, strlen($chars) - 1)];
    }
    return $ref;
}

/**
 * Generate sale number
 */
function generateSaleNumber($user_id) {
    global $conn;

    $year = date('Y');
    $result = $conn->query("SELECT COUNT(*) as count FROM sales WHERE user_id = $user_id AND YEAR(created_at) = $year");
    $row = $result->fetch_assoc();
    $count = $row['count'] + 1;

    return 'SL-' . $year . '-' . str_pad($count, 5, '0', STR_PAD_LEFT);
}

/**
 * Generate receipt number
 */
function generateReceiptNumber($user_id) {
    global $conn;

    $year = date('Y');
    $result = $conn->query("SELECT COUNT(*) as count FROM payments WHERE user_id = $user_id AND YEAR(created_at) = $year");
    $row = $result->fetch_assoc();
    $count = $row['count'] + 1;

    return 'RCP-' . $year . '-' . str_pad($count, 6, '0', STR_PAD_LEFT);
}

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

/**
 * Get initials from name
 */
function getInitials($name, $length = 2) {
    $words = explode(' ', trim($name));
    $initials = '';
    foreach ($words as $word) {
        $initials .= strtoupper(substr($word, 0, 1));
        if (strlen($initials) >= $length) break;
    }
    return $initials;
}

/**
 * Get status badge HTML
 */
function statusBadge($status, $type = 'default') {
    $colors = [
        // General statuses
        'active' => 'success',
        'inactive' => 'secondary',
        'pending' => 'warning',
        'completed' => 'success',
        'cancelled' => 'danger',
        'expired' => 'danger',
        'suspended' => 'danger',

        // Plot statuses
        'available' => 'success',
        'reserved' => 'warning',
        'sold' => 'info',
        'unavailable' => 'secondary',

        // Payment statuses
        'confirmed' => 'success',
        'paid' => 'success',
        'partial' => 'warning',
        'overdue' => 'danger',
        'bounced' => 'danger',

        // Subscription statuses
        'trial' => 'info',

        // Default
        'default' => 'secondary'
    ];

    $color = $colors[strtolower($status)] ?? $colors['default'];
    $label = ucfirst(str_replace('_', ' ', $status));

    return '<span class="badge bg-' . $color . '">' . $label . '</span>';
}

/**
 * Get plot status color for grid
 */
function plotStatusColor($status) {
    $colors = [
        'available' => '#22c55e',   // Green
        'reserved' => '#f59e0b',    // Orange
        'sold' => '#ef4444',        // Red
        'unavailable' => '#94a3b8'  // Gray
    ];
    return $colors[$status] ?? $colors['unavailable'];
}

/**
 * Format phone number
 */
function formatPhone($phone) {
    // Remove all non-numeric characters
    $phone = preg_replace('/[^0-9]/', '', $phone);

    // Handle Tanzania phone numbers
    if (strlen($phone) === 9) {
        return '0' . $phone;
    } elseif (strlen($phone) === 10 && substr($phone, 0, 1) === '0') {
        return $phone;
    } elseif (strlen($phone) === 12 && substr($phone, 0, 3) === '255') {
        return '+' . $phone;
    }

    return $phone;
}

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

/**
 * Validate phone number
 */
function isValidPhone($phone) {
    $phone = preg_replace('/[^0-9]/', '', $phone);
    return strlen($phone) >= 9 && strlen($phone) <= 15;
}

/**
 * Calculate percentage
 */
function calculatePercent($part, $total, $decimals = 1) {
    if ($total == 0) return 0;
    return round(($part / $total) * 100, $decimals);
}

/**
 * Get pagination data
 */
function paginate($total, $page = 1, $perPage = null) {
    $perPage = $perPage ?? ITEMS_PER_PAGE;
    $totalPages = ceil($total / $perPage);
    $page = max(1, min($page, $totalPages));
    $offset = ($page - 1) * $perPage;

    return [
        'total' => $total,
        'per_page' => $perPage,
        'current_page' => $page,
        'total_pages' => $totalPages,
        'offset' => $offset,
        'has_prev' => $page > 1,
        'has_next' => $page < $totalPages,
        'prev_page' => $page - 1,
        'next_page' => $page + 1
    ];
}

/**
 * Render pagination HTML
 */
function renderPagination($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_prev']) {
        $html .= '<li class="page-item"><a class="page-link" href="' . $baseUrl . 'page=' . $pagination['prev_page'] . '">Previous</a></li>';
    } else {
        $html .= '<li class="page-item disabled"><span class="page-link">Previous</span></li>';
    }

    // Page numbers
    $start = max(1, $pagination['current_page'] - 2);
    $end = min($pagination['total_pages'], $pagination['current_page'] + 2);

    if ($start > 1) {
        $html .= '<li class="page-item"><a class="page-link" href="' . $baseUrl . 'page=1">1</a></li>';
        if ($start > 2) {
            $html .= '<li class="page-item disabled"><span class="page-link">...</span></li>';
        }
    }

    for ($i = $start; $i <= $end; $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 ($end < $pagination['total_pages']) {
        if ($end < $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']) {
        $html .= '<li class="page-item"><a class="page-link" href="' . $baseUrl . 'page=' . $pagination['next_page'] . '">Next</a></li>';
    } else {
        $html .= '<li class="page-item disabled"><span class="page-link">Next</span></li>';
    }

    $html .= '</ul></nav>';

    return $html;
}

/**
 * Get flash messages HTML
 */
function renderFlashMessages() {
    $html = '';
    $types = ['success', 'error', 'warning', 'info'];

    foreach ($types as $type) {
        $message = getFlash($type);
        if ($message) {
            $alertType = $type === 'error' ? 'danger' : $type;
            $html .= '<div class="alert alert-' . $alertType . ' alert-dismissible fade show" role="alert">';
            $html .= htmlspecialchars($message);
            $html .= '<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>';
            $html .= '</div>';
        }
    }

    return $html;
}

/**
 * Check if array has required keys
 */
function hasRequiredKeys($array, $keys) {
    foreach ($keys as $key) {
        if (!isset($array[$key]) || empty(trim($array[$key]))) {
            return false;
        }
    }
    return true;
}

/**
 * Get setting from database
 */
function getSetting($key, $default = null) {
    global $conn;

    $stmt = $conn->prepare("SELECT setting_value FROM settings WHERE setting_key = ?");
    $stmt->bind_param("s", $key);
    $stmt->execute();
    $result = $stmt->get_result();

    if ($row = $result->fetch_assoc()) {
        return $row['setting_value'];
    }

    return $default;
}

/**
 * Update setting in database
 */
function updateSetting($key, $value, $user_id = null) {
    global $conn;

    $stmt = $conn->prepare("INSERT INTO settings (setting_key, setting_value, updated_by) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE setting_value = ?, updated_by = ?");
    $stmt->bind_param("ssisi", $key, $value, $user_id, $value, $user_id);
    return $stmt->execute();
}

/**
 * File upload handler
 */
function uploadFile($file, $directory, $allowedTypes = null, $maxSize = null) {
    $allowedTypes = $allowedTypes ?? array_merge(ALLOWED_IMAGE_TYPES, ALLOWED_DOCUMENT_TYPES);
    $maxSize = $maxSize ?? MAX_UPLOAD_SIZE;

    // Check for errors
    if ($file['error'] !== UPLOAD_ERR_OK) {
        return ['success' => false, 'error' => 'Upload failed with error code: ' . $file['error']];
    }

    // Check file size
    if ($file['size'] > $maxSize) {
        return ['success' => false, 'error' => 'File is too large. Maximum size: ' . ($maxSize / 1024 / 1024) . 'MB'];
    }

    // Get file extension
    $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));

    // Check file type
    if (!in_array($ext, $allowedTypes)) {
        return ['success' => false, 'error' => 'File type not allowed'];
    }

    // Generate unique filename
    $filename = uniqid() . '_' . time() . '.' . $ext;
    $uploadPath = UPLOADS_PATH . '/' . $directory;

    // Create directory if it doesn't exist
    if (!is_dir($uploadPath)) {
        mkdir($uploadPath, 0755, true);
    }

    $filepath = $uploadPath . '/' . $filename;

    // Move uploaded file
    if (move_uploaded_file($file['tmp_name'], $filepath)) {
        return [
            'success' => true,
            'filename' => $filename,
            'path' => $directory . '/' . $filename,
            'full_path' => $filepath
        ];
    }

    return ['success' => false, 'error' => 'Failed to move uploaded file'];
}

/**
 * Delete uploaded file
 */
function deleteFile($path) {
    $filepath = UPLOADS_PATH . '/' . $path;
    if (file_exists($filepath)) {
        return unlink($filepath);
    }
    return false;
}

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

/**
 * Error JSON response
 */
function jsonError($message, $statusCode = 400) {
    jsonResponse(['success' => false, 'error' => $message], $statusCode);
}

/**
 * Success JSON response
 */
function jsonSuccess($data = [], $message = 'Success') {
    jsonResponse(array_merge(['success' => true, 'message' => $message], $data));
}

/**
 * Calculate installment amount
 */
function calculateInstallment($totalAmount, $depositPercent, $months) {
    $deposit = ($totalAmount * $depositPercent) / 100;
    $balance = $totalAmount - $deposit;
    $monthlyAmount = $months > 0 ? ceil($balance / $months) : $balance;

    return [
        'total' => $totalAmount,
        'deposit' => $deposit,
        'deposit_percent' => $depositPercent,
        'balance' => $balance,
        'monthly_amount' => $monthlyAmount,
        'months' => $months
    ];
}

/**
 * Calculate agent commission
 */
function calculateCommission($saleAmount, $commissionType, $commissionRate, $fixedAmount = 0) {
    if ($commissionType === 'percentage') {
        return ($saleAmount * $commissionRate) / 100;
    }
    return $fixedAmount;
}

/**
 * Get days until date
 */
function daysUntil($date) {
    $target = strtotime($date);
    $now = time();
    $diff = $target - $now;
    return ceil($diff / 86400);
}

/**
 * Get days since date
 */
function daysSince($date) {
    $target = strtotime($date);
    $now = time();
    $diff = $now - $target;
    return floor($diff / 86400);
}

/**
 * Check if date is overdue
 */
function isOverdue($date) {
    return strtotime($date) < strtotime('today');
}

/**
 * Asset URL helper
 */
function asset($path) {
    return ASSETS_URL . '/' . ltrim($path, '/');
}

/**
 * Get billing cycle label
 */
function billingCycleLabel($cycle) {
    $labels = [
        'monthly' => 'Monthly',
        'quarterly' => '3 Months',
        'semiannual' => '6 Months',
        'yearly' => 'Yearly'
    ];
    return $labels[$cycle] ?? $cycle;
}

/**
 * Get billing cycle months
 */
function billingCycleMonths($cycle) {
    $months = [
        'monthly' => 1,
        'quarterly' => 3,
        'semiannual' => 6,
        'yearly' => 12
    ];
    return $months[$cycle] ?? 1;
}
