<?php

use App\Classes\Sanitize;
use App\Model\StaticPage;
use App\Rules\MimeMatch;
use Illuminate\Http\Request as HttpRequest;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\MessageBag;
use Illuminate\Support\Number;
use Illuminate\Support\ViewErrorBag;
use Modules\Admin\Entities\Admin;
use Modules\Block\Entities\Block;
use Modules\User\Entities\User;
use Nwidart\Modules\Facades\Module;

/**
 * Get the instance of Uno Singleton - located at \app\Providers\AppServiceProvider.
 * @return App\Classes\Uno
 */
function uno()
{
    return app('uno');
}

function admin(): Admin|null
{
    return auth('admin')->check() ? auth('admin')->user() : null;
}

function has_route($name)
{
    return Route::has($name);
}

function route_match($name = '')
{
    return Route::currentRouteNamed($name);
}

function route_active($name = '')
{
    return route_match($name) ? 'active' : '';
}

function route_is_equal($name)
{
    return Route::currentRouteName() == $name;
}

function api_request()
{
    return str_contains(URL::full(), 'api');
}

function admin_dashboard()
{
    return str_contains(URL::full(), 'uno-dashboard');
}

function url_active($sub_url)
{
    return URL::current() == url('/') . $sub_url;
}

function is_homepage()
{
    return Route::currentRouteNamed('index');
}

function static_page($id)
{
    return StaticPage::active()->find($id);
}

function only_numbers($string)
{
    return preg_replace('/[^0-9]+/', '', $string);
}

function only_characters($string, $replace = '')
{
    return preg_replace('/[^0-9a-zA-Z]+/', $replace, $string);
}

function remove_break_new_lines($string, $replace = '')
{
    return preg_replace("/\r\n|\r|\n/", $replace, $string);
}

function is_even($number, $index = false)
{
    return ($index ? $number + 1 : $number) % 2 == 0;
}

function get_lang($locale = null)
{
    if (!$locale) {
        $locale = config('app.default_locale');
    }

    return array_flip(config('app.available_locales'))[$locale];
}

function in_percentage($number, $precision = 0, $max_precision = 2)
{
    return Number::percentage($number, $precision, $max_precision);
}

function in_abbreviate($number)
{
    return Number::abbreviate($number);
}

function in_filesize($number)
{
    return Number::filesize((int) $number * 1024);
}

function get_uploaded_file_name(HttpRequest $request, $name, $filename = null)
{
    $input = $request->file($name) ?: $request->input($name);

    if ($input instanceof UploadedFile) {
        $filename = clean_filename($input->getClientOriginalName(), $input->extension());
    } else if (is_string($input)) {
        $filename = basename($input);
    }

    return $filename;
}

function file_validation($value = null, $mimes = 'png,jpeg,jpg', $required = false, $max = 1024, $sometimes = true)
{
    $max = config('app.max_file_size');

    if (is_string($value)) {
        return [$sometimes ? 'sometimes' : 'bail', $required ? 'required' : 'nullable', 'string', 'starts_with:files', 'ends_with:' . $mimes];
    } else {
        return [$sometimes ? 'sometimes' : 'bail', $required ? 'required' : 'nullable', 'file', 'mimes:' . $mimes, 'max:' . $max, new MimeMatch];
    }
}

function anti_xss($value, $ignore = [])
{
    $trim = true;
    $clean = true;

    if ($value === null || is_bool($value) || is_int($value) || is_float($value)) {
        return $value;
    }

    if (!is_array($value)) {
        return sanitize((string) $value, $trim, $clean);
    }

    $final = [];

    foreach ($value as $k => $v) {
        if ($v !== null && !in_array($k, $ignore)) {
            $final[$k] = anti_xss($v);
        } else {
            $final[$k] = $v;
        }
    }

    return $final;
}

function sanitize(string $value, bool $trim, bool $clean)
{
    if ($trim) {
        $value = trim($value);
    }

    if ($clean) {
        $value = Sanitize::init()->clean($value);
    }

    if ($trim) {
        $value = trim($value);
    }

    return $value;
}

function mask(string $string = '', int $visible = 3, int $extra = 5)
{
    if (!$string) {
        return '';
    }

    $length = strlen($string);
    $doubleVisible = $visible * 2;

    if ($doubleVisible >= $length) {
        $visible = 3;
        $doubleVisible = $visible * 2;
    }

    $start = substr($string, 0, $visible);
    $end = substr($string, "-{$visible}");

    $hiddenCount = ($length - $doubleVisible) + $extra;

    return $start . str_repeat('*', $hiddenCount) . $end;
}

function get_dt_column_config(string $data, ?string $name = null, bool $orderable = true, bool $searchable = true, string $default = '-', ?string $class = null, mixed $entity = null, array $can = [], bool $visible = true)
{
    if ($entity && !admin()->canAny($can, $entity)) {
        return null;
    }

    return [
        'data' => $data,
        'name' => $name ?: $data,
        'orderable' => $orderable,
        'searchable' => $searchable,
        'visible' => $visible,
        'defaultContent' => $default,
        'className' => $class,
    ];
}

function list_of_days()
{
    return [
        'monday',
        'tuesday',
        'wednesday',
        'thursday',
        'friday',
        'saturday',
        'sunday',
    ];
}

function format_bytes($size, $precision = 0)
{
    return Number::fileSize($size, $precision);
}

function clean_filename($file, $extension)
{
    return strtolower(only_characters(pathinfo($file, PATHINFO_FILENAME), '_')) . '.' . $extension;
}

function generate_password()
{
    $generate_password = str()->password(length: (config('password.min_length', 12) - 1), symbols: false);

    // NOTE: generate password less 1 char to manually insert random 1 symbol
    $symbols = collect(['~', '!', '#', '$', '(', ')', '-', '_', '?', '/', '{', '}', '[', ']']);

    $collect_password = collect(str_split($generate_password));

    $collect_password->push($symbols->random());

    return $collect_password->shuffle()->implode('');
}

function disk_public()
{
    return Storage::disk('public');
}

function disk_private()
{
    return Storage::disk('private');
}

function upload_file(HttpRequest $request, $name, $folder = '', $fallback = null, $disk = 'public')
{
    $input = $request->file($name) ?: $request->input($name);

    if ($input instanceof UploadedFile) {
        $input = $input->store('files/' . $folder, $disk);
    }

    return $input ?: $fallback;
}

function asset_exists($path, $disk = 'public')
{
    if (is_null($path) || filter_var($path, FILTER_VALIDATE_URL)) {
        return false;
    }

    return Storage::disk($disk)->exists($path);
}

function destroy_asset($path, $disk = 'public')
{
    if (filter_var($path, FILTER_VALIDATE_URL)) {
        //
    } else if (asset_exists($path)) {
        if (!str_starts_with($path, 'files/sample')) {
            Storage::disk($disk)->delete($path);
        }
    }
}

function get_content_block($slug): ?string
{
    $block = Block::whereSlug($slug)->active()->first();

    return $block?->editor_content ?: view('block::fallback.' . $slug)->render();
}

function previous_route()
{
    try {
        return Route::getRoutes()->match(Request::create(url()->previous()))->getName();
    } catch (\Exception $e) {
        return null;
    }
}

function flash_error_message($message)
{
    $message = new MessageBag((array) $message);

    $errors = session()->get('errors', new ViewErrorBag);

    if (! $errors instanceof ViewErrorBag) {
        $errors = new ViewErrorBag;
    }

    session()->flash(
        'errors', $errors->put('default', $message)
    );
}

function belongs_to_model_policy(Admin|User $auth, $model = null, $allow = false, $compare = false)
{
    if ($auth instanceof User) {
        if (is_null($model) || !$model->exists) {
            return $allow;
        }

        return $compare;
    }

    return false;
}

function merge_url_query_params($full_url, $new_params = [])
{
    if ($query = parse_url($full_url, PHP_URL_QUERY)) {
        list($url, $query) = explode('?', $full_url);
    } else {
        $url = $full_url;
    }

    $old_params = [];

    if ($query) {
        parse_str($query, $old_params);
    }

    return $url . '?' . http_build_query(array_merge($old_params, $new_params));
}

function module_enabled($name)
{
    return Module::isEnabled($name);
}

function convert_duration($duration)
{
    try {
        $interval = new DateInterval($duration);
        $formatted = $interval->format('%H:%I:%S');

        list($hours, $minutes, $seconds) = explode(':', $formatted);

        $duration = '';

        if (intval($hours) > 0) {
            $duration .= $hours . ':';
        }

        return $duration . $minutes . ':' . $seconds;
    } catch (\Exception $e) {
        return null;
    }
}

function fallback_via_placeholder($value, $extension = 'png')
{
    list($https, $remaining) = explode('via.placeholder.com', $value);

    list($params, $query) = explode('?', str_replace('.' . $extension, '', $remaining));

    return $https . 'placehold.co' . $params . '/000?' . $query;
}

function date_formatted($date, $format = 'd/m/Y')
{
    return carbon($date)->format($format);
}

function time_formatted($time, $format = 'h:i A')
{
    return Carbon::createFromFormat('H:i:s', $time)->format($format);
}

if (! function_exists('carbon')) {
    function carbon($date)
    {
        return Carbon::parse($date);
    }
}
