<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;

use App\Models\User;
use App\Models\Chat;
use App\Models\Page;
use App\Http\Requests\UserValidation;
use App\Http\Requests\RequestPasswordResetValidation;
use App\Http\Requests\ResetPasswordValidation;
use App\Http\Requests\UserActivationCheckValidation;

use App\Events\UserBanned;

use App\Utilities\PageResponse;
use App\Utilities\SearchResult;

use App\Mail\EmailVerification;
use App\Mail\ResetPassword;

class UsersController extends Controller
{
    public function index()
    {
        if (!auth()->user()->can('viewAny', User::class)) {
            return redirect('/')->with(['error' => 'You do not have permission to view that page']);
        }

        return view('users.index');
    }

    public function current()
    {
        if (!auth()->user()) {
            abort(401);
        }

        return response()->json([
            'user' => auth()->user()->load('roles', 'staffProfile'),
        ]);
    }

    public function paginate()
    {
        if (!auth()->user()->can('viewAny', User::class)) {
            return response()->json([
                'error' => 'You do not have permission to load users'
            ], 403);
        }

        $users = User::with('roles');

        if (request('terms')) {
            $terms = SearchResult::collectTerms();

            if (count($terms) > 0) {
                $first = true;
                foreach ($terms as $term) {
                    
                    if ($first) {
                        $users->where('name', 'LIKE', '%'.$term.'%');
                        $first = false;
                    } else {
                        $users->orWhere('name', 'LIKE', '%'.$term.'%');
                    }

                    $users->orWhere('email', 'LIKE', '%'.$term.'%')
                          ->orWhereHas('roles', function($query) use($term) {
                            $query->where('name', 'LIKE', '%'.$term.'%');
                          });
                }
            }
        }

        return $users->paginate(request('paginate_count', 10), $columns = ['*'], $pageName = 'paginate_page');
    }

    public function store(UserValidation $request, $id = null)
    {
        if ($id) {
            if (!auth()->user()->can('update', User::find($id))) {
                return redirect()->route('home')->with(['error' => 'You do not have permission to udpate that user']);
            }
        }
        $user = (new User())->saveUser(requestInput(), $id);

        return response()->json([
            'success' => $user->name.' Saved',
            'user' => $user,
        ]);
    }

    public function search()
    {
        if (!auth()->user()->can('viewAny', User::class)) {
            return response()->json([ 'error' => 'You do not have permission to search for users' ], 403);
        }

        return (new User())->search();
    }

    public function ban($id)
    {
        $user = User::findOrFail($id);

        if (requestInput('room')) {
            if (!Chat::canModerateRoom(requestInput('room'))) {
                return response()->json([ 'error' => 'You do not have permission to ban for users' ], 403);
            }
        } else {
            if (!auth()->user()->can('ban', $user)) {
                return response()->json([ 'error' => 'You do not have permission to ban for users' ], 403);
            }
        }

        $user->banned_at = now();
        $user->save();

        Chat::where('user_id', $user->id)->delete();

        broadcast(new UserBanned($user));

        return response()->json([
            'success' => $user->name.' Banned',
        ]);
    }

    public function sendEmailVerification($id)
    {
        $user = User::findOrFail($id);

        if (!auth()->user()->can('update', $user)) {
            return response()->json(['error' => 'You do not have access to that user']);
        }

        if ($user->email_verified_at) {
            return response()->json(['error' => 'Your email has already been confirmed'], 422);
        }

        Mail::to($user->email)
                ->queue(new EmailVerification($user));

        return response()->json([
            'success' => 'Email Verification Sent',
        ]);
    }

    public function verifyEmail($id)
    {
        if (! request()->hasValidSignature()) {
            abort(401);
        }

        $user = User::findOrFail($id);

        if ($user->email_verified_at) {
            return (new PageResponse())->view(Page::getHomePage(), 'pages.view')->with(['error' => 'Your email has already been confirmed']);
        }

        $user->email_verified_at = now();
        $user->save();

        return (new PageResponse())->view(Page::getHomePage(), 'pages.view')->with(['success' => 'Email Verification Complete']);
    }

    public function requestPasswordReset(RequestPasswordResetValidation $request)
    {
        $user = User::where('email', requestInput('email'))->first();

        if (!$user) {
            return response()->json(['error' => 'There is no user with that email address'], 401);
        }

        if ($user->oauth_id) {
            return response()->json(['error' => 'Please reset your password via Google'], 422);
        }

        Mail::to($user->email)
                ->queue(new ResetPassword($user));

        return response()->json([
            'success' => 'Password Reset Email Sent',
        ]);
    }

    public function viewResetPassword($id)
    {
        if (! request()->hasValidSignature()) {
            abort(401);
        }

        $user = User::findOrFail($id);

        return view('auth.reset-password', compact('user'));
    }

    public function resetPassword(ResetPasswordValidation $request, $id)
    {
        $user = User::findOrFail($id);

        $user->password = Hash::make(requestInput('password'));
        if (!$user->activated_at) {
            $user->activated_at = now();
        }
        $user->save();
        auth()->login($user);
        auth()->user()->setSessionTimeout();

        return response()->json([
            'success' => 'Password Reset',
        ]);
    }

    public function activationCheck(UserActivationCheckValidation $requst)
    {
        $user = User::where('email', request('email'))->first();

        if (!$user) {
            $activated_at = false;
        } else {
            $activated_at = $user->activated_at ? true : false;
        }

        return response()->json([
            'activated_at' => $activated_at,
        ]);
    }

    public function register()
    {
        if (auth()->user() && !editing() && !request('editing')) {
            return redirect('/')->with(['error' => 'You cannot register when logged in']);
        }

        $page = (new Page())->findByFullSlug('register');
        return (new PageResponse())->view($page, 'pages.view');
    }

    public function editingToggle()
    {
        request()->validate([
            'enable' => 'required|boolean',
            'page_type' => 'required',
            'page_id' => 'required',
        ]);

        $page_class = 'App\Models\\'.Str::title(request('page_type'));
        $page = (new $page_class())->findOrFail(request('page_id'));

        $user = auth()->user();

        if (!$user->can('update', $page) && !$user->editing) {
            return response()->json(['error' => 'You cannot update this page'], 403);
        }

        if ((bool) request('enable')) {
            $user->enableEditing();
            return response()->json([
                'success' => 'Editing Enabled',
                'editing' => true,
            ]);
        } else {
            $user->disableEditing();
            return response()->json([
                'success' => 'Editing Disabled',
                'editing' => false,
            ]);
        }
    }

    public function darkToggle()
    {
        $user = auth()->user();
        $user->dark_mode = !$user->dark_mode;
        $user->save();

        return response()->json([
            'success' => 'Dark Mode '.($user->dark_mode ? 'Enabled' : 'Disabled'),
            'enabled' => $user->dark_mode,
        ]);
    }
}
