<?php

namespace App\Providers;

use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider;
use App\Helpers\DatabaseSchema\CustomBluePrint;
use App\Helpers\DatabaseSchema\Schema as CustomSchema;

class AppServiceProvider extends ServiceProvider{
    /**
     * Register any application services.
     *
     * @return void
     * @throws \Exception
     */
    public function register(){
        //toutes le colonnes 'varchar' seront par defaut (255 caractères)
        Schema::defaultStringLength(255);


        $location = user_location();
        $timezone =  env("APP_TIME_ZONE","Africa/Malabo");
        if (is_array($location) and isset($location['timezone'])){
            $timezone = $location['timezone'];
        }

        // fixe le fuseau horaire de l'application au fuseau de l'utilisateur
        date_default_timezone_set($timezone);
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot(){
        Paginator::useBootstrap();

        Relation::enforceMorphMap(config('morphs-map'));

        JsonResource::withoutWrapping();

        //Lorsque la requête contient le paramètre "showed_all"
        request()->whenHas("showed_all",function ($input){
            //Demande aux json-ressources de laravel de mapper le retour des données dans un attribut 'data'
            JsonResource::wrap("data");
        });

        //demande à 'Carbon' d'uliser la langue de l'application
        Carbon::setLocale($this->app->getLocale());

        // Definition du macro "whereLike" sur le Builder d'Eloquent
        EloquentBuilder::macro("whereLike",function ($attributes,$search){
            $attributes = (array) $attributes;
            if (is_array($attributes)){
                foreach (Arr::wrap($attributes) as $attribute){
                    $this->orWhere($attribute,"like","{$search}%");
                }
            }
            return $this;
        });

        // Definition du macro "whereDateBetween" sur le Builder d'Eloquent
        EloquentBuilder::macro("whereDateBetween",function ($attributes,$start_date,$end_date){
           return $this->where(
                fn ($query) => $query->whereDate($attributes,">=",format_date($start_date,'Y-m-d'))
                                     ->whereDate($attributes,"<=",format_date($end_date,'Y-m-d'))
            );
        });

        EloquentBuilder::macro("whereContains",function ($attributes, $search){
           return $this->whereIn($attributes,(is_string($search)) ? explode(",",$search) : $search);
        });

        // Definition du macro "orWhereMultiple" sur le Builder d'Eloquent
        EloquentBuilder::macro("orWhereMultiple",function ($attributes, $search){
            $attributes = (array) $attributes;
            if (is_array($attributes)){
                foreach (Arr::wrap($attributes) as $attribute){
                    $this->orWhere($attribute,"{$search}");
                }
            }
            return $this;
        });

        // Definition du macro "wherePeriod" sur le Builder d'Eloquent
        // clause de recherche
        EloquentBuilder::macro("wherePeriod",function ($attributes, $search){
            $attributes = (array) $attributes; // [2022-04 , 2022-01]
            if (is_array($attributes)){
                foreach (Arr::wrap($attributes) as $attribute){
                    $date = $search; // 2022-02
                    $year = date("Y",strtotime($date)); // 2022
                    $month = date("m",strtotime($date)); // 04
                    $this->whereYear($attribute,"{$year}")
                        ->whereMonth($attribute,"{$month}");
                }
            }else{
                $date = $search; // 2020-04
                $year = date("Y",strtotime($search)); // 2020
                $month = date("m",strtotime($search)); // 04
                $this->whereYear($attributes,"{$year}")
                    ->whereMonth($attributes,"{$month}");
            }
            return $this;
        });


        //Converti tous les éléments (array ou objet) d'une collection en collection
        Collection::macro('recursive', function () {
            return $this->map(function ($value) {
                return  (is_array($value) || is_object($value))
                        ? collect($value)->recursive()
                        : $value;
            });
        });

        if (env('DISPLAY_QUERY_IN_CONSOLE',false)){
            /*ecoute chaque requete entrante dans la bd*/
            DB::listen(function ($query) {
                $userAgent = request()->userAgent();
                $bindings  = json_encode($query->bindings);
                $content   = "[SQL] {$query->sql} in {$query->time} s\n
                              [bindinds]: {$bindings}\n [userAgent]: {$userAgent} \n";

                /*imprime le message sur le terminal courant en exécution (s'il est ouvert)*/
                file_put_contents('php://stderr', $content);
            });
        }





        CustomSchema::blueprintResolver(static function($table, $callback) {
            return new CustomBluePrint($table, $callback);
        });

//        Schema::blueprintResolver(static function($table, $callback) {
//            return new CustomBluePrint($table, $callback);
//        });


        if (CustomSchema::hasTable("migrations")){
            DB::table('migrations')
                ->whereIn('migration',[
                    "2024_31_17_141516_add_fields_authorable",
                    "2024_02_21_100404_add_field_to_payment_method_table",
                    "2022_10_31_204157_create_stock_management_tables",
                ])
                ->delete();
        }

    }
}
