<?php

use App\Models\Ads;
use App\Models\BlogCategory;
use App\Models\Category;
use App\Models\Config;
use App\Models\Country;
use App\Models\Currency;
use App\Models\EmailTemplate;
use App\Models\Episode;
use App\Models\Genre;
use App\Models\Language;
use App\Models\LiveTv;
use App\Models\LiveTvCategory;
use App\Models\Movie;
use App\Models\MovieIndustry;
use App\Models\MovieLanguage;
use App\Models\Package;
use App\Models\RentalHistory;
use App\Models\Season;
use App\Models\Star;
use App\Models\Subscription;
use App\Models\TvShow;
use App\Models\User;
use App\Models\MovieFile;
use App\Models\Review;
use App\Models\VideoQuality;
use App\Models\WatchHistory;
use Illuminate\Support\Facades\Request;
use Jackiedo\DotenvEditor\DotenvEditor;
use GuzzleHttp\Client;
use Carbon\Carbon;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage;
use GeoSot\EnvEditor\Facades\EnvEditor;
use Dotenv\Dotenv;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Str;

if (! function_exists('isAppMode')) {
    function isAppMode(): bool
    {
        return config('app.mobile_mode') == 'on';
    }
}

// Detect if running on php artisan serve
function isServe(): bool
{
    return isset($_SERVER['SERVER_SOFTWARE'])
        && str_contains($_SERVER['SERVER_SOFTWARE'], 'PHP');
}

if (! function_exists('validate_purchase')) {
    function validate_purchase($code, $data)
    {
        $script_url      = str_replace('install/process', '', (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http') . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]");

        $fields          = [
            'item_id'         => '59566505',
            'activation_code' => urlencode($code),
            'current_version' => setting('current_version'),
        ];
        $response        = false;
        if (config('app.beta_channel')) {
            $url = 'https://license.spagreen.net/version-check-including-beta';
        } else {
            $url = 'https://license.spagreen.net/version-check';
        }

        $request         = curlRequest($url, $fields);
        if (property_exists($request, 'status') && $request->status) {
            $response = $request->release_info;
        }
        $install_version = 140;
        $fields          = [
            'domain'          => urlencode($_SERVER['SERVER_NAME']),
            'version'         => $install_version,
            'item_id'         => '59566505',
            'url'             => urlencode($script_url),
            'activation_code' => urlencode($code),
            'is_beta'         => (config('app.beta_channel')) ? '1' : '0',
        ];

        $curl_response   = curlRequest('https://license.spagreen.net/verify-installation-v3', $fields);

        if (property_exists($curl_response, 'status') && $curl_response->status) {
            envWrite('DB_HOST', $data['DB_HOST']);
            envWrite('DB_DATABASE', $data['DB_DATABASE']);
            envWrite('DB_USERNAME', $data['DB_USERNAME']);
            envWrite('DB_PASSWORD', $data['DB_PASSWORD']);
            // Only sleep if NOT running in php artisan serve
            if (!isServe()) {
                sleep(5);
            }

            $zip_file = $curl_response->release_zip_link;

            if ($zip_file) {
                try {
                    $file_path = base_path('public/install/installer.zip');
                    file_put_contents($file_path, file_get_contents($zip_file));
                } catch (Exception $e) {
                    return 'Zip file cannot be Imported. Please check your server permission or Contact with Script Author.';
                }
            }
            return 'success';
        } else {
            return $curl_response->message;
        }
    }
}

if (!function_exists('static_asset')) {
    function static_asset($path = null, $secure = null)
    {
        // Remove any leading slashes to avoid double slashes
        $path = ltrim($path, '/');

        // Determine if we're running in CLI or from public
        $isCli = strpos(php_sapi_name(), 'cli') !== false || defined('LARAVEL_START_FROM_PUBLIC');

        // For local development (localhost or 127.0.0.1)
        $isLocal = isset($_SERVER['SERVER_NAME']) &&
            ($_SERVER['SERVER_NAME'] == 'localhost' || $_SERVER['SERVER_NAME'] == '127.0.0.1');

        // Always use the same path structure
        $assetPath = $isLocal && !$isCli ? 'public/' . $path : $path;

        // Generate the URL
        $url = app('url')->asset($assetPath, $secure);

        // Clean up any potential double 'public' segments
        return str_replace('public/public/', 'public/', $url);
    }
}

if (!function_exists('get_config')) {
    function get_config($value)
    {
        return Config::where('title', $value)->value('value');
    }
}

if (!function_exists('httpRequest')) {
    function httpRequest($url, $fields, $headers = [], $is_form = false, $method = 'POST')
    {
        if ($is_form) {
            $response = Http::withHeaders($headers)->timeout(30)->asForm()->$method($url, $fields);
        } else {
            $response = Http::withHeaders($headers)->timeout(30)->$method($url, $fields);
        }

        return $response->json();
    }
}

if (! function_exists('checkEmptyProvider')) {
    function checkEmptyProvider($check_for)
    {
        foreach (get_yrsetting($check_for) as $title) {
            if (setting($title) == '') {
                return false;
            }
        }

        return true;
    }
}

if (!function_exists('setting')) {
    function setting($title, $lang = 'en')
    {
        if (!$lang) {
            $lang = app()->getLocale();
        }
        try {
            $settings = Config::query();
            if (!blank($title)) {
                if (in_array($title, get_yrsetting('setting_array')) || in_array($title, get_yrsetting('setting_image'))) {
                    $data = $settings->where('title', $title)->first();
                    if (!blank($data)) {
                        return $data->value ? unserialize($data->value) : [];
                    }
                } else {
                    if (in_array($title, get_yrsetting('setting_by_lang'))) {
                        $data = $settings->where('title', $title)->where('lang', $lang)->first();

                        if (blank($data)) {
                            $data = $settings->where('title', $title)->where('lang', 'en')->first();

                            return !blank($data) ? $data->value : '';
                        }

                        return $data->value;
                    } else {
                        $data = $settings->where('title', $title)->first();
                    }

                    return !blank($data) ? $data->value : '';
                }
            } else {
                return '';
            }
        } catch (\Exception $e) {
            // dd($e);
            return '';
        }
    }
}

if (!function_exists('settingHelper')) {
    /**
     * Simple key-value lookup for license/updater (purchase_code, client_name, current_version, etc.).
     */
    function settingHelper($key)
    {
        try {
            $data = \App\Models\Config::where('title', $key)->first();
            return $data !== null ? $data->value : null;
        } catch (\Exception $e) {
            return null;
        }
    }
}

if (!function_exists('get_media')) {
    /**
     * Get media URL from different storage systems
     *
     * @param string|null $item The media path
     * @param string $storage Storage driver (local, aws_s3, do, wasabi)
     * @param bool $updater Whether to return filesystem path (for updates) or URL
     * @return string|false
     */
    function get_media($item, $storage = 'local', $updater = false)
    {
        if (blank($item) || blank($storage)) {
            return false;
        }

        $item = ltrim($item, '/'); // Normalize path

        try {
            switch ($storage) {
                case 'local':
                    if ($updater) {
                        // Return filesystem path for updater
                        return public_path($item);
                    }
                    // Return web-accessible URL
                    return asset($item);

                case 'aws_s3':
                    return Storage::disk('s3')->url($item);

                case 'do':
                    $directory = setting('do_directory') ? trim(setting('do_directory'), '/') . '/' : '';
                    return Storage::disk('do')->url($directory . $item);

                case 'wasabi':
                    return Storage::disk('wasabi')->url($item);

                default:
                    return false;
            }
        } catch (Exception $e) {
            // Log error if needed
            // logger()->error("Media URL generation failed: " . $e->getMessage());
            return false;
        }
    }
}

if (! function_exists('isLocalhost')) {

    function isLocalhost(): string
    {
        return ! (str_contains(php_sapi_name(), 'cli') || defined('LARAVEL_START_FROM_PUBLIC')) ? 'public/' : '';
    }
}

if (!function_exists('menuActivation')) {
    function menuActivation($urls, $class, $other = null)
    {
        $check_lang = '';
        if (is_array($urls)) {
            foreach ($urls as $url) {
                if (Request::is($check_lang . $url)) {
                    return $class;
                }
            }
        } elseif (Request()->is($check_lang . $urls)) {
            return $class;
        } else {
            return $other;
        }
    }
}
if (! function_exists('isDemoMode')) {
    function isDemoMode(): bool
    {
        return env('DEMO_MODE', false); // default false
    }
}
if (!function_exists('stringMasking')) {
    function stringMasking($string, $pattern, $start_range, $end_range = null)
    {
        return isDemoMode() ? \Illuminate\Support\Str::mask($string, $pattern, $start_range, $end_range) : $string;
    }
}

if (! function_exists('envWrite')) {
    function envWrite($key, $value)
    {
        try {
            if (is_bool($value)) {
                $value = $value ? 'true' : 'false';
            } else {
                $value = '"' . trim($value) . '"';
            }
            if (EnvEditor::keyExists($key)) {
                EnvEditor::editKey($key, $value);
            } else {
                EnvEditor::addKey($key, $value);
            }
        } catch (Exception $e) {
            dd($e);
        }
    }
}



if (!function_exists('EmailTemplate')) {
    function EmailTemplate($title)
    {
        return EmailTemplate::where('title', $title)->first();
    }
}
if (!function_exists('getArrayValue')) {
    function getArrayValue($key, $array, $default = null)
    {
        return arrayCheck($key, $array) ? $array[$key] : $default;
    }
}
if (!function_exists('is_file_exists')) {
    function is_file_exists($item, $storage = 'local')
    {
        if (blank($item) || blank($storage)) {
            return false;
        }
        if (filter_var($item, FILTER_VALIDATE_URL)) {
            return true;
        }
        $item = ltrim($item, '/');
        if ($storage == 'local') {
            return file_exists(public_path($item));
        }
        if ($storage == 'aws_s3') {
            return Storage::disk('s3')->exists($item);
        }
        if ($storage == 'wasabi') {
            return Storage::disk('wasabi')->exists($item);
        }
        if ($storage == 'do') {
            return Storage::disk('do')->exists($item);
        }

        return false;
    }
}

if (!function_exists('storage_disk_for_setting')) {
    /**
     * Map lmssetting default_storage value to a Laravel filesystem disk name.
     */
    function storage_disk_for_setting(?string $storage): ?string
    {
        return match ($storage) {
            'aws_s3' => 's3',
            'wasabi' => 'wasabi',
            'do' => 'do',
            default => null,
        };
    }
}

if (!function_exists('cloud_object_key_from_public_url')) {
    /**
     * Extract object key from a stored URL or return path if already a key.
     */
    function cloud_object_key_from_public_url(string $diskName, string $fileUrlOrKey): ?string
    {
        $raw = trim($fileUrlOrKey);
        if ($raw === '') {
            return null;
        }
        if (! preg_match('#^https?://#i', $raw)) {
            return ltrim($raw, '/');
        }
        $path = parse_url($raw, PHP_URL_PATH);
        if (! is_string($path) || $path === '') {
            return null;
        }
        $path = ltrim($path, '/');
        $bucket = config("filesystems.disks.{$diskName}.bucket");
        if ($bucket && Str::startsWith($path, $bucket . '/')) {
            return substr($path, strlen($bucket) + 1);
        }

        return $path;
    }
}

if (!function_exists('media_or_local_asset')) {
    /**
     * Public URL for a path stored either on local disk under public/ or on a cloud disk (lmssetting storage key).
     */
    function media_or_local_asset(?string $path, string $storage = 'local'): string
    {
        if (blank($path)) {
            return '';
        }
        $path = ltrim($path, '/');
        if ($storage === 'local') {
            return static_asset($path);
        }
        $u = get_media($path, $storage);

        return $u !== false ? $u : static_asset($path);
    }
}

if (!function_exists('delete_stored_movie_file')) {
    function delete_stored_movie_file(?string $fileSource, ?string $fileUrl): void
    {
        if (blank($fileSource) || blank($fileUrl)) {
            return;
        }
        if ($fileSource === 'local' || $fileSource === 'video') {
            $p = public_path($fileUrl);
            if (file_exists($p)) {
                @unlink($p);
            }

            return;
        }
        if (! in_array($fileSource, ['s3', 'wasabi', 'do'], true)) {
            return;
        }
        $key = cloud_object_key_from_public_url($fileSource, $fileUrl);
        if ($key) {
            Storage::disk($fileSource)->delete($key);
        }
    }
}

if (!function_exists('getFileLinkVariantField')) {
    /**
     * Map getFileLink() call semantics to a JSON image variant key from saveImage().
     */
    function getFileLinkVariantField(string $type, string $placeholder): string
    {
        if ($type === 'original_image' || $placeholder === 'original') {
            return 'original_image';
        }
        if ($type === '80x80' || $type === 'user' || $type === 'image') {
            return 'image_80x80';
        }
        if (in_array($type, ['poster', 'star'], true)) {
            return 'image_1080x720';
        }
        if ($type === 'live_tv') {
            return 'image_1080x720';
        }
        if (preg_match('/^(\d+)x(\d+)$/', $placeholder, $m)) {
            $w = (int) $m[1];
            $h = (int) $m[2];
            if ($w > 0 && $h > 0) {
                if ($w <= 120 && $h <= 120) {
                    return 'image_80x80';
                }
                if (($w / $h) >= 1.2) {
                    return 'image_1080x720';
                }
            }
        }

        return 'image_240x240';
    }
}

if (!function_exists('getFileLink')) {
    function getFileLink($type, $json, $folder = null, $size = null, $placeholder_size = '80x80')
    {
        $ph = $size ?? $placeholder_size ?? '80x80';
        if (is_array($json)) {
            $json = json_encode($json);
        }
        if (! is_string($json) || trim($json) === '') {
            return 'https://placehold.co/' . $ph;
        }

        $decoded = json_decode($json);
        if (json_last_error() !== JSON_ERROR_NONE || ! $decoded) {
            return 'https://placehold.co/' . $ph;
        }

        $storage = property_exists($decoded, 'storage') && $decoded->storage !== null && $decoded->storage !== ''
            ? $decoded->storage
            : 'local';

        $variantHint = ($size !== null && $size !== '') ? (string) $size : (string) ($placeholder_size ?? '80x80');
        $field = getFileLinkVariantField((string) $type, $variantHint);
        $path = null;
        if (isset($decoded->{$field}) && $decoded->{$field} !== '') {
            $path = $decoded->{$field};
        }
        if (empty($path)) {
            foreach (['image_1080x720', 'image_240x240', 'image_80x80', 'original_image'] as $k) {
                if (! empty($decoded->{$k})) {
                    $path = $decoded->{$k};
                    break;
                }
            }
        }

        if (empty($path)) {
            return 'https://placehold.co/' . $ph;
        }

        if (filter_var($path, FILTER_VALIDATE_URL)) {
            if ($placeholder_size === 'original') {
                return str_replace('w500', 'original', $path);
            }
            if ($placeholder_size === 'w500') {
                return str_replace('w342', 'w500', $path);
            }

            return $path;
        }

        $path = ltrim($path, '/');

        if ($storage === 'local') {
            $url = $path;
            if ($folder) {
                $url = str_replace('uploads/' . $folder . '/', 'images/', $path);
            }
            if ($url && file_exists(public_path($url)) && is_file(public_path($url))) {
                return static_asset($url);
            }
            if (file_exists(public_path($path)) && is_file(public_path($path))) {
                return static_asset($path);
            }

            return 'https://placehold.co/' . $ph;
        }

        $mediaUrl = get_media($path, $storage);

        return $mediaUrl !== false ? $mediaUrl : 'https://placehold.co/' . $ph;
    }
}

if (!function_exists('get_star')) {
    function get_star($id, $value)
    {
        $star = Star::where('id', $id)->first();
        if ($value == 'star_image') {
            return get_media_file('80x80', $star?->star_image);
        } else {
            return $star?->$value;
        }
    }
}
if (!function_exists('get_media_file')) {
    function get_media_file($size, $json)
    {
        $image = json_decode($json);

        if (isset($image->original_image)) {
            return $image->original_image;
        } else {
            return 'https://placehold.co/250x280';
        }
    }
}

if (!function_exists('TMDBImageUrl')) {
    function TMDBImageUrl($image, $size)
    {

        if ($image == null || $image == ''):
            $url = 'https://placehold.co/250x280';
        else:
            $url = 'https://image.tmdb.org/t/p/' . $size . $image;
        endif;
        return $url;
    }
}

if (!function_exists('get_ads')) {
    function get_ads($position, $size = '300x250', $return = null)
    {
        $now = now()->format('Y-m-d\TH:i');

        $ads = Ads::where('position', $position)
            ->where('status', 1)
            ->where(function ($query) use ($now) {
                $query->whereNull('start_date')
                    ->orWhereDate('start_date', '<=', $now);
            })
            ->where(function ($query) use ($now) {
                $query->whereNull('end_date')
                    ->orWhereDate('end_date', '>=', $now);
            })
            ->first();

        if (!$ads) {
            return false;
        }

        // Return the full ad object if requested
        if ($return === 'object') {
            // Add commonly used URLs for convenience
            $ads->image_url = getFileLink('ads', $ads->banner, 'adss', $size);
            $ads->video_link = $ads->video_link ?? null;
            $ads->google_ads_code = $ads->content ?? null;
            $ads->url = $ads->redirect_url ?? null;
            return $ads;
        }

        // Return redirect URL if requested
        if ($return === 'url') {
            return $ads->redirect_url ?? '#';
        }

        // Return MP4 link if requested and type is mp4
        if ($return === 'mp4' && $ads->type == 'mp4') {
            return $ads->video_link ?? '';
        }

        // Return based on ad type
        if ($ads->type == 'local') {
            return getFileLink('ads', $ads->banner, 'adss', $size);
        } elseif ($ads->type == 'google') {
            return $ads->content;
        } elseif ($ads->type == 'mp4') {
            return $ads->video_link ?? '';
        }

        return false;
    }
}

if (!function_exists('get_subscription_plan')) {
    function get_subscription_plan($value)
    {
        $subscription = Subscription::where('client_id', auth()->user()->client_id)->orderBy('id', 'DESC')->first();

        if (!$subscription) {
            return null;
        }
        $package = Package::find($subscription->plan_id);
        if (!$package) {
            return null;
        }
        return $package->$value ?? null;
    }
}
if (!function_exists('get_episode_slug')) {
    function get_episode_slug($id)
    {
        $season = Season::whereJsonContains('tv_show_id', (string)$id)->orderBy('id', 'DESC')->first();
        if (!$season) {
            return null;
        }

        $episode = Episode::where('season_id', $season->id)->orderBy('id', 'DESC')->first();
        if (!$episode) {
            return null;
        }

        return $episode->slug ?? null;
    }
}
if (!function_exists('get_subscription_info')) {
    function get_subscription_info($value)
    {
        $subscription = Subscription::where('client_id', auth()->user()->client_id)->orderBy('id', 'DESC')->first();

        if (!$subscription) {
            return null;
        }

        return $subscription->$value ?? null;
    }
}
if (!function_exists('is_admin')) {
    function is_admin()
    {
        $user = auth()->user();
        if (!$user) {
            return false;
        }
        if ($user->user_type == 'admin') {
            return true;
        }
        return false;
    }
}
if (!function_exists('check_subscription')) {
    function check_subscription()
    {
        $user = auth()->user();

        if (!$user) {
            return false;
        }
        $subscription = Subscription::where('client_id', $user->client_id)
            ->where('status', 1)
            ->orderBy('id', 'DESC')
            ->first();
        if (!$subscription) {
            return false;
        }

        $package = Package::find($subscription->plan_id);
        // Calculate expiration date
        $startDate = $subscription->created_at;
        $validDays = $package->day ?? 0;

        $expirationDate = Carbon::parse($startDate)->addDays($validDays);
        // Check if subscription is still valid
        if (Carbon::now()->lessThanOrEqualTo($expirationDate)) {
            return true; // Subscribed and active
        }

        return false; // Expired
    }
}

if (!function_exists('get_price')) {

    function get_price($price, $curr = null)
    {
        return get_currency($price);
    }
}

if (!function_exists('arrayCheck')) {
    function arrayCheck($key, $array): bool
    {
        return is_array($array) && count($array) > 0 && array_key_exists($key, $array) && !empty($array[$key]) && $array[$key] != 'null';
    }
}

if (!function_exists('checkArrayInput')) {
    function checkArrayInput($value)
    {
        return blank($value) || $value == '' || $value == null || is_array($value) == false ? [] : $value;
    }
}

if (!function_exists('configHelper')) {

    function configHelper($config_for)
    {
        return Config::where('title', $config_for)->value('value');
    }
}

if (!function_exists('slugify')) {
    function slugify($string, $separator = '-')
    {
        // Convert to lowercase and remove special characters
        $slug = preg_replace('/[^A-Za-z0-9-]+/', $separator, strtolower(trim($string)));

        // Remove duplicate separators
        $slug = preg_replace('/' . preg_quote($separator, '/') . '+/', $separator, $slug);

        // Trim separator from both ends
        return trim($slug, $separator);
    }
}
if (!function_exists('hasPermission')) {
    function hasPermission($key_word)
    {
        $user = auth()->user();
        $permissions = [];

        if ($user) {
            $permissions = is_array($user->permissions)
                ? $user->permissions
                : json_decode($user->permissions, true);
        }

        return in_array($key_word, $permissions ?? []) || $user?->role_id == 1;
    }
}
if (!function_exists('unslugify')) {
    function unslugify($slug, $separator = '-')
    {
        // Replace the separator with space and capitalize each word
        return ucwords(str_replace($separator, ' ', $slug));
    }
}
if (!function_exists('adminInfo')) {
    function adminInfo($value)
    {
        return User::where('user_type', 'admin')->orWhere('role_id', 1)->value($value);
    }
}

if (!function_exists('trending_movies')) {
    function trending_movies()
    {
        return App\Models\Movie::where('status', 1)->get();
    }
}
if (!function_exists('config')) {
    function config($title)
    {
        $config = Config::where('title', $title)->first();
        return $config->title;
    }
}
if (!function_exists('get_movie_quality')) {
    function get_movie_quality($input)
    {
        if (!is_numeric($input)) {
            return $input;
        }
        $quality = VideoQuality::find($input);
        return $quality ? $quality->quality : 'Unknown';
    }
}
if (!function_exists('get_movie_genre')) {
    function get_movie_genre($value)
    {
        $genre = json_decode($value);
        $genre = is_array($genre) ? $genre : [];
        if (count($genre) > 0) {
            return Genre::where('id', $genre[0])->value('name');
        }
        return null;
    }
}
if (!function_exists('get_movie_category')) {
    function get_movie_category($value)
    {
        if ($value) {
            return Category::where('id', $value)->value('video_type');
        } else {
            return false;
        }
    }
}
if (!function_exists('get_rating')) {
    function get_rating($value)
    {
        return number_format((float) $value, 1);
    }
}
if (!function_exists('get_all_genres')) {
    function get_all_genres()
    {
        return Genre::where('status', 1)->get();
    }
}
if (!function_exists('get_genre')) {
    function get_genre($data, $key, $value = null)
    {
        if ($data == 'name') {
            return Genre::where('id', $key)->value('name');
        }
        $genre = json_decode($data);
        if (isset($genre)) {
            return Genre::where('id', $genre[$key])->value($value);
        }
        return null;
    }
}
if (!function_exists('get_video_type')) {
    function get_video_type($id, $value)
    {
        return Category::where('id', $id)->value($value);
    }
}
if (!function_exists('get_video_quality')) {
    function get_video_quality($data, $value)
    {
        if ($data == 'HD') {
            return $data;
        } else {
            return VideoQuality::where('id', $data)->value($value);
        }
    }
}
if (!function_exists('getAllMovieLanguages')) {
    function getAllMovieLanguages()
    {
        return MovieLanguage::where('status', 1)->get();
    }
}
if (!function_exists('get_all_countries')) {
    function get_all_countries()
    {
        return Country::where('status', 1)->get();
    }
}

if (!function_exists('apiImage')) {
    /**
     * @param  string  $url  Relative path or key (same as stored in JSON fields)
     * @param  string  $string  Folder prefix to rewrite to images/ (legacy local paths)
     * @param  string  $storage  lmssetting value: local, aws_s3, wasabi, do
     */
    function apiImage($url, $string = '', $storage = 'local')
    {
        $url = trim((string) $url);

        if (filter_var($url, FILTER_VALIDATE_URL)) {
            return $url;
        }

        if ($url === '') {
            return url('images/default.png');
        }

        if ($string) {
            $url = str_replace($string . '/', 'images/', $url);
        }
        $url = str_replace(['uploads/', 'public/public/'], ['', 'public/'], $url);
        $url = ltrim($url, '/');

        if ($storage === 'local') {
            if ($url !== '' && file_exists(public_path($url)) && is_file(public_path($url))) {
                return url($url);
            }
            // Paths like "live_tv_thumbs/..." after stripping "uploads/" still live under public/uploads/
            if ($url !== '' && ! Str::startsWith($url, 'uploads/')) {
                $underUploads = 'uploads/' . $url;
                if (file_exists(public_path($underUploads)) && is_file(public_path($underUploads))) {
                    return url($underUploads);
                }
            }

            return url('images/default.png');
        }

        $media = get_media($url, $storage);

        return $media !== false ? $media : url('images/default.png');
    }
}

if (!function_exists('apiImageFromJson')) {
    function apiImageFromJson($json, string $field = 'original_image', string $string = ''): string
    {
        if (empty($json) || ! is_string($json)) {
            return url('images/default.png');
        }
        $decoded = json_decode($json);
        if (! $decoded) {
            return url('images/default.png');
        }
        $storage = isset($decoded->storage) && $decoded->storage !== '' ? $decoded->storage : 'local';
        $tryKeys = array_unique(array_merge(
            [$field],
            ['image_1080x720', 'image_240x240', 'image_80x80', 'original_image']
        ));
        foreach ($tryKeys as $key) {
            if (! empty($decoded->{$key})) {
                return apiImage($decoded->{$key}, $string, $storage);
            }
        }

        return url('images/default.png');
    }
}


if (!function_exists('related_movies')) {
    function related_movies()
    {
        return Movie::latest()->limit(15)->get();
    }
}
if (!function_exists('recommended_movies')) {
    function recommended_movies()
    {
        return Movie::where('status', 1)->where('is_recommended', 1)->latest()->limit(15)->get();
    }
}
if (!function_exists('playlists')) {
    function playlists()
    {
        return auth()->user()->playLists ?? [];
    }
}
if (!function_exists('liveTvCategories')) {
    function liveTvCategories()
    {
        return LiveTvCategory::where('status', 1)->latest()->limit(4)->get();
    }
}
if (!function_exists('getLiveTvRating')) {

    function getLiveTvRating($id, $withStars = true)
    {
        $average = Review::where('reviewable_type', 'App\Models\LiveTv')
            ->where('reviewable_id', $id)
            ->avg('rating');

        return $average !== null ? round((float) $average, 1) : 0.0;
    }
}

if (!function_exists('episode_view')) {
    function episode_view($id)
    {
        return WatchHistory::where('watchable_type', 'episode')->where('watchable_id', $id)->count();
    }
}
if (!function_exists('movie_files')) {
    function movie_files($id)
    {
        return MovieFile::where('video_id', $id)->orderBy('order', 'ASC')->get();
    }
}
if (!function_exists('blogCategories')) {
    function blogCategories()
    {
        return BlogCategory::where('status', 1)->get();
    }
}
if (!function_exists('get_review_count')) {
    function get_review_count($id)
    {
        return Review::where('reviewable_type', 'App\Models\Blog')->where('reviewable_id', $id)->count();
    }
}
if (!function_exists('movieIndustries')) {
    function movieIndustries()
    {
        return MovieIndustry::where('status', 1)->get();
    }
}
if (!function_exists('get_yrsetting')) {

    function get_yrsetting($setting_for)
    {
        return config()->get('lmssetting.' . $setting_for);
    }
}

if (!function_exists('get_currency_symbol')) {

    function get_currency_symbol()
    {
        $currency_symbol = Currency::where('id', get_config('currency_symbol'))->value('symbol');
        return $currency_symbol;
    }
}
if (!function_exists('get_season')) {

    function get_season($series)
    {
        $seasons = Season::whereJsonContains('tv_show_id', (string)$series)->orderBy('order', 'desc')->get();
        return $seasons;
    }
}
if (!function_exists('validity')) {

    function validity($hours)
    {
        $hours = (int) $hours;
        $days = intdiv($hours, 24);
        $remainingHours = $hours % 24;

        $validity = '';

        // If exactly 1 day (24 hours)
        if ($hours === 24) {
            $validity = '1 day';
        }
        // More than 1 day
        elseif ($hours > 24) {
            $validity .= $days . ' ' . ($days === 1 ? 'day' : 'days');

            if ($remainingHours > 0) {
                $validity .= ' ' . $remainingHours . ' ' . ($remainingHours === 1 ? 'hour' : 'hours');
            }
        }
        // Less than 1 day
        else {
            $validity = $hours . ' ' . ($hours === 1 ? 'hour' : 'hours');
        }

        return $validity;
    }
}
if (!function_exists('get_episode_by_season')) {

    function get_episode_by_season($series)
    {
        $episodes = Episode::where('series_id', (string)$series)->orderBy('order', 'desc')->withCount('downloadLinks')->get();
        return $episodes;
    }
}
if (!function_exists('get_discount_percentage')) {

    function get_discount_percentage($price, $discount)
    {
        if ($price <= 0 || $discount <= 0) {
            return 0;
        }
        $percentage = ($discount / $price) * 100;
        return round($percentage, 2) . '%'; // returns percentage with 2 decimal points
    }
}
if (!function_exists('languageCheck')) {
    function languageCheck()
    {
        if (session('locale')) {
            $lang = session('locale');
        } elseif (setting('default_language')) {
            $lang = setting('default_language');
        } else {
            $lang = 'en';
        }

        return $lang;
    }
}

if (!function_exists('get_currency')) {

    function get_currency($price)
    {
        if (!$price || is_numeric($price) === false) {
            return get_currency_symbol() . '0';
        }
        // Get default values if not provided
        $currency_symbol = get_currency_symbol();
        $currency_symbol_position = get_config('currency_symbol_position');

        // Format price with 2 decimals
        $formatted_price = number_format($price, 0);

        // Handle position
        switch ($currency_symbol_position) {
            case 'left':
                return $currency_symbol . $formatted_price;
            case 'left_with_space':
                return $currency_symbol . ' ' . $formatted_price;
            case 'right':
                return $formatted_price . $currency_symbol;
            case 'right_with_space':
                return $formatted_price . ' ' . $currency_symbol;
            default:
                return $currency_symbol . $formatted_price;
        }
    }
}

if (!function_exists('setLanguageRedirect')) {
    function setLanguageRedirect($language_locale): array|string
    {
        return url('/change-language') . '/' . $language_locale;
    }

    if (!function_exists('new_tv_shows')) {
        function new_tv_shows()
        {
            return TvShow::where(['status' => 1])->latest()->get();
        }
    }
    if (!function_exists('blockbuster_tv_shows')) {
        function blockbuster_tv_shows()
        {
            return TvShow::where(['status' => 1, 'is_blockbuster' => 1])->limit(10)->get();
        }
    }
    if (!function_exists('liveTvs')) {
        function liveTvs()
        {
            return LiveTv::where('status', 1)->get();
        }
    }

    if (!function_exists('runtime')) {
        function runtime($minutes)
        {
            $minutes = (int) $minutes;
            if ($minutes < 1) {
                return '0m';
            }
            $h = floor($minutes / 60);
            $m = $minutes % 60;
            $result = '';
            if ($h > 0) {
                $result .= $h . 'h ';
            }
            if ($m > 0) {
                $result .= $m . 'm';
            }
            return trim($result);
        }
    }
    if (!function_exists('get_rent_expire_at')) {
        function get_rent_expire_at($type, $video_id, $user_id = null)
        {
            if (!$user_id) {
                // If user_id is not provided, use the authenticated user's ID
                $user_id = auth()->id();
            }

            if (!$user_id || !$video_id) {
                return null;
            }

            if ($type === 'movie') {
                $video = Movie::find($video_id);
            } elseif (in_array($type, ['series', 'tv'])) {
                $video = TvShow::find($video_id); // or TvEpisode depending on your model
            } else {
                return null; // unsupported type
            }

            if (!$video) {
                return null;
            }

            $rental_history = RentalHistory::where('video_id', $video_id)
                ->where('video_type', $type) // make sure your table tracks this
                ->where('user_id', $user_id)
                ->latest()
                ->first();

            if (!$rental_history || !$rental_history->created_at) {
                return null;
            }

            if ($rental_history->status == 0) {
                return false;
            }

            $base_time = Carbon::parse($rental_history->created_at);
            $duration = $video->rental_duration ?? 1;
            $rental_type = $video->rental_type ?? 'hours';

            $expire_at = match ($rental_type) {
                'hours' => $base_time->clone()->addHours($duration),
                'day', 'days' => $base_time->clone()->addDays($duration),
                'month', 'months' => $base_time->clone()->addMonths($duration),
                'year', 'years' => $base_time->clone()->addYears($duration),
                default => $base_time->clone()->addHours(24),
            };

            if (now()->gt($expire_at)) {
                return null;
            }

            return $expire_at->format('d/m/y h:i A');
        }
    }

    if (!function_exists('is_rent_expire')) {
        function is_rent_expire($type, $video_id)
        {
            $date = get_rent_expire_at($type, $video_id);
            if (!$date) {
                return false;
            }

            $carbonDate = Carbon::createFromFormat('d/m/y h:i A', $date);

            if ($carbonDate->timestamp > time()) {
                return true;
            } else {
                return false;
            }
        }
    }
    if (!function_exists('is_rented')) {
        function is_rented($type, $video_id, $user_id = null)
        {

            if (!$user_id || !$video_id) {
                return false;
            }

            $date = get_rent_expire_at($type, $video_id, $user_id);
            if (!$date) {
                return false;
            }

            $carbonDate = Carbon::createFromFormat('d/m/y h:i A', $date);

            if ($carbonDate->timestamp > time()) {
                return true;
            } else {
                return false;
            }
        }
    }


    if (!function_exists('getVideoAdTimestamp')) {
        function getVideoAdTimestamp($runtimeInMinutes, $adDurationInSeconds, $type = 'start')
        {
            $totalSeconds = (int) round($runtimeInMinutes * 60);

            $targetSeconds = match ($type) {
                'start' => max($totalSeconds - $adDurationInSeconds, 0),
                'end' => $totalSeconds,
                default => throw new InvalidArgumentException("Invalid type: use 'start' or 'end'")
            };

            $hours = floor($targetSeconds / 3600);
            $minutes = floor(($targetSeconds % 3600) / 60);
            $seconds = $targetSeconds % 60;

            return sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds);
        }
    }

    if (!function_exists('is_rental')) {
        function is_rental($type, $video_id)
        {
            if ($type == 'movie') {
                $video = Movie::where('id', $video_id)->first();
            } elseif ($type == 'series') {
                $video = TvShow::where('id', $video_id)->first();
            }
            if (@$video->is_rental) {
                return true;
            } else {
                return false;
            }
        }
    }

    if (!function_exists('is_free')) {
        function is_free($type, $video_id)
        {
            if ($type == 'movie') {
                $video = Movie::where('id', $video_id)->first();
            } elseif ($type == 'series') {
                $video = TvShow::where('id', $video_id)->first();
            }
            if (@$video->is_free > 0) {
                return true;
            } else {
                return false;
            }
        }
    }



    if (!function_exists('getSlug')) {
        function getSlug($table, $name, $column = 'slug', $id = null): string
        {
            $slug = \Illuminate\Support\Str::slug($name);
            $count = \Illuminate\Support\Facades\DB::table($table)->when($id, function ($query) use ($id) {
                $query->where('id', '!=', $id);
            })->where($column, $slug)->count();
            if ($count > 0) {
                $slug = $slug . '-' . strtolower(\Illuminate\Support\Str::random(5));
            }

            return $slug;
        }
    }

    if (!function_exists('activeLanguages')) {
        function activeLanguages()
        {
            return Language::where('status', 1)->get();
        }
    }
    if (!function_exists('curlRequest')) {
        function curlRequest($url, $fields, $method = 'POST', $headers = [], $is_array = false)
        {
            $client = new Client(['verify' => false]);

            $data = is_string($fields) ? [
                'body' => $fields,
                'headers' => $headers,
            ] : [
                'form_params' => $fields,
                'headers' => $headers,
            ];

            $response = $client->request($method, $url, $data);
            $result = $response->getBody()->getContents();

            return json_decode($result, $is_array);
        }
    }

    if (!function_exists('watch_history_duration')) {
        function watch_history_duration($video_type, $total_duration, $watched_seconds, $episode_order = 1)
        {
            // Convert seconds to minutes
            $watched_mins = floor($watched_seconds / 60);
            $total_mins = floor($total_duration / 60);

            // Calculate remaining seconds
            $watched_secs = $watched_seconds % 60;
            $total_secs = $total_duration % 60;

            if ($video_type == 'movie') {
                return sprintf(
                    "%d of %d mins",
                    $watched_mins,
                    $total_mins
                );
            } elseif ($video_type == 'episode') {
                return sprintf(
                    "Episode - " . $episode_order . " %d of %d mins",
                    // "Episode - ".$episode_order." %d:%02d of %d:%02d mins",
                    $watched_mins,
                    $watched_mins,
                    $watched_secs,
                    $total_mins,
                    $total_secs
                );
            }

            return '';
        }
    }

    if (!function_exists('get_movie_url')) {
        function get_movie_url($movie_id)
        {
            $movie = MovieFile::where('video_id', $movie_id)->orderBy('id', 'desc')->first();

            return ($movie && $movie->file_url) ? true : false;
        }
    }


    if (!function_exists('demoVideos')) {
        function demoVideos()
        {
            // Path to your JSON file in public folder
            $path = public_path('video_links.json');

            // Check if file exists
            if (!file_exists($path)) {
                return [];
            }

            // Get file content and decode JSON
            $json = file_get_contents($path);
            $data = json_decode($json, true);

            // Return decoded array (or empty array if invalid)
            return is_array($data) ? $data : [];
        }
    }

    if (!function_exists('isRtl')) {

        function isRtl()
        {
            $system_languages = Language::where('status', 1)->get();
            $default_language = Language::where('id', get_config('default_language'))->value('locale');

            $current_language = session()->has('locale') ? session()->get('locale') : $default_language;

            $rtl_langs = ['ar', 'he', 'ur', 'arc', 'az', 'dv', 'ku', 'fa'];
            if(in_array($current_language, $rtl_langs)) {
                return 'rtl';
            } else {
                return 'ltr';
            }
    
        }
    }
}