<?php

namespace App\Http\Controllers;

use App\Models\Direction;
use App\Models\PortefeuilleAcheteur;
use App\Models\PortefeuilleResponsableAchat;
use App\Models\Service;
use App\Models\Structure;
use App\Models\User;
use APPLICATION;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;

class UtilisateurController extends Controller
{
    public function __construct()
    {
        $this->middleware('permission:see_utilisateur')->only(['index']);
        $this->middleware('permission:add_utilisateur')->only(['create', 'store']);
        $this->middleware('permission:edit_utilisateur')->only(['edit', 'update', 'active']);
        $this->middleware('permission:delete_utilisateur')->only(['destroy']);
    }

    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Http\Response
     */
    public function index()
    {
        return view('utilisateurs.index', [
            'users' => User::where('structure_id', Auth::user()->structure_id)->paginate(APPLICATION::ITEMS_PER_PAGE)
        ]);
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Http\Response
     */
    public function create()
    {
        return view('utilisateurs.create', [
            'roles' => Structure::get_roles(Auth::user()->structure_id),
            'directions' => Direction::where('structure_id', Auth::user()->structure_id)->get(),
            'portefeuilles_responsables' => PortefeuilleResponsableAchat::where('structure_id', Auth::user()->structure_id)->get()
        ]);
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\RedirectResponse
     */
    public function store(Request $request)
    {
        $request->validate([
            'role' => 'required',
            'direction' => 'required_if:role,equipe_projet,directeur',
            'portefeuille_responsable' => 'required_if:role,responsable_achat',
            'portefeuille_acheteur' => 'required_if:role,equipe_projet,acheteur',
            'prenom' => 'required|string|max:45',
            'nom' => 'required|string|max:45',
            'email' => 'required|email|max:255|unique:users',
            'password' => 'required|between:8,16|confirmed',
        ]);

        // On récupère les objets pour faire des vérification d'intégrité
        $direction = Direction::find($request->direction);
        $service_value = explode('_', $request->service);
        $service = Service::find($service_value[array_key_last($service_value)]);
        $portefeuille_responsable = PortefeuilleResponsableAchat::find($request->portefeuille_responsable);
        $portefeuille_acheteur = PortefeuilleAcheteur::find($request->portefeuille_acheteur);
        $portefeuille_responsable_acheteur = isset($portefeuille_acheteur) ?
            PortefeuilleResponsableAchat::find($portefeuille_acheteur->portefeuille_responsable_achat_id)
            : null;

        // On vérifie que toutes données match entre elles et match avec la structure
        $this->checkIntegriteDonnees($direction, $service, $portefeuille_responsable, $portefeuille_acheteur, $portefeuille_responsable_acheteur);

        $user = User::firstOrCreate(array_merge(
            $request->only(['prenom', 'nom', 'email', 'structure_id']),
            [
                'password' => Hash::make($request->password),
                'structure_id' => Auth::user()->structure_id,
                'direction_id' => isset($direction) ? $direction->id : null,
                'service_id' => isset($service) ? $service->id : null,
                'portefeuille_responsable_achat_id' => isset($portefeuille_responsable) ? $portefeuille_responsable->id : null,
                'portefeuille_acheteur_id' => isset($portefeuille_acheteur) ? $portefeuille_acheteur->id : null,
                'active' => true
            ]
        ));
        $user->assignRole($request->role);
        $user->sendEmailVerificationNotification();
        return redirect()->route('utilisateurs.index')->with('success', 'Utilisateur ajouté avec succès.');
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Http\Response
     */
    public function edit($id)
    {
        $user = User::find($id);
        if (isset($user)) {
            if ($user->structure_id == Auth::user()->structure_id) {
                return view('utilisateurs.edit', [
                    'user' => $user,
                    'roles' => Structure::get_roles(Auth::user()->structure_id),
                    'directions' => Direction::where('structure_id', Auth::user()->structure_id)->get(),
                    'portefeuilles_responsables' => PortefeuilleResponsableAchat::where('structure_id', Auth::user()->structure_id)->get()
                ]);
            } else {
                abort(403);
            }
        } else {
            abort(404);
        }
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\RedirectResponse
     */
    public function update(Request $request, $id)
    {
        $request->validate([
            'role' => 'required',
            'direction' => 'required_if:role,equipe_projet,directeur',
            'portefeuille_responsable' => 'required_if:role,responsable_achat',
            'portefeuille_acheteur' => 'required_if:role,equipe_projet,acheteur',
            'prenom' => 'required|string|max:45',
            'nom' => 'required|string|max:45',
            'email' => 'required|email|max:255|unique:users,email,' . $id
        ]);

        $user = User::find($id);
        if (isset($user)) {
            if ($user->structure_id == Auth::user()->structure_id) {
                // On récupère les objets pour faire des vérification d'intégrité
                $direction = Direction::find($request->direction);
                $service_value = explode('_', $request->service);
                $service = Service::find($service_value[array_key_last($service_value)]);
                $portefeuille_responsable = PortefeuilleResponsableAchat::find($request->portefeuille_responsable);
                $portefeuille_acheteur = PortefeuilleAcheteur::find($request->portefeuille_acheteur);
                $portefeuille_responsable_acheteur = isset($portefeuille_acheteur) ?
                    PortefeuilleResponsableAchat::find($portefeuille_acheteur->portefeuille_responsable_achat_id)
                    : null;

                // On vérifie que toutes données match entre elles et match avec la structure
                $this->checkIntegriteDonnees($direction, $service, $portefeuille_responsable, $portefeuille_acheteur, $portefeuille_responsable_acheteur);

                $user->update(array_merge(
                    $request->only(['prenom', 'nom', 'email']),
                    [
                        'direction_id' => isset($direction) ? $direction->id : null,
                        'service_id' => isset($service) ? $service->id : null,
                        'portefeuille_responsable_achat_id' => isset($portefeuille_responsable) ? $portefeuille_responsable->id : null,
                        'portefeuille_acheteur_id' => isset($portefeuille_acheteur) ? $portefeuille_acheteur->id : null
                    ]
                ));

                // On assigne le role si ce n'est pas l'utilisateur connecté
                if ($user->id != Auth::user()->getAuthIdentifier()) {
                    $user->syncRoles($request->role);
                }

                return redirect()->route('utilisateurs.index')->with('success', 'Utilisateur mis à jour avec succès.');
            } else {
                abort(403);
            }
        } else {
            abort(404);
        }
    }

    /**
     * Permet de desactiver ou activer le compte d'un utilisateur
     *
     * @param $id
     * @return \Illuminate\Http\RedirectResponse
     */
    public function active($id)
    {
        $user = User::find($id);
        if (isset($user)) {
            if ($user->structure_id == Auth::user()->structure_id && $user->id != Auth::user()->getAuthIdentifier()) {
                $user->update(['active' => !$user->active]);
                return $user->active ?
                    redirect()->route('utilisateurs.index')->with('success', 'Utilisateur activé avec succès.')
                    : redirect()->route('utilisateurs.index')->with('success', 'Utilisateur désactivé avec succès.');
            } else {
                abort(403);
            }
        } else {
            abort(404);
        }
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\RedirectResponse
     */
    public function destroy($id)
    {
        $user = User::find($id);
        if (isset($user)) {
            if ($user->id != Auth::user()->getAuthIdentifier()) {
                if ($user->projets->count() > 0 || $user->membres_projets->count() > 0 || $user->status_projets->count() > 0) {
                    return redirect()->back()->withErrors('Impossible de supprimer l\'utilisateur car il possède ou fait partie d\'un projet ou s\'il a émis des avis sur certains projets.');
                }
                $user->delete();
                return redirect()->route('utilisateurs.index')->with('success', 'Utilisateur supprimé avec succès.');
            } else {
                abort(403);
            }
        } else {
            abort(404);
        }
    }

    private function checkIntegriteDonnees($direction, $service, $portefeuille_responsable, $portefeuille_acheteur, $portefeuille_responsable_acheteur)
    {
        if (isset($direction) && isset($service)
            && $direction->structure_id != Auth::user()->structure_id
            && $service->direction_id != $direction->id) {
            abort(403);
        }

        if (isset($portefeuille_responsable) && $portefeuille_responsable->structure_id != Auth::user()->structure_id) {
            abort(403);
        }

        if (isset($portefeuille_acheteur) && isset($portefeuille_responsable_acheteur)
            && $portefeuille_responsable_acheteur->structure_id != Auth::user()->structure_id
            && $portefeuille_acheteur->portefeuille_responsable_achat_id != $portefeuille_responsable_acheteur->id) {
            abort(403);
        }
    }
}
