<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Utils\UtilController;
use App\Models\Artist;
use App\Models\Manager;
use App\Models\ManagerInvite;
use App\Models\User;
use App\Notifications\ManagerArtistInviteNotification;
use App\Notifications\ManagerRegisterArtistInviteNotification;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Exception;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;

class InviteManagerController extends Controller
{
    //
    public function __construct()
    {
        $this->middleware(['auth', 'verified', 'onboarding']);
        $this->middleware(['role:artist'])->only('storeInvitation');
        $this->middleware(['role:manager'])->only('accept');
    }

    public function storeInvitation(Request $request): RedirectResponse
    {
        $validator = Validator::make($request->all(), [
            'email' => ['required', 'email', 'max:255'],
        ]);

        if ($validator->fails()) {
            return redirect()->back()
                ->with('error', $validator->messages()->all());
        }

        if (Artist::where('user_id', Auth::id())
            ->whereNotNull('manager_id')
            ->exists()) {
            return redirect()->back()
                ->with('error', 'You already have a manager. Cannot invite more than one!');
        }

        $invitation = new ManagerInvite();
        $invitation->email = $request->email;

        $artist = Artist::find(Auth::id());
        $invitation->artist()->associate($artist);

        $token = UtilController::generateToken($request->email);
        $invitation->invitation_token = Hash::make($token);

        try {
            $invitation->save();
        } catch (Exception $e) {
            return redirect()->back()
                ->with('error', 'Issue while inviting the manager - ' . $e->getMessage());
        }

        if (User::where('email', $request->email)->exists()) {
            try {
                $invitation->notify(new ManagerArtistInviteNotification($token));
            } catch (Exception $e) {
                return redirect()->back()
                    ->with('error', $e->getMessage());
            }
        } else {
            try {
                $invitation->notify(new ManagerRegisterArtistInviteNotification($token));
            } catch (Exception $e) {
                return redirect()->back()
                    ->with('error', $e->getMessage());
            }
        }

        return redirect()->back()
            ->with('success', 'Manager invited successfully!');
    }

    /**
     * Accept the invitation token sent by the artist
     * @param $token - invitation token
     */
    public function accept(Request $request, $token)
    {
        if (!$request->hasValidSignature()) {
            abort(401);
        }

        $invitations = ManagerInvite::where([
            ['email', $request->email],
            ['artist_id', $request->artist_id],
        ])->get();

        foreach ($invitations as $invitation) {
            if (Hash::check($token, $invitation->invitation_token)) {
                $artist = Artist::where('user_id', $invitation->artist_id)->firstOrFail();
                $user_manager = User::where('email', $invitation->email)->firstOrFail();
                $manager = Manager::where('user_id', $user_manager->id)->firstOrFail();

                $artist->manager()->associate($manager);

                try {
                    $artist->save();
                } catch (Exception $e) {
                    return redirect()->back()
                        ->with('error', $e->getMessage());
                }

                $invitation->registered_at = Carbon::now();

                try {
                    $invitation->save();
                } catch (Exception $e) {
                    return redirect()->back()
                        ->with('error', $e->getMessage());
                }
            }
        }

        return redirect('/explore')
            ->with('success', 'You have been added as a manager of ' . $artist->user->name . ' 🥳');
    }
}
