<?php

namespace App\Helpers;

use App\Models\Entry;
use App\Models\EntryFile;
use App\Models\News;
use App\Services\XenforoApiService;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;

class EntryHelpers {

    /**
     * Create a unique slug.
     *
     * @param string $title
     * @param class-string $model The model with a 'slug' field.
     * @param int|null $ignoreId Ignore specific ID, like when edition
     *
     * @return string The original slug if no duplicates, otherwise with a number at the end.
     */
    public static function uniqueSlug(string $title, string $model, ?int $ignoreId = null ): string {

        $slug = Str::slug($title);
        $baseSlug = $slug;
        $i = 1;
        while(
            $model::where( 'slug', $slug )
                ->when($ignoreId, fn($q) => $q->where('id', '!=', $ignoreId))
                ->exists() && $i < 100
        ){
            $slug = $baseSlug . '-' . $i++;
        }

        if( $i >= 100 ){
            $slug = Str::uuid(); // Fallback...
        }

        return $slug;
    }

    /**
     * Build complete title.
     *
     * @param string $section
     * @param array $fields
     *
     * @return string
     */
    public static function buildCompleteTitle( string $section, array $fields = [] ){

        $fields = array_merge( ['entry_title' => 'Untitled', 'game_name' => '', 'languages_string' => '', 'platform_name' => ''], $fields );

        return match ($section) {
            'translations' => sprintf('%s (%s Translation) %s', $fields['entry_title'] ?? $fields['game_name'], $fields['languages_string'], $fields['platform_name']),
            'romhacks' => sprintf('%s (%s) Romhack', $fields['entry_title'], $fields['platform_name']),
            'homebrew' => sprintf('%s (%s) Homebrew', $fields['game_name'], $fields['platform_name']),
            'utilities' => sprintf('%s - Utility', $fields['entry_title']),
            'documents' => sprintf('%s - Document', $fields['entry_title']),
            'lua-scripts' => sprintf('%s (%s) LUA Script', $fields['entry_title'], $fields['platform_name']),
            'tutorials' => sprintf('%s - Tutorial', $fields['entry_title']),
            default => $fields['entry_title'],
        };
    }

    public static function getLatestComments(Entry|News $entry, int $limit = 20): array {

        if( !$entry->comments_thread_id ){
            return [];
        }

        if( is_a( $entry, News::class ) )
            $cacheKey = "news_comments_{$entry->id}";
        else
            $cacheKey = "entry_comments_{$entry->id}";
        return Cache::remember($cacheKey, now()->addDays(1), function () use ($entry, $limit) {

            $service = app(XenforoApiService::class);

            // Get thread infos and pagination.
            $paginationInfos = $service->getThreadPosts($entry->comments_thread_id, 1);
            $lastPage = $paginationInfos['pagination']['last_page'] ?? 1;

            // Get last threads
            $lastPageData = $lastPage > 1 ? $service->getThreadPosts($entry->comments_thread_id, $lastPage) : $paginationInfos;
            $posts = $lastPageData['posts'] ?? [];

            if( count( $posts ) < $limit && $lastPage > 1 ){
                $previousPageData = $service->getThreadPosts($entry->comments_thread_id, $lastPage - 1 );
                $posts = array_merge( $posts, $previousPageData['posts'] ?? [] );
            }

            return collect( $posts )->slice(-$limit)->reverse()->values()->toArray();

        });
    }

    public static function enableOnlinePatcherBasedOnExtension(string $filename): bool
    {
        return Str::endsWith(Str::lower($filename), ['.ips', '.bps', '.xdelta', '.ups', '.aps', '.ppf', '.zip' ]);
    }

    public static function getYoutubeVideoId(string $url): ?string
    {
        $pattern = '%(?:https?://)?(?:www\.|m\.)?(?:youtu\.be/|youtube(?:-nocookie)?\.com/(?:watch\?.*v=|embed/|v/|shorts/|live/))([\w-]{11})%i';

        preg_match($pattern, $url, $matches);
        return $matches[1] ?? null;
    }

    public static function fileAlreadyDownloaded(EntryFile $entryFile): bool
    {
        return session("downloaded_file_{$entryFile->file_uuid}", null ) !== null;
    }

    public static function markFileAsDownloaded(EntryFile $entryFile): bool
    {
        session(["downloaded_file_{$entryFile->file_uuid}" => 1]);
        return true;
    }
}
