<?php

function generateCsrfToken() {
    if (empty($_SESSION['csrf_token'])) {
        $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    }
    $_SESSION['csrf_token_time'] = $_SESSION['csrf_token_time'] ?? time();
    if (time() - $_SESSION['csrf_token_time'] > 3600) {
        $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
        $_SESSION['csrf_token_time'] = time();
    }
    return $_SESSION['csrf_token'];
}

function verifyCsrfToken($token) {
    if (!isset($_SESSION['csrf_token']) || empty($token)) {
        return false;
    }
    if (!is_string($token) || strlen($token) !== 64) {
        return false;
    }
    $valid = hash_equals($_SESSION['csrf_token'], $token);
    if ($valid) {
        $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
        $_SESSION['csrf_token_time'] = time();
    }
    return $valid;
}

function csrfField() {
    $token = generateCsrfToken();
    return '<input type="hidden" name="csrf_token" value="' . htmlspecialchars($token) . '">';
}

function logAudit($action, $entityType = null, $entityId = null, $details = null) {
    try {
        $db = getDB();
        $stmt = $db->prepare("INSERT INTO audit_logs (admin_user, action, entity_type, entity_id, details, ip_address) VALUES (?, ?, ?, ?, ?, ?)");
        $stmt->execute([
            $_SESSION['admin_user'] ?? 'system',
            sanitizeString($action),
            $entityType ? sanitizeString($entityType) : null,
            $entityId,
            $details ? mb_substr($details, 0, 1000) : null,
            getClientIp()
        ]);
    } catch (PDOException $e) {
    }
}

function getClientIp() {
    $ip = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
    if (filter_var($ip, FILTER_VALIDATE_IP)) {
        return $ip;
    }
    return '0.0.0.0';
}

function checkLoginThrottle($username) {
    $db = getDB();
    $stmt = $db->prepare("SELECT login_attempts, locked_until FROM admin_users WHERE username = ?");
    $stmt->execute([$username]);
    $user = $stmt->fetch();
    if (!$user) return true;
    if ($user['locked_until'] && strtotime($user['locked_until']) > time()) {
        return false;
    }
    if ($user['login_attempts'] >= 5) {
        $lockUntil = date('Y-m-d H:i:s', time() + 900);
        $db->prepare("UPDATE admin_users SET locked_until = ? WHERE username = ?")->execute([$lockUntil, $username]);
        return false;
    }
    return true;
}

function recordLoginAttempt($username, $success) {
    $db = getDB();
    if ($success) {
        $db->prepare("UPDATE admin_users SET login_attempts = 0, locked_until = NULL WHERE username = ?")->execute([$username]);
    } else {
        $db->prepare("UPDATE admin_users SET login_attempts = login_attempts + 1 WHERE username = ?")->execute([$username]);
    }
}

function makeSlug($text) {
    $text = trim($text);
    $text = mb_strtolower($text, 'UTF-8');
    $text = preg_replace('/[^a-z0-9]+/', '-', $text);
    return trim($text, '-');
}

function sanitizeString($input, $maxLength = 500) {
    if (!is_string($input)) return '';
    $input = trim($input);
    $input = mb_substr($input, 0, $maxLength, 'UTF-8');
    $input = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/', '', $input);
    return $input;
}

function sanitizeEmail($email) {
    $email = trim($email);
    $email = filter_var($email, FILTER_SANITIZE_EMAIL);
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        return false;
    }
    return $email;
}

function sanitizeUrl($url) {
    $url = trim($url);
    if (empty($url) || $url === '#') return $url;
    if (preg_match('#^(https?://|/)#i', $url)) {
        return filter_var($url, FILTER_SANITIZE_URL);
    }
    return '';
}

function sanitizeInt($value, $min = 0, $max = PHP_INT_MAX) {
    $value = (int) $value;
    return max($min, min($max, $value));
}

function checkRateLimit($action, $maxAttempts = 10, $windowSeconds = 60) {
    $ip = getClientIp();
    $key = 'rate_' . $action . '_' . $ip;
    
    if (!isset($_SESSION[$key])) {
        $_SESSION[$key] = ['count' => 0, 'window_start' => time()];
    }
    
    if (time() - $_SESSION[$key]['window_start'] > $windowSeconds) {
        $_SESSION[$key] = ['count' => 0, 'window_start' => time()];
    }
    
    $_SESSION[$key]['count']++;
    
    if ($_SESSION[$key]['count'] > $maxAttempts) {
        return false;
    }
    
    return true;
}

function handleFileUpload($fileInput, $allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'application/pdf'], $maxSize = 5242880) {
    if (!isset($_FILES[$fileInput]) || $_FILES[$fileInput]['error'] !== UPLOAD_ERR_OK) {
        return ['success' => false, 'error' => 'No file uploaded or upload error.'];
    }
    
    $file = $_FILES[$fileInput];
    
    if ($file['size'] > $maxSize || $file['size'] === 0) {
        return ['success' => false, 'error' => 'File too large or empty. Maximum size is ' . ($maxSize / 1048576) . 'MB.'];
    }
    
    $finfo = new finfo(FILEINFO_MIME_TYPE);
    $mimeType = $finfo->file($file['tmp_name']);
    
    if (!in_array($mimeType, $allowedTypes)) {
        return ['success' => false, 'error' => 'File type not allowed.'];
    }
    
    $allowedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'pdf'];
    $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
    if (!in_array($ext, $allowedExtensions)) {
        return ['success' => false, 'error' => 'File extension not allowed.'];
    }
    
    $mimeExtMap = [
        'image/jpeg' => ['jpg', 'jpeg'],
        'image/png' => ['png'],
        'image/gif' => ['gif'],
        'image/webp' => ['webp'],
        'application/pdf' => ['pdf']
    ];
    if (isset($mimeExtMap[$mimeType]) && !in_array($ext, $mimeExtMap[$mimeType])) {
        return ['success' => false, 'error' => 'File extension does not match file content.'];
    }
    
    if (strpos($mimeType, 'image/') === 0 && $ext !== 'webp') {
        $imageInfo = @getimagesize($file['tmp_name']);
        if ($imageInfo === false) {
            return ['success' => false, 'error' => 'Invalid image file.'];
        }
    }
    
    $uploadDir = __DIR__ . '/uploads/';
    if (!is_dir($uploadDir)) {
        mkdir($uploadDir, 0755, true);
    }
    
    $filename = bin2hex(random_bytes(16)) . '.' . $ext;
    $destination = $uploadDir . $filename;
    
    if (move_uploaded_file($file['tmp_name'], $destination)) {
        chmod($destination, 0644);
        return ['success' => true, 'filename' => $filename, 'url' => '/uploads/' . $filename, 'mime' => $mimeType];
    }
    
    return ['success' => false, 'error' => 'Failed to save file.'];
}

function generateCaptcha() {
    $a = rand(2, 15);
    $b = rand(2, 15);
    $_SESSION['captcha_answer'] = $a + $b;
    $_SESSION['captcha_time'] = time();
    return "$a + $b = ?";
}

function verifyCaptcha($userAnswer) {
    $expected = $_SESSION['captcha_answer'] ?? null;
    $captchaTime = $_SESSION['captcha_time'] ?? 0;
    unset($_SESSION['captcha_answer']);
    unset($_SESSION['captcha_time']);
    if ($expected === null) return false;
    if (time() - $captchaTime > 600) return false;
    return (int)$userAnswer === (int)$expected;
}

function hasPermission($permission) {
    if (empty($_SESSION['admin_role'])) return false;
    if ($_SESSION['admin_role'] === 'super_admin') return true;
    $db = getDB();
    $stmt = $db->prepare("SELECT permissions FROM admin_roles WHERE name = ?");
    $stmt->execute([$_SESSION['admin_role']]);
    $role = $stmt->fetch();
    if (!$role) return false;
    if ($role['permissions'] === 'all') return true;
    $perms = explode(',', $role['permissions']);
    return in_array($permission, $perms);
}

function isAdminAuthenticated() {
    if (empty($_SESSION['admin_logged_in']) || $_SESSION['admin_logged_in'] !== true) {
        return false;
    }
    if (empty($_SESSION['admin_id']) || empty($_SESSION['admin_user'])) {
        return false;
    }
    if (isset($_SESSION['_last_activity']) && (time() - $_SESSION['_last_activity'] > 3600)) {
        return false;
    }
    return true;
}

function escapeOutput($value) {
    return htmlspecialchars($value ?? '', ENT_QUOTES | ENT_HTML5, 'UTF-8');
}
