<?php

namespace App\Http\Controllers;

use App\Http\Requests\ApproveInviteRequest;
use App\Http\Requests\DenyInviteRequest;
use App\Http\Requests\InvitationRequest;
use App\Http\Requests\ValidateInviteRequest;
use App\Invitation;
use App\Mail\InviteApprovedMail;
use App\Mail\InvitedToApp;
use App\Mail\InviteRequestReceived;
use App\Response;
use Auth;
use Illuminate\Http\Request;
use Mail;
use Session;

class InvitationController extends Controller
{
    public function index()
    {
        $this->authorize('viewAny', Invitation::class);

        return view('dashboard.administration.invites', [
            'invites' => Invitation::all()
        ]);
    }

    public function requestInvite(InvitationRequest $request)
    {

        $this->authorize('create', Invitation::class);

        $guest = Auth::guest();
        $invitation = new Invitation();

        $invitation->requestor_email = $request->input('email');
        $invitation->requestor_ip_address = $request->ip();
        $invitation->status = $guest ? 'pending' : 'approved';
        $invitation->notified = !$guest; // confirmation msg doesn't count
        $invitation->invitation_code = bin2hex(random_bytes(64));
        $invitation->expiration = now()->addDays(2);

        try {
            $invitation->saveOrFail();
            $addlMessage = ($guest) ? __('Check your email address for a confirmation email.') : '';

            $request->session()->flash('success', __('Invitation request sent. :additionalUnauthenticatedMessage', ['additionalUnauthenticatedMessage' => $addlMessage]));

            if ($guest) {
                Mail::to($invitation->requestor_email)->send(new InviteRequestReceived());
            }
            else {
                // this is an approved invite
                Mail::to($invitation->requestor_email)->send(new InvitedToApp($invitation));
            }


        } catch (\Exception $exception) {

            \Log::debug('[INVITES]: Error saving invite request', ['message' => $exception->getMessage(), 'requestor_ip' => $request->ip()]);
            $request->session()->flash('error', __('Sorry, but we were unable to request an invitation for you. If you already requested one, trying to request another will not be possible, nor will it speed up the process.'));

        }

        return redirect()->back();
    }

    public function approveInvite(ApproveInviteRequest $request, Invitation $invitation)
    {
        $this->authorize('update', $invitation);

        $approvableStates = [
            'pending'
        ];

        if ($invitation->expiration && now()->lessThanOrEqualTo($invitation->expiration) && in_array($invitation->status, $approvableStates))
        {
            $invitation->status = 'approved';
            $invitation->notified = true;
            $invitation->save();

            Mail::to($invitation->requestor_email)->send(new InviteApprovedMail($invitation));

            return redirect()
                ->back()
                ->with('success', __('Invite request approved! This user can now sign up.'));

        }
        else
        {
            return redirect()
                ->back()
                ->with('error', __('This invitation couldn\'t be approved because either it\'s already approved or it is expired.'));

        }
    }

    public function denyInvite(DenyInviteRequest $request, Invitation $invitation)
    {
        $this->authorize('update', $invitation);

        $declinableStates = [
          'pending'
        ];

        if ($invitation->expiration && now()->lessThanOrEqualTo($invitation->expiration) && in_array($invitation->status, $declinableStates))
        {
            $invitation->status = 'denied';
            $invitation->save();

            return redirect()
                ->back()
                ->with('success', __('Invitation denied. No notifications were sent. This user cannot be invited again.'));

        }

        return redirect()
            ->back()
            ->with('error', __('This invitation could not be denied because it is either already approved, expired, or in an otherwise invalid state.'));
    }

    public function redeemInvite(Request $request)
    {
        return view('auth.redeem-invite', ['validationToken' => $request->route('token')]);
    }

    public function validateInvite(ValidateInviteRequest $request)
    {
        $token = $request->input('validation_token');
        $email = $request->input('email');

        $invite = Invitation::where('requestor_email', $email)->first();



        if (!empty($invite) && $token === $invite->invitation_code && 'approved' === $invite->status && $invite->expiration && now()->lessThanOrEqualTo($invite->expiration))
        {
            $invite->status = 'completed';
            $invite->save();

            Session::put('ALLOW_REGISTRATION_OVERRIDE', true);
            Session::put('REGISTRATION_OVERRIDE_EMAIL', $email);

            return redirect()
                ->route('register')
                ->with('success', __('Invitation code validated! You can now sign up with the email address you were invited with.'));
        }
        else
        {
            return redirect()
                ->back()
                ->with('error', __('Something went wrong while validating your invite. Either it does not exist, is expired, has not been approved yet, or the token is wrong (do not edit it).'));
        }

    }

}

