<?php

declare(strict_types=1);

use App\Core\Application;

function app(): Application
{
    return Application::instance();
}

function env(string $key, mixed $default = null): mixed
{
    return $_ENV[$key] ?? $_SERVER[$key] ?? $default;
}

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

function csrf_token(): string
{
    if (empty($_SESSION['_csrf_token'])) {
        $_SESSION['_csrf_token'] = bin2hex(random_bytes(32));
    }

    return $_SESSION['_csrf_token'];
}

function csrf_field(): string
{
    return '<input type="hidden" name="_csrf_token" value="' . e(csrf_token()) . '">';
}

function verify_csrf(?string $token): bool
{
    return is_string($token)
        && isset($_SESSION['_csrf_token'])
        && hash_equals($_SESSION['_csrf_token'], $token);
}

function flash(string $key, mixed $value = null): mixed
{
    if ($value !== null) {
        $_SESSION['_flash'][$key] = $value;
        return null;
    }

    $message = $_SESSION['_flash'][$key] ?? null;
    unset($_SESSION['_flash'][$key]);

    return $message;
}

function old(string $key, mixed $default = ''): mixed
{
    return $_SESSION['_old'][$key] ?? $default;
}

function keep_old(array $input): void
{
    unset($input['password'], $input['password_confirmation'], $input['_csrf_token']);
    $_SESSION['_old'] = $input;
}

function clear_old(): void
{
    unset($_SESSION['_old']);
}

function current_user(): ?array
{
    return $_SESSION['user'] ?? null;
}

function auth_check(): bool
{
    return current_user() !== null;
}

function require_auth(): void
{
    if (!auth_check()) {
        flash('error', 'Inicie sessao para continuar.');
        app()->response()->redirect('/login');
    }
}

function require_guest(): void
{
    if (auth_check()) {
        app()->response()->redirect('/dashboard');
    }
}

function has_role(string $role): bool
{
    $user = current_user();

    return $user !== null && ($user['role'] ?? null) === $role;
}

function require_role(string $role): void
{
    require_auth();

    if (!has_role($role)) {
        flash('error', 'Nao tem permissao para aceder a esta area.');
        app()->response()->redirect('/dashboard');
    }
}

function storage_path(string $path = ''): string
{
    return app()->basePath('storage' . ($path ? DIRECTORY_SEPARATOR . ltrim($path, DIRECTORY_SEPARATOR) : ''));
}

function public_url(string $path = ''): string
{
    $path = '/' . ltrim($path, '/');

    return app()->publicBasePath() . ($path === '/' ? '' : $path);
}

function role_label(string $role): string
{
    return [
        'admin' => 'Administrador',
        'student' => 'Aluno',
        'instructor' => 'Instrutor',
        'institution' => 'Instituicao',
        'support' => 'Suporte',
    ][$role] ?? ucfirst($role);
}

function status_label(string $status): string
{
    return [
        'active' => 'Activo',
        'pending' => 'Pendente',
        'suspended' => 'Suspenso',
        'rejected' => 'Rejeitado',
    ][$status] ?? ucfirst($status);
}

function format_date(?string $date): string
{
    if (!$date) {
        return '-';
    }

    $timestamp = strtotime($date);

    return $timestamp ? date('d/m/Y H:i', $timestamp) : '-';
}

function money_mzn(float|int|string $amount): string
{
    return number_format((float) $amount, 2, ',', '.') . ' MZN';
}

function course_status_label(string $status): string
{
    return [
        'draft' => 'Rascunho',
        'submitted' => 'Em aprovacao',
        'published' => 'Publicado',
        'rejected' => 'Rejeitado',
        'suspended' => 'Suspenso',
        'archived' => 'Arquivado',
    ][$status] ?? ucfirst($status);
}

function level_label(string $level): string
{
    return [
        'beginner' => 'Iniciante',
        'intermediate' => 'Intermedio',
        'advanced' => 'Avancado',
        'all' => 'Todos os niveis',
    ][$level] ?? ucfirst($level);
}

function course_effective_price(array $course): float
{
    $discount = (float) ($course['discount_price'] ?? 0);
    $price = (float) ($course['price'] ?? 0);

    return $discount > 0 && $discount < $price ? $discount : $price;
}

function lines_list(?string $value): array
{
    $lines = preg_split('/\r\n|\r|\n|;/', (string) $value) ?: [];

    return array_values(array_filter(array_map('trim', $lines)));
}

function lesson_type_label(string $type): string
{
    return [
        'video' => 'Video-aula',
        'text' => 'Aula em texto',
        'pdf' => 'Aula em PDF',
    ][$type] ?? ucfirst($type);
}

function promo_video_data(?string $url): array
{
    $url = trim((string) $url);

    if ($url === '') {
        return ['type' => 'none', 'url' => ''];
    }

    $parts = parse_url($url);
    $host = strtolower((string) ($parts['host'] ?? ''));
    $path = (string) ($parts['path'] ?? '');
    $query = [];
    parse_str((string) ($parts['query'] ?? ''), $query);

    if (str_contains($host, 'youtube.com') || str_contains($host, 'youtu.be')) {
        $videoId = '';
        if (str_contains($host, 'youtu.be')) {
            $videoId = trim($path, '/');
        } elseif (!empty($query['v'])) {
            $videoId = (string) $query['v'];
        } elseif (str_starts_with($path, '/embed/')) {
            $videoId = substr($path, strlen('/embed/'));
        } elseif (str_starts_with($path, '/shorts/')) {
            $videoId = substr($path, strlen('/shorts/'));
        }

        $videoId = preg_replace('/[^a-zA-Z0-9_-]/', '', $videoId ?? '') ?: '';

        if ($videoId !== '') {
            return ['type' => 'embed', 'url' => 'https://www.youtube.com/embed/' . $videoId];
        }
    }

    if (str_contains($host, 'vimeo.com')) {
        $videoId = preg_replace('/[^0-9]/', '', trim($path, '/')) ?: '';

        if ($videoId !== '') {
            return ['type' => 'embed', 'url' => 'https://player.vimeo.com/video/' . $videoId];
        }
    }

    $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
    if (in_array($extension, ['mp4', 'webm', 'ogg'], true)) {
        return ['type' => 'file', 'url' => $url];
    }

    return ['type' => 'link', 'url' => $url];
}

function payment_status_label(string $status): string
{
    return [
        'pending' => 'Pendente',
        'proof_submitted' => 'Com comprovativo',
        'approved' => 'Aprovado',
        'rejected' => 'Rejeitado',
        'cancelled' => 'Cancelado',
    ][$status] ?? ucfirst($status);
}
