<?php

namespace Ignite\Core\Http\Controllers\Admin;

use Ignite\Core\Entities\User;
use Ignite\Core\Http\Controllers\Controller;
use Ignite\Core\Traits\StopImpersonating;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;

class SessionController extends Controller
{
    use AuthenticatesUsers;
    use StopImpersonating;

    /**
     * Where to redirect users after login.
     *
     * @var string
     */
    protected $redirectTo = '/admin';

    /**
     * Display the login form to create the session.
     *
     * @return \Illuminate\View\View
     */
    public function create()
    {
        return view('Core::admin.session.create');
    }

    /**
     * Store the session and handle the request.
     *
     * @param Request $request
     *
     * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse|\Illuminate\Http\Response
     * @throws ValidationException
     */
    public function store(Request $request)
    {
        return $this->login($request);
    }

    /**
     * Destroy the session.
     *
     * @param Request $request
     *
     * @return \Illuminate\Http\Response
     * @throws \Exception
     */
    public function destroy(Request $request)
    {
        return $this->logout($request);
    }

    /**
     * The user has logged out of the application.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return mixed
     */
    protected function loggedOut(Request $request)
    {
        return redirect('/admin/login')->with('status', 'You are now signed out.');
    }

    /**
     * Attempt to log the user into the application if the user is active.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return bool
     */
    protected function attemptLogin(Request $request)
    {
        $credentials = $this->credentials($request);

        $useEmail = config('core.use_email_as_username');
        if ($useEmail) {
            $credentials['email'] = $credentials['username'];
            unset($credentials['username']);
        }

        return $this->guard()->attempt(
            array_merge([
                'status' => User::STAT_ACTIVE,
                'internal' => User::TYPE_INTERNAL
            ], $credentials),
            $request->has('remember')
        );
    }

    /**
     * Overrides the default get login username to be used by the controller.
     *
     * @return string
     */
    public function username()
    {
        return 'username';
    }

    /**
     * Get the failed login response instance.
     *
     * @param  \Illuminate\Http\Request  $request
     * @throws \Illuminate\Validation\ValidationException
     */
    protected function sendFailedLoginResponse(Request $request)
    {
        /** @var User $user */
        $user = User::where('email', $request->only($this->username()))->first();

        if ($user && $user->isInactive()) {
            throw ValidationException::withMessages(['status' => 'Your account is inactive.']);
        }

        if ($user && $user->isPending()) {
            throw ValidationException::withMessages([
                'status' => 'Your account is pending. Please set your password. '
                            . 'If you have not received an email with instructions on setting your password. '
                            . 'Please reset your password.'
            ]);
        }

        if ($user && $user->type !== User::TYPE_INTERNAL) {
            throw ValidationException::withMessages(['status' => 'Your account is not configured to access the admin panel.']);
        }

        if ($user && $user->cannot('core.dashboard.browse')) {
            throw ValidationException::withMessages(['status' => 'Your account is not configured to access the admin panel.']);
        }

        throw ValidationException::withMessages([
            $this->username() => [trans('auth.failed')],
        ]);
    }

    /**
     * Log the user out of the application.
     *
     * @param \Illuminate\Http\Request $request
     *
     * @return RedirectResponse|\Illuminate\Http\Response
     */
    public function logout(Request $request)
    {
        $impersonating = $this->stopImpersonating();
        if ($impersonating instanceof RedirectResponse) {
            return $impersonating;
        }

        $this->guard()->logout();

        $request->session()->invalidate();

        $request->session()->regenerateToken();

        return $this->loggedOut($request) ?: redirect('/');
    }
}
