<?php

namespace App\Http\Controllers\User;

use App\Helpers\ActionLogger;
use App\Helpers\Logger;
use App\Http\Controllers\Controller;
use App\Models\Cabelcategory;
use App\Models\Contract;
use App\Models\Loan;
use App\Models\LoanerType;
use App\Models\LoanType;
use App\Models\Note;
use App\Models\Permission;
use App\Models\Role;
use App\Models\User;
use Illuminate\Auth\Access\Response;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;

class UserController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     */
    public function index(Request $request)
    {
        Auth::user()->role->permissions->contains(Permission::firstWhere('name', '=', 'users_viewAny'))
            ? Response::allow()
            : Response::deny('you are not the chosen one');

        $search_types = [];
        array_push($search_types,array("value" => "username", "name" => "username"));
        array_push($search_types,array("value" => "name", "name" => "name_full"));
        array_push($search_types,array("value" => "role", "name" => "role"));

        $PerPagination = $request->input('p') ?? 10;
        $search_term =  $request->input('search_term');
        $search_type = $request->input('search_type');
        $search_compare = $request->input('search_compare');

        if($search_term != ""){
            switch ($search_type){
                case "username":
                    switch($search_compare){
                        case('='):
                            $users = User::where(function ($query) use ($search_term){
                                $query->where('username','=',$search_term);
                            })->paginate($PerPagination);
                        break;
                        default:
                            $users = User::where(function ($query) use ($search_term){
                                $query->where('username','like','%' . $search_term . '%');
                            })->paginate($PerPagination);
                        break;
                    }

                break;
                case "name":
                    switch($search_compare){
                        case('='):
                            $users = User::where(function ($query) use ($search_term){
                                $query->where('name','=',$search_term);
                            })->paginate($PerPagination);
                        break;
                        default:
                            $users = User::where(function ($query) use ($search_term){
                                $query->where('name','like','%' . $search_term . '%');
                            })->paginate($PerPagination);
                        break;
                    }
                break;
                case "role":
                    switch($search_compare){
                        case('='):
                            $users = User::where(function ($query) use ($search_term){
                                $query->whereHas('role',function ($query) use ($search_term){
                                    $query->where('name','=',$search_term);
                                });
                            })->paginate($PerPagination);
                            break;
                        default:
                            $users = User::where(function ($query) use ($search_term){
                                $query->whereHas('role',function ($query) use ($search_term){
                                    $query->where('name','like','%' . $search_term . '%');
                                });
                            })->paginate($PerPagination);
                        break;
                    }
                break;
            }
        }
        else{
            $users = User::paginate($PerPagination);
        }

        return view('users.index')
            ->with('search_types',$search_types)
            ->with('data',$users)
            ->with('data_name','user')
            ->with('data_names','users')
        ;
    }

    /**
     * Display a listing of the resource.
     *
     */
    public function deleted(Request $request)
    {
        Auth::user()->role->permissions->contains(Permission::firstWhere('name', '=', 'users_viewAny_deleted'))
            ? Response::allow()
            : Response::deny('you are not the chosen one');

        $search_types = [];
        array_push($search_types,array("value" => "username", "name" => "username"));
        array_push($search_types,array("value" => "name", "name" => "name"));
        array_push($search_types,array("value" => "role", "name" => "role"));

        $PerPagination = $request->input('p');
        $search_term =  $request->input('search_term');
        $search_type = $request->input('search_type');
        $search_compare = $request->input('search_compare');

        if($search_term != ""){
            switch ($search_type){
                case "username":
                    switch($search_compare){
                        case('='):
                            $users = User::onlyTrashed()->where(function ($query) use ($search_term){
                                $query->where('username','=',$search_term);
                            })->paginate($PerPagination);
                        break;
                        default:
                            $users = User::onlyTrashed()->where(function ($query) use ($search_term){
                                $query->where('username','like','%' . $search_term . '%');
                            })->paginate($PerPagination);
                        break;
                    }

                    break;
                case "name":
                    switch($search_compare){
                        case('='):
                            $users = User::onlyTrashed()->where(function ($query) use ($search_term){
                                $query->where('name','=',$search_term);
                            })->paginate($PerPagination);
                        break;
                        default:
                            $users = User::onlyTrashed()->where(function ($query) use ($search_term){
                                $query->where('name','like','%' . $search_term . '%');
                            })->paginate($PerPagination);
                        break;
                    }
                break;
                case "role":
                    switch($search_compare){
                        case('='):
                            $users = User::onlyTrashed()->where(function ($query) use ($search_term){
                                $query->whereHas('role',function ($query) use ($search_term){
                                    $query->where('name','=',$search_term);
                                });
                            })->paginate($PerPagination);
                        break;
                        default:
                            $users = User::onlyTrashed()->where(function ($query) use ($search_term){
                                $query->whereHas('role',function ($query) use ($search_term){
                                    $query->where('name','like','%' . $search_term . '%');
                                });
                            })->paginate($PerPagination);
                        break;
                    }
                break;
                default:
                    $users = User::onlyTrashed()->where(function ($query) use ($search_term){
                        $query->where('username', 'like', '%'.$search_term.'%')
                            ->orWhere('name', 'like', '%'.$search_term.'%')
                            ->orWhereHas('role', function ($query) use ($search_term){
                                $query->where('name', 'like', '%'.$search_term.'%');
                            });
                    })->paginate($PerPagination);
                break;
            }
        }
        else{
            $users = User::onlyTrashed()->paginate($PerPagination);
        }

        return view('users.deleted')
            ->with('search_types',$search_types)
            ->with('data',$users)
            ->with('data_name','user')
            ->with('data_names','users')
        ;
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
     */
    public function create()
    {
        Auth::user()->role->permissions->contains(Permission::firstWhere('name', '=', 'user_ceate'))
            ? Response::allow()
            : Response::deny('you are not the chosen one');

        $exclude = array();
        if(Auth::user()->role->name != "Administrator"){
            array_push($exclude,Role::firstWhere("name", "=", "Administrator")->id);
        }

        return view('users.create')
            ->with('loanerTypes', LoanerType::all())
            ->with('roles', Role::all()->except($exclude))
            ->with('password_input_repeat','true')
        ;
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\RedirectResponse
     */
    public function store(Request $request)
    {
        Auth::user()->role->permissions->contains(Permission::firstWhere('name', '=', 'users_create'))
            ? Response::allow()
            : Response::deny('you are not the chosen one');

        $nadUser = LoanerType::where('name','=','nadUser')->first();
        $user = new User();
        $user->name = $request->name;
        $user->username = $request->username;
        $user->password = Hash::make($request->password);
        $user->loaner_type_id  = $nadUser->id;
        $user->role_id = $request->role_id;
        $user->save();
        Logger::LogCreated($user->id,get_class($user));

        return redirect()->route('users.index');
    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Models\User  $user
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
     */
    public function show($user)
    {
        $object = User::withTrashed()->where('id','=',$user)->first();

        if(Auth::user()->id != $object->id){
            Auth::user()->role->permissions->contains(Permission::firstWhere('name', '=', 'users_view'))
                ? Response::allow()
                : Response::deny('you are not the chosen one');
        }

        $loans = Loan::where('loan_type_id','=',LoanType::where('name','=','Loan')->first()->id)
            ->where('user_id','=',$object->id)
            ->select('*',DB::raw('count(loanable_id) as amount'))
            ->groupBy('loanable_type','loanable_id','date_start','date_end')
            ->orderBy('date_end')
            ->orderBy('date_start')
            ->orderBy('loanable_type')
            ->orderBy('loanable_id')
            ->get()
        ;

        $reservations = Loan::where('loan_type_id','!=',LoanType::where('name','=','Loan')->first()->id)
            ->where('user_id','=',$object->id)
            ->select('*',DB::raw('count(loanable_id) as amount'))
            ->groupBy('loanable_type','loanable_id','loan_type_id','room_id')
            ->orderBy('loan_type_id')
            ->orderBy('room_id')
            ->orderBy('date_start')
            ->orderBy('date_end')
            ->orderBy('loanable_type')
            ->orderBy('loanable_id')
            ->get()
        ;

        $notes = Note::where('user_id','=',$object->id)
            ->get()
        ;

        $contracts = Contract::where('user_id','=',$object->id)
            ->orderBy('type')
            ->orderBy('timestamp','desc')
            ->get()
        ;

        return view('users.show')
            ->with('data',$object)
            ->with('loans',$loans)
            ->with('reservations',$reservations)
            ->with('contracts',$contracts)
            ->with('notes',$notes)
        ;
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
     */
    public function edit($user)
    {
        $object = User::withTrashed()->where('id','=',$user)->first();

        if(Auth::user()->id != $object->id){
            Auth::user()->role->permissions->contains(Permission::firstWhere('name', '=', 'users_edit'))
                ? Response::allow()
                : Response::deny('you are not the chosen one');
        }

        $exclude = array();
        if(Auth::user()->role->name != "Administrator"){
            array_push($exclude,Role::where("name","=","Administrator")->first()->id);
        }

        return view('users.edit')
            ->with('data', $object)
            ->with('loanerTypes', LoanerType::all())
            ->with('users', User::all())
            ->with('roles', Role::all()->except($exclude))
            ->with('password_input_repeat','true')
            ->with('data_name', 'user')
            ->with('data_names', 'users')
        ;
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\RedirectResponse
     */
    public function update(Request $request, $user)
    {
        $object = User::withTrashed()->where('id','=',$user)->first();

        if(Auth::user()->id != $object->id){
            Auth::user()->role->permissions->contains(Permission::firstWhere('name', '=', 'users_edit'))
                ? Response::allow()
                : Response::deny('you are not the chosen one');
        }

        return redirect()->route('roles.index');
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Models\User  $user
     * @return \Illuminate\Http\RedirectResponse
     */
    public function destroy($user)
    {
        Auth::user()->role->permissions->contains(Permission::firstWhere('name', '=', 'user_delete'))
            ? Response::allow()
            : Response::deny('you are not the chosen one');

        $object = User::withTrashed()->where('id','=',$user)->first();
        Logger::LogDeleted($object->id,get_class($object));
        $object->delete();
        return redirect()->route('users.index');
    }

    /**
     * Permanently Remove the specified resource from storage.
     *
     * @param  \App\Models\User  $user
     * @return \Illuminate\Http\RedirectResponse
     */
    public function delete_force($user)
    {
        Auth::user()->role->permissions->contains(Permission::firstWhere('name', '=', 'user_delete_force'))
            ? Response::allow()
            : Response::deny('you are not the chosen one');

        $object = User::withTrashed()->where('id','=',$user)->first();

        $laptop_files = Storage::files('laptops');
        foreach($laptop_files as $file){
            $no_dir = str_replace("laptops/", "",$file);
            $parts = explode('_',$no_dir);
            $file_name = 'app\\'.$file;
            $file_full = storage_path($file_name);
            if($parts[0] == $object->username){
                unlink($file_full);
            }
        }

        $reservation_files = Storage::files('reservation');
        foreach($reservation_files as $file){
            $no_dir = str_replace("reservation/", "",$file);
            $parts = explode('_',$no_dir);
            $file_name = 'app\\'.$file;
            $file_full = storage_path($file_name);
            if($parts[0] == $object->username){
                unlink($file_full);
            }
        }

        $contract_files = Storage::files('contracts');
        foreach($contract_files as $file){
            $no_dir = str_replace("contracts/", "",$file);
            $parts = explode('_',$no_dir);
            $file_name = 'app\\'.$file;
            $file_full = storage_path($file_name);
            if($parts[0] == $object->username){
                unlink($file_full);
            }
        }

        Logger::LogForceDeleted($object->id,get_class($object));
        $object->forceDelete();
        return redirect()->route('users.index');
    }

    /**
     * Restore the specified resource from storage.
     *
     * @param  \App\Models\User  $user
     * @return \Illuminate\Http\RedirectResponse
     */
    public function restore($user)
    {
        Auth::user()->role->permissions->contains(Permission::firstWhere('name', '=', 'user_restore'))
            ? Response::allow()
            : Response::deny('you are not the chosen one');

        $object = User::withTrashed()->where('id','=',$user)->first();
        $object->restore();
        Logger::LogRestored($object->id,get_class($object));

        return redirect()->route('users.index');
    }
}