<?php
/**
 * Genel yardımcı fonksiyonlar.
 * Base URL tespiti kök / alt klasör / subdomain kurulumlarında sorunsuz çalışır.
 */

/** Uygulamanın base yolunu tespit eder (örn. "" veya "/altklasor"). */
function base_path(): string
{
    static $base = null;
    if ($base !== null) {
        return $base;
    }
    // index.php'nin bulunduğu klasör -> alt klasör kurulumları için doğru sonucu verir.
    $script = str_replace('\\', '/', dirname($_SERVER['SCRIPT_NAME'] ?? ''));
    $script = rtrim($script, '/');
    if ($script === '/' || $script === '.') {
        $script = '';
    }
    return $base = $script;
}

/** Tam base URL (şema + host + base yol). */
function base_url(): string
{
    $https = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
        || (($_SERVER['SERVER_PORT'] ?? '') == 443)
        || (($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '') === 'https');
    $scheme = $https ? 'https' : 'http';
    $host = $_SERVER['HTTP_HOST'] ?? 'localhost';
    return $scheme . '://' . $host . base_path();
}

/** Uygulama içi URL üretir. */
function url(string $path = ''): string
{
    $path = ltrim($path, '/');
    return base_url() . '/' . $path;
}

/** Yüklenen dosya / statik varlık URL'i (CSS/JS için cache-bust). */
function asset(string $path): string
{
    $url = url($path);
    $file = APP_ROOT . '/' . ltrim(str_replace('\\', '/', $path), '/');
    if (is_file($file)) {
        $url .= '?v=' . filemtime($file);
    }
    return $url;
}

/** İstek yolunu (route) döndürür; base yolu temizlenmiş halde. */
function current_route(): string
{
    $uri = $_SERVER['REQUEST_URI'] ?? '/';
    $uri = parse_url($uri, PHP_URL_PATH) ?? '/';
    $uri = rawurldecode($uri);
    $base = base_path();
    if ($base !== '' && str_starts_with($uri, $base)) {
        $uri = substr($uri, strlen($base));
    }
    $uri = '/' . ltrim($uri, '/');
    // index.php doğrudan çağrıldıysa ?r= parametresini de destekle
    if (($uri === '/' || $uri === '/index.php') && isset($_GET['r'])) {
        $uri = '/' . ltrim($_GET['r'], '/');
    }
    return $uri === '' ? '/' : $uri;
}

/** HTML kaçışlama (XSS + Türkçe karakter güvenli). */
function e(?string $s): string
{
    return htmlspecialchars((string) $s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}

/** Türkçe karakter uyumlu SEO slug üretir. */
function slugify(string $text): string
{
    $tr = ['ç','Ç','ğ','Ğ','ı','İ','ö','Ö','ş','Ş','ü','Ü'];
    $en = ['c','c','g','g','i','i','o','o','s','s','u','u'];
    $text = str_replace($tr, $en, $text);
    $text = mb_strtolower($text, 'UTF-8');
    $text = preg_replace('/[^a-z0-9]+/', '-', $text);
    $text = trim($text, '-');
    return $text === '' ? 'urun-' . substr(md5(microtime(true)), 0, 6) : $text;
}

/** Fiyatı biçimlendirir. */
function money($amount, string $currency = '₺'): string
{
    $amount = (float) $amount;
    $formatted = number_format($amount, ($amount == (int) $amount) ? 0 : 2, ',', '.');
    return $currency . $formatted;
}

/** Ayarları önbellekli olarak yükler (bellek + dosya önbelleği). */
function settings(bool $reload = false): array
{
    static $cache = null;
    if ($reload) {
        $cache = null;
    }
    if ($cache !== null) {
        return $cache;
    }

    $cacheFile = APP_ROOT . '/cache/settings.json';
    if (!$reload && is_file($cacheFile)) {
        $raw = @file_get_contents($cacheFile);
        if ($raw !== false) {
            $decoded = json_decode($raw, true);
            if (is_array($decoded)) {
                return $cache = $decoded;
            }
        }
    }

    $cache = [];
    try {
        foreach (Database::all("SELECT `key`, `value` FROM settings") as $row) {
            $cache[$row['key']] = $row['value'];
        }
        $dir = APP_ROOT . '/cache';
        if (!is_dir($dir)) {
            @mkdir($dir, 0775, true);
        }
        @file_put_contents($cacheFile, json_encode($cache, JSON_UNESCAPED_UNICODE), LOCK_EX);
    } catch (Throwable $e) {
        $cache = [];
    }
    return $cache;
}

/** Ayar dosya önbelleğini temizler. */
function settings_flush_cache(): void
{
    @unlink(APP_ROOT . '/cache/settings.json');
}

/** Tek bir ayar değeri. */
function setting(string $key, $default = '')
{
    $s = settings();
    return $s[$key] ?? $default;
}

/** Ayar kaydeder / günceller. */
function set_setting(string $key, string $value): void
{
    Database::query(
        "INSERT INTO settings (`key`, `value`) VALUES (?, ?)
         ON DUPLICATE KEY UPDATE `value` = VALUES(`value`)",
        [$key, $value]
    );
    settings(true);
    settings_flush_cache();
}

/** Yüklenen medya dosyasını diskten siler (yalnızca assets/uploads). */
function delete_media_file(?string $path): void
{
    if (!$path || preg_match('#^https?://#', $path)) {
        return;
    }
    $path = ltrim(str_replace('\\', '/', $path), '/');
    if (!str_starts_with($path, 'assets/uploads/')) {
        return;
    }
    $full = APP_ROOT . '/' . $path;
    if (is_file($full)) {
        @unlink($full);
    }
}

/** Yönlendirme yapar. */
function redirect(string $path): void
{
    $target = preg_match('#^https?://#', $path) ? $path : url($path);
    header('Location: ' . $target);
    exit;
}

/** CSRF token üret/al. */
function csrf_token(): string
{
    if (empty($_SESSION['csrf'])) {
        $_SESSION['csrf'] = bin2hex(random_bytes(32));
    }
    return $_SESSION['csrf'];
}

/** CSRF alanı (form için). */
function csrf_field(): string
{
    return '<input type="hidden" name="_csrf" value="' . e(csrf_token()) . '">';
}

/** CSRF doğrula. */
function csrf_check(): void
{
    $token = $_POST['_csrf'] ?? '';
    if (!hash_equals($_SESSION['csrf'] ?? '', $token)) {
        http_response_code(419);
        exit('Oturum süresi doldu (CSRF). Lütfen sayfayı yenileyip tekrar deneyin.');
    }
}

/** Flash mesaj ayarla. */
function flash(string $msg, string $type = 'success'): void
{
    $_SESSION['flash'][] = ['msg' => $msg, 'type' => $type];
}

/** Flash mesajları al ve temizle. */
function get_flashes(): array
{
    $f = $_SESSION['flash'] ?? [];
    unset($_SESSION['flash']);
    return $f;
}

/** Görsel/video yükleme. Başarılıysa göreli yolu döndürür. */
function handle_upload(string $field, array $allowed, string $subdir = 'uploads'): ?string
{
    if (empty($_FILES[$field]['name']) || $_FILES[$field]['error'] === UPLOAD_ERR_NO_FILE) {
        return null;
    }
    $file = $_FILES[$field];
    if ($file['error'] !== UPLOAD_ERR_OK) {
        throw new RuntimeException('Dosya yükleme hatası (kod: ' . $file['error'] . ').');
    }
    $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
    if (!in_array($ext, $allowed, true)) {
        throw new RuntimeException('İzin verilmeyen dosya türü: .' . $ext);
    }
    // Boyut sınırı (görsel 8MB, video 64MB)
    $isVideo = in_array($ext, ['mp4', 'webm', 'mov'], true);
    $maxBytes = $isVideo ? 64 * 1024 * 1024 : 8 * 1024 * 1024;
    if ($file['size'] > $maxBytes) {
        throw new RuntimeException('Dosya çok büyük (en fazla ' . ($isVideo ? '64MB video' : '8MB görsel') . ').');
    }
    // Raster görsellerde gerçekten görsel mi diye içerik doğrula (sahte uzantıya karşı)
    if (in_array($ext, ['jpg', 'jpeg', 'png', 'webp', 'gif'], true)) {
        $info = @getimagesize($file['tmp_name']);
        if ($info === false) {
            throw new RuntimeException('Geçersiz görsel dosyası.');
        }
    }
    $dir = APP_ROOT . '/assets/' . $subdir;
    if (!is_dir($dir)) {
        mkdir($dir, 0775, true);
    }
    $name = date('Ymd_His') . '_' . substr(md5(uniqid('', true)), 0, 8) . '.' . $ext;
    $dest = $dir . '/' . $name;
    if (!move_uploaded_file($file['tmp_name'], $dest)) {
        throw new RuntimeException('Dosya taşınamadı. Klasör yazma izinlerini kontrol edin.');
    }
    return 'assets/' . $subdir . '/' . $name;
}

/** Admin girişli mi? */
function is_admin(): bool
{
    return !empty($_SESSION['admin_id']);
}

/** Admin girişi zorunlu. */
function require_admin(): void
{
    if (!is_admin()) {
        redirect('admin/login');
    }
}

/** Görsel/video URL — yerel dosya öncelikli, dış URL'de yüksek çözünürlük. */
function media_url(?string $path): string
{
    if (!$path) {
        return url('assets/img/placeholder.svg');
    }
    if (preg_match('#^https?://#', $path)) {
        return media_optimize_external($path);
    }
    return url($path);
}

/** Dış (Framer vb.) görsel URL'lerini net göstermek için genişletir. */
function media_optimize_external(string $url): string
{
    if (preg_match('#framerusercontent\.com/images/.+\.(jpg|jpeg|png|webp)#i', $url)) {
        if (!preg_match('/[?&]width=/', $url)) {
            $url .= (str_contains($url, '?') ? '&' : '?') . 'width=1200';
        }
    }
    return $url;
}

/** Ürün/kategori poster görseli (yüksek çözünürlük). */
function media_poster(?string $path, int $width = 1200): string
{
    if (!$path) {
        return url('assets/img/placeholder.svg');
    }
    if (preg_match('#^https?://#', $path)) {
        $u = media_optimize_external($path);
        if (!preg_match('/[?&]width=/', $u)) {
            $u .= (str_contains($u, '?') ? '&' : '?') . 'width=' . $width;
        }
        return $u;
    }
    return url($path);
}

/** Kullanıcıdan gelen bağlantıyı güvenli hale getirir (javascript:, data: engellenir). */
function safe_url(?string $url): string
{
    $url = trim((string) $url);
    if ($url === '') {
        return '';
    }
    if (preg_match('#^\s*(javascript|data|vbscript|file)\s*:#i', $url)) {
        return '';
    }
    // Şema yoksa ve mutlak/protokol-göreli değilse http:// ekle
    if (!preg_match('#^(https?:)?//#i', $url) && !str_starts_with($url, '/') && !str_starts_with($url, '#')) {
        $url = 'https://' . $url;
    }
    return $url;
}

/** Video preload modu — hero dışında metadata (jet yükleme). */
function video_preload(bool $hero = false): string
{
    return $hero ? 'auto' : 'metadata';
}

/** Temel güvenlik + performans başlıkları. */
function send_security_headers(): void
{
    if (headers_sent()) {
        return;
    }
    header('X-Content-Type-Options: nosniff');
    header('X-Frame-Options: SAMEORIGIN');
    header('Referrer-Policy: strict-origin-when-cross-origin');
    header('X-XSS-Protection: 1; mode=block');
    header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
    header('Pragma: no-cache');
}
