<?php

namespace App\Api\V1\Controllers;

use App\Models\RouteStop;
use Illuminate\Support\Facades\Date;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Tymon\JWTAuth\JWTAuth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Route;
use App\Models\RouteLog;
use App\Models\RouteLogGps;
use App\Models\RouteLogKid;
use App\Models\Kid;
use App\Models\KidActiveRoute;
use Tymon\JWTAuth\Exceptions\JWTException;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Carbon\Carbon;
use Auth;
use DB;
use Illuminate\Support\Facades\Log;

use App\Traits\OneSignalMessages;

class RouteLogController extends Controller
{
    use OneSignalMessages;
    
    public function createLog(Request $request)
    {
        $route_stops = collect($request->input('route_stops'));
        
        
        $routeLog = new RouteLog([
            'route_id' => $request->input('route_id'),
            'start' => Carbon::now()->toDateTimeString(),
        ]);
        $routeLog->status_route = 1; // este campo se���ala que se inicio la ruta
        if(!$routeLog->save()) {
            throw new HttpException(500);
        }
        
        //Agregamos el route log a la ruta
        $route = $routeLog->route;
        // Si es ruta tipo=1 ida, tipo=2 vuelta
        // Estados ni���os -> 0=casa, 1=bus, 2=colegio
        $initialState = ($route->type == 1) ? 0 : 2;
        
        $onlyKids = $route_stops->where('kid_id', '!=', NULL);
        $kids = $onlyKids->pluck('kid_id');

        Kid::whereIn('id', $kids)->update(['status'=>$initialState]);

        // se almacenaran los ids de los padres para enviar el mensaje
        // no se repetiran los padres si esque hay mas de 1 hijo asociado
        $arregloPadres = [];
        $contador = 0;
        foreach($onlyKids as $stop) {
            //$parents = $stop->kid->users->pluck('id');

            // crear en kidActiveRoute // verificara que el usuario estuvo en la ruta
            $kidActiveRoute = new KidActiveRoute();

            $kidActiveRoute->route_log_id = $routeLog->id;
            $kidActiveRoute->estado_nino_ruta = 1;
            $kidActiveRoute->id_kid = $stop['kid_id'];
            $kidActiveRoute->created_at = \Carbon\Carbon::now();
            $kidActiveRoute->updated_at = \Carbon\Carbon::now();
            $kidActiveRoute->save();


            $routeLogKid = new RouteLogKid();
            $routeLogKid->route_log_id = $routeLog->id;
            $routeLogKid->kid_id = $stop['kid_id'];
            $routeLogKid->status = $initialState;

            //$routeLogKid->save();

            $kid = Kid::findOrFail($routeLogKid->kid_id);
            $idUser =  $kid->users()->pluck('id');
            $idUser = str_replace('[', '', $idUser);
            $idUser = str_replace(']', '', $idUser);
            if(!in_array($idUser, $arregloPadres) ){
                array_push($arregloPadres, $idUser);
                $contador++;

            }

        }

        //enviar notificacion empezo la ruta
        $this->sendNotificationInitRouteParents( $route->driver->user->first_name, $arregloPadres);
        return response()->json($routeLog);
    }

    public function existeNinoEnBus($kid_id,$ninosBus){
        $existe = false;
        $kid_status = 0;
        foreach ($ninosBus as $nino){
            if($nino['kid_id'] == $kid_id){
                $existe = true;
                $kid_status = $nino['kid_status'];
                break;
            }
            //Log::info($nino);
            //Log::info($kid_id);
        }
        return (object)['existe' => $existe, 'kid_status' => $kid_status];
        //return $existe;
    }
    
    public function endLog(Request $request, $log_id,$tipo_fin_ruta)
    {
        // tipo fin ruta si es 1 indica que fue el ciclo natural
        // tipo fin ruta si es 2 indica que el ciclo fue cortado (detener ruta boton )
        $routeLog = RouteLog::with('route.routeStops.kid')->findOrFail($log_id);
        $ninosBus =  $request->input('ninosBus');
        $lat =  $request->input('lat');
        $lng =  $request->input('lng');

        // se almacenaran los ids de los padres para enviar el mensaje
        // no se repetiran los padres si esque hay mas de 1 hijo asociado
        $arregloPadres = [];
        $contador = 0;
        foreach($routeLog->route->routeStops as $stop) {
            $kid = null;
            $objExiste = null;
            $kid = Kid::findOrFail($stop->kid_id);
            $objExiste = $this->existeNinoEnBus($kid->id, $ninosBus);

            if($objExiste->existe){
              /*  if ($routeLog->route->type === 1) {
                    $kid->status = $objExiste->kid_status;
                    $kid->update();
                    $routeLogKid = new RouteLogKid();
                    $routeLogKid->route_log_id = $log_id;
                    $routeLogKid->kid_id = $stop->kid_id;
                    $routeLogKid->status = 2; // $objExiste->kid_status;
                    $routeLogKid->lat = $lat;
                    $routeLogKid->lng = $lng;
                    $routeLogKid->save();
                } else {
                    $kid->status = $objExiste->kid_status;
                    $kid->update();
                    $routeLogKid = new RouteLogKid();
                    $routeLogKid->route_log_id = $log_id;
                    $routeLogKid->kid_id = $stop->kid_id;
                    $routeLogKid->status = 0;//$objExiste->kid_status;
                    $routeLogKid->lat = $lat;
                    $routeLogKid->lng = $lng;
                    $routeLogKid->save();
                } */

                $idUser =  $kid->users()->pluck('id');
                $idUser = str_replace('[', '', $idUser);
                $idUser = str_replace(']', '', $idUser);
                if(!in_array($idUser, $arregloPadres) ){
                    array_push($arregloPadres, $idUser);
                    $contador++;
                }

            }

        }
        Log::info($arregloPadres);
        $routeLog->end = Carbon::now()->toDateTimeString();
        $routeLog->status_route = 0;



        if(!$routeLog->update()) {
            throw new HttpException(500);
        }
        else{
            if(count($arregloPadres) > 0){
             $timeOutNotification = config('onesignal.timeout_endlog_notification');
             //enviar notificacion termino la ruta a los padres
             $this->enviarNotification($routeLog,$arregloPadres,$timeOutNotification);
            }

        }

        return response()->json($routeLog);
    }


    public function enviarNotification($routeLog,$arregloPadres,$timeOutNotification){
        $this->sendNotificationFinishRouteParents( $routeLog->route->driver->user->first_name, $arregloPadres);
    }


    public function getLastRouteLogKidByIdRouteLog( $idKid,$idRouteLog)
    {
        $routeLogKid = RouteLogKid::where('route_log_id',$idRouteLog)->where('kid_id',$idKid)->latest()->first();

        return response()->json($routeLogKid);
    }

    public function getLastRouteLogGpsByIdRouteLog( $id)
    {
        $routeLogGps = RouteLogGps::where('route_log_id',$id)->orderBy('route_log_id', 'DESC')->first();

        return response()->json($routeLogGps);
    }

    /*public function getRouteLogByIdAndKidById( $idRouteLog, $idKid)
    {
       // $routeLog = RouteLog::findOrFail($idRouteLog);
        $routeLog = DB::select('SELECT public.route_log.id, public.route_log.route_id, public.route_log.start, public.route_log.end, public.route_log.created_at, public.route_log.updated_at, public.route_log.status_route  FROM public.route_log 
		inner join public.route on public.route.id = public.route_log.route_id
		inner join public.kid_active_route on public.kid_active_route.route_log_id = public.route_log.id
        where public.kid_active_route.id_kid = ?
        order by public.route_log.created_at desc limit 1', [$idKid])[0];
        $kid = Kid::findOrFail($idKid);
        $route = Route::where('id',$routeLog->route_id)->first();

        return response()->json([
            'routeLog' => $routeLog,
            'kid' => $kid,
            'route' => $route
        ]);
    }*/
    
    public function getRouteLogByIdAndKidById( $idRouteLog, $idKid)
    {
       // $routeLog = RouteLog::findOrFail($idRouteLog);
        $routeLog = DB::select('SELECT public.route_log.id, public.route_log.route_id, public.route_log.start, public.route_log.end, public.route_log.created_at, public.route_log.updated_at, public.route_log.status_route  FROM public.route_log 
		inner join public.route on public.route.id = public.route_log.route_id
		inner join public.kid_active_route on public.kid_active_route.route_log_id = public.route_log.id
        where public.kid_active_route.id_kid = ?
        order by public.route_log.created_at desc limit 1', [$idKid])[0];
        $kid = Kid::findOrFail($idKid);

        return response()->json([
            'routeLog' => $routeLog,
            'kid' => $kid
        ]);
    }
    
    
      public function getRouteByRouteLogId($kidId)
    {

        $route = DB::table('route')
        ->select('route.*')
        ->join('route_log', 'route.id', '=', 'route_log.route_id')
        ->join('kid_active_route', 'kid_active_route.route_log_id', '=', 'route_log.id')
        ->where('kid_active_route.id_kid', '=', $kidId)
        ->orderBy('route_log.created_at', 'desc')
        ->limit(1)
        ->get()
        ->first();
        //$route = RouteLog::with('route')->findOrFail($idRouteLog)->route;
        return response()->json([
            'route' => $route
        ]);
         
    }
    
    

   /* public function updateLocationSetStatusKid(Request $request){

        Log::info($request);

        $route = RouteLog::with('route')->where('id',$request->id)->first()->route;
        $status = 0;
        if($route->type == 1) {
            $status = 0;
        }
        if($route->type == 2) {
            $status = 2;
        }

            $findRoute = DB::update('update kid AS k
            set status = ?
            from route_log_kid as rlog
            where rlog.kid_id = k.id
            and rlog.route_log_id = ?', [$status, $request->id]);


        return response()->json($findRoute);

    }*/

    public function updateLocationSetStatusKid(Request $request){

        $validatedData = $request->validate([
            'route_log_id' => 'required|max:255',
            'lat' => 'required',
            'lng' => 'required',
        ]);
        $routeLogGps = new RouteLogGps($validatedData);

        if(!$routeLogGps->save()) {
            throw new HttpException(500);
        }


        $route = RouteLog::with('route')->where('id', $routeLogGps->route_log_id)->first()->route;
        /*$status = 0;
        if($route->type == 1) {
            $status = 0;
        }
        if($route->type == 2) {
            $status = 2;
        }

        $findRoute = DB::update('update kid AS k
            set status = ?
            from route_log_kid as rlog
            where rlog.kid_id = k.id
            and rlog.route_log_id = ?', [$status, $request->id]);*/


        return response()->json($routeLogGps);

    }
    
    public function updateLocation(Request $request)
    {
        $validatedData = $request->validate([
            'route_log_id' => 'required|max:255',
            'lat' => 'required',
            'lng' => 'required',
        ]);
        $routeLogGps = new RouteLogGps($validatedData);

        if(!$routeLogGps->save()) {
            throw new HttpException(500);
        }
        
        return response()->json($routeLogGps);
    }
    
    public function getLastGps(Request $request)
    {
        $routeLogId = $request->input('route_log_id');
     //   $routeLog = RouteLog::findOrFail($routeLogId);
     //   if ($routeLog->end === null) {
            $gps = RouteLogGps::orderBy('id', 'desc')->where('route_log_id', $routeLogId)->first();
     //   } else {
      //      $gps = null;
       // }
        
        return response()->json($gps);
    }
    
    public function getLog(Request $request)
    {
        
        $kid_id = $request->input('kid_id');
        
        $findRoute = DB::select('SELECT route_log.*
        FROM route_stop, route, route_log
        WHERE route_stop.kid_id = ?
        AND route.id = route_stop.route_id
        AND route_log.route_id = route.id
        AND route_log.end IS NULL 
        order by route_log.created_at desc
        LIMIT 1', [$kid_id]);
        
        if (count($findRoute) > 0){
            $routeLog = RouteLog::findOrFail($findRoute[0]->id);
            if ($routeLog->end !== null) {
                $routeLog = null;
            }
        } else {
            $routeLog = null;    
        }
        
        return response()->json($routeLog);
    }
    
    public function getOffBus(Request $request, $id)
    {
        $routeLogId = $request->input('route_log_id');
        $routeId = $request->input('route_id');
        $lat = $request->input('lat');
        $lng = $request->input('lng');
        
        $routeLog = RouteLog::findOrFail($routeLogId);
        $route = Route::with('driver.user')->findOrFail($routeId);
        
        $kid = Kid::with('users')->findOrFail($id);
        $kid->status = 0;
        if(!$kid->update()) {
            throw new HttpException(500);
        }
        
        $parents = $kid->users->pluck('id');
        //
        $this->sendNotificationKidToUserOffBus($route->name, $route->driver->user->first_name, $kid, $parents);

        // Actualizamos log
        $routeLogKid = new RouteLogKid();
        $routeLogKid->route_log_id = $routeLogId;
        $routeLogKid->kid_id = $id;        
        $routeLogKid->status = 0;
        $routeLogKid->lat = $lat;
        $routeLogKid->lng = $lng;
        
        if(!$routeLogKid->save()) {
            throw new HttpException(500);
        }
        
        return response()->json($kid);
    }
    
    public function getOffBusMassive(Request $request)
    {
        $stops = $request->input('stops');
        $school = $request->input('school');
        $routeLogId = $request->input('route_log_id');
        $routeId = $request->input('route_id');
        $lat = $request->input('lat');
        $lng = $request->input('lng');
        $route = Route::with('driver.user')->findOrFail($routeId);
        
        foreach ($stops as $stop) {
            if ($stop['kid'] !== null && $stop['school']['name'] === $school) {
                $kid = Kid::with('users')->findOrFail($stop['kid']['id']);
                $kid->status = 2;
                if(!$kid->update()) {
                    throw new HttpException(500);
                }

                //

                
                // Actualizamos log
                $routeLogKid = new RouteLogKid();
                $routeLogKid->route_log_id = $routeLogId;
                $routeLogKid->kid_id = $kid->id;        
                $routeLogKid->status = 2;
                $routeLogKid->lat = $lat;
                $routeLogKid->lng = $lng;
                
                if(!$routeLogKid->save()) {
                    throw new HttpException(500);
                }
                
                $parents = $kid->users->pluck('id');
        //
                Log::info("PROBANDO");
                $this->sendNotificationKidToUserEndRoute($route->name, $route->driver->user->first_name, $kid, $parents);
            }
        }

        $route_log = RouteLog::where('id',$routeLogId)->first();
        $route_log->status_route = 0;
        $route_log->save();
        return response()->json($stops);
    }
    
    public function getOnBus(Request $request, $id)
    {
        $routeLogId = $request->input('route_log_id');
        $routeId = $request->input('route_id');
        $lat = $request->input('lat');
        $lng = $request->input('lng');
        
        $routeLog = RouteLog::findOrFail($routeLogId);
        $route = Route::with('driver.user')->findOrFail($routeId);

        Log::info('lat lng: ' .$lat. "   " .$lng);
        $kid = Kid::with('users')->findOrFail($id);
        $kid->status = 1;
        
        if(!$kid->update()) {
            throw new HttpException(500);
        }
        
        $parents = $kid->users->pluck('id');
        //
        $this->sendNotificationKidToUserOnBus($route->name, $route->driver->user->first_name, $kid, $parents);
        
        // Actualizamos log
        $routeLogKid = new RouteLogKid();
        $routeLogKid->route_log_id = $routeLogId;
        $routeLogKid->kid_id = $id;        
        $routeLogKid->status = 1;
        $routeLogKid->lat = $lat;
        $routeLogKid->lng = $lng;
        if(!$routeLogKid->save()) {
            throw new HttpException(500);
        }
        
        return response()->json($kid);
    }
    
    public function getOnBusMassive(Request $request)
    {
        $routeLogId = $request->input('route_log_id');
        $routeId = $request->input('route_id');
        
        $routeLog = RouteLog::findOrFail($routeLogId);
        $route = Route::with('driver.user')->findOrFail($routeId);
        
        $stops = $request->input('stops');
        
        foreach ($stops as $stop) {
            if ($stop['kid'] !== null) {
                $kid = Kid::with('users')->findOrFail($stop['kid']['id']);
                $kid->status = 1;
                if(!$kid->update()) {
                    throw new HttpException(500);
                }
                
                // Actualizamos log
                $routeLogKid = new RouteLogKid();
                $routeLogKid->route_log_id = $routeLogId;
                $routeLogKid->kid_id = $stop['kid']['id'];        
                $routeLogKid->status = 1;
                
                if(!$routeLogKid->save()) {
                    throw new HttpException(500);
                }
                
                $parents = $kid->users->pluck('id');
        //
                $this->sendNotificationKidToUserStartRoute($route->name, $route->driver->user->first_name, $kid, $parents);
            }
        }
        
        return response()->json($stops);
    }
    
    public function notGetInBus(Request $request, $id)
    {
        $kid = Kid::with('users')->findOrFail($id);

        $route_log_id = $request->input("route_log_id");

        $kidActiveRoute = KidActiveRoute::where('route_log_id',$route_log_id)->where('id_kid',$id)->first();
        $kidActiveRoute->estado_nino_ruta = 0;
        $kidActiveRoute->save();


        $parents = $kid->users->pluck('id');
        //
        $this->sendNotificationKidToUserNotGetInBus($kid, $parents);
        
        return response()->json(['status' => 'ok']);
    }



    public function verifyLastStatusRoute($id)
    {

        $verify = DB::select('SELECT public.route_log.id as idRouteLog, public.route_log.route_id, public.route_log.status_route, public.user.id as userId FROM public.route_log inner join public.route on public.route.id = public.route_log.route_id
        inner join public.driver on public.driver.id = public.route.driver_id 
        inner join public.user on public.user.id = public.driver.user_id
        where public.user.id = ? and public.route_log.status_route = 1
        order by public.route_log.created_at asc limit 1',[$id]);

        if (count($verify) > 0){
            $route = Route::with('routeStops.kid.school', 'routeStops.school')->findOrFail($verify[0]->route_id);
            //$route = Route::find($verify[0]->route_id);
            $route_log = RouteLog::where('id',$verify[0]->idroutelog)->first();
            $kidActiveRoute = KidActiveRoute::where('route_log_id',$verify[0]->idroutelog)->get();
            return response()->json(['verify' => $verify[0], 'route' => $route, 'route_log' => $route_log, 'kidActiveRoute' => $kidActiveRoute ,'rutaFinalizada' => false]);
        }
        else{
            return response()->json(['verify' => $verify, 'rutaFinalizada' => true ]);
        }
    }
    
} 
