<?php

namespace App\Http\Controllers;

use App\Exports\RespArsPaatsExport;
use App\Models\Categorie;
use App\Models\CommentairesRapportActivite;
use App\Models\Consolidation;
use App\Models\Domaine;
use App\Models\Famille;
use App\Models\Projet;
use App\Models\Segment;
use App\Models\Structure;
use App\Models\User;
use App\Models\Paat;
use App\Tables\ProjetsTable;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Session;
use Maatwebsite\Excel\Facades\Excel;
use ROLE;
use PAAT_STATUT;
use TEXT;

class HomeController extends Controller
{
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth');
        $this->middleware('role_or_permission:see_performance_economique|see_achats_mutualises|see_rse|see_gestion_paat|' . ROLE::RESPONSABLE_PERFORMANCE_ARS . '|' . ROLE::ACHETEUR . '|' . ROLE::CONTROLEUR_GESTION)->only('filtres');
    }

    /**
     * Show the application home.
     *
     * @return \Illuminate\Contracts\Support\Renderable
     */
    public function index($refresh_table = false)
    {
        // Liste des paats
        $paats = Paat::getAllPaatsByStructureId(Auth::user()->structure_id);
        // On récupère l'id du paat que l'on souhaite afficher -> par defaut on prends le paat courant
        $paat_id = Session::get('paat_id') != null ? Session::get('paat_id')
            : Paat::where('structure_id', Auth::user()->structure_id)->where('statut', PAAT_STATUT::EN_COURS)->first()->id ?? array_key_first($paats) ?? null;

        // On initialise la date au premier janvier de l'année courante
        $dateDebutInit = Carbon::createFromFormat('d/m/Y', '01/01/'.date("Y"));

        $date_debut = Session::get('date_debut') != null ? Carbon::createFromFormat('d/m/Y', Session::get('date_debut')) : $dateDebutInit;
        $date_fin = Session::get('date_fin') != null ? Carbon::createFromFormat('d/m/Y', Session::get('date_fin')) : Carbon::today();
        $between_debut = clone $date_debut;
        $betweenDates = array($between_debut->subDays(1), $date_fin);

        $familles = Famille::select('id', 'nom')->where('structure_id', Auth::user()->structure_id)->get();
        $famille_id = Session::get('famille_id') ?? null;
        $domaines = Domaine::select('domaines.id', 'domaines.nom', 'domaines.famille_id')
            ->join('familles', 'familles.id', 'domaines.famille_id')
            ->where('familles.structure_id', Auth::user()->structure_id)->get();
        $domaine_id = Session::get('domaine_id') ?? null;
        $categories = Categorie::select('categories.id', 'categories.nom', 'categories.domaine_id')
            ->join('domaines', 'domaines.id', 'categories.domaine_id')
            ->join('familles', 'familles.id', 'domaines.famille_id')
            ->where('familles.structure_id', Auth::user()->structure_id)->get();
        $categorie_id = Session::get('categorie_id') ?? null;
        $segments = Segment::select('segments.id', 'segments.nom', 'segments.categorie_id')
            ->join('categories', 'categories.id', 'segments.categorie_id')
            ->join('domaines', 'domaines.id', 'categories.domaine_id')
            ->join('familles', 'familles.id', 'domaines.famille_id')
            ->where('familles.structure_id', Auth::user()->structure_id)->get();
        $segment_id = Session::get('segment_id') ?? null;

        if (Auth::user()->hasAnyRole([ROLE::DIRECTEUR, ROLE::CHEF_PROJET, ROLE::CONTROLEUR_GESTION, ROLE::RESPONSABLE_ACHAT])) {
            $utilisateurs = User::select('users.*')
                ->where('structure_id', Auth::user()->structure_id);
            if (Auth::user()->hasRole(ROLE::RESPONSABLE_ACHAT)) {
                $utilisateurs->join('portefeuilles_acheteurs', 'portefeuilles_acheteurs.id', '=', 'users.portefeuille_acheteur_id')
                    ->where('portefeuilles_acheteurs.portefeuille_responsable_achat_id', Auth::user()->portefeuille_responsable_achat_id);
            }
            $utilisateurs = $utilisateurs->get();
        }
        $utilisateur_id = Session::get('utilisateur_id') ?? null;

        // Application des filtres
        switch (Auth::user()->nom_role()) {
            case ROLE::DIRECTEUR:
                // On récupère les ids des projets de l'établissement du directeur en tant que membre projet
                $projets_membre_id = Projet::leftJoin('membres_projets', 'membres_projets.projet_id', '=', 'projets.id')
                    ->where('membres_projets.user_id', Auth::user()->getAuthIdentifier())->pluck('projets.id')->toArray();

                // On récupère les projet de l'etablissement ou ceux dont il fait partie
                $projets = Projet::where(function ($query) use ($projets_membre_id) {
                    $query->where('projets.direction_id', Auth::user()->direction_id)
                    ->where('projets.owner_id', Auth::user()->getAuthIdentifier())
                    ->orWhereIn('projets.id', array_values($projets_membre_id));
                })->whereBetween('projets.date_debut', $betweenDates);
                break;
            case ROLE::RESPONSABLE_ACHAT :
                // Si l'utilisateur est un responsable achat, on affiche les projets de ses acheteurs ou ceux dont il fait partie.
                $projets_membre_id = Projet::leftJoin('membres_projets', 'membres_projets.projet_id', '=', 'projets.id')
                    ->leftJoin('users', 'users.id', '=', 'projets.owner_id')
                    ->leftJoin('portefeuilles_acheteurs', 'portefeuilles_acheteurs.id', '=', 'users.portefeuille_acheteur_id')
                    ->leftJoin('portefeuilles_responsables_achats', 'portefeuilles_responsables_achats.id', '=', 'portefeuilles_acheteurs.portefeuille_responsable_achat_id')
                    ->where('portefeuilles_responsables_achats.id', Auth::user()->portefeuille_responsable_achat_id)
                    ->orWhere('membres_projets.user_id', Auth::user()->getAuthIdentifier())
                    ->pluck('projets.id')->toArray();

                // On récupère les projets
                $projets = Projet::where(function ($query) use ($projets_membre_id) {
                    $query->where('projets.owner_id', Auth::user()->getAuthIdentifier())
                    ->orWhereIn('projets.id', array_values($projets_membre_id));
                })->whereBetween('projets.date_debut', $betweenDates);
                break;
            case ROLE::ACHETEUR:
                // On récupère les ids des projets dont fait partie l'acheteur en tant que membre projet
                $projets_membre_id = Projet::leftJoin('membres_projets', 'membres_projets.projet_id', '=', 'projets.id')
                    ->where('membres_projets.user_id', Auth::user()->getAuthIdentifier())->pluck('projets.id')->toArray();

                // On récupère les projets de l'acheteur ou ceux dont il fait partie
                $projets = Projet::where(function ($query) use ($projets_membre_id) {
                    $query->where('projets.owner_id', Auth::user()->getAuthIdentifier())
                    ->orWhereIn('projets.id', array_values($projets_membre_id));
                })->whereBetween('projets.date_debut', $betweenDates);
                break;
            case ROLE::EQUIPE_PROJET:
                // Si l'utilisateur a pour role equipe projet, on affiche les projets dont il fait partie
                $projets = Projet::join('membres_projets', 'membres_projets.projet_id', '=', 'projets.id')
                    ->where('membres_projets.user_id', Auth::user()->getAuthIdentifier())
                    ->whereBetween('projets.date_debut', $betweenDates);
                break;
            default:
                $projets = Projet::whereBetween('projets.date_debut', $betweenDates);
                break;
        }

        if ($famille_id != null) {
            $projets->where('projets.famille_id', $famille_id);
        }
        if ($domaine_id != null) {
            $projets->where('projets.domaine_id', $domaine_id);
        }
        if ($categorie_id != null) {
            $projets->where('projets.categorie_id', $categorie_id);
        }
        if ($segment_id != null) {
            $projets->where('projets.segment_id', $segment_id);
        }
        if ($utilisateur_id != null) {
            $projets->where('projets.owner_id', $utilisateur_id);
        }
        if ($paat_id != null && !Auth::user()->hasRole(ROLE::RESPONSABLE_PERFORMANCE_ARS)) {
            $projets->where('projets.paat_id', $paat_id);
        }

        if (Auth::user()->hasRole(ROLE::RESPONSABLE_PERFORMANCE_ARS)) {
            // On récupère la structure du responsable performance ars
            $structure = Structure::find(Auth::user()->structure_id);
            // Si la structure est ratachée à une consolidation, on récupère tous les projets de toutes les structures
            // Sinon on prend les projets de la structure courante
            $structure->consolidation_id != null ?
                $projets->join('structures', 'structures.id', '=', 'projets.structure_id')
                    ->where('structures.consolidation_id', $structure->consolidation_id)
                : $projets->join('structures', 'structures.id', '=', 'projets.structure_id')
                ->where('structures.id', Auth::user()->structure_id);

            // Récupération des données pour les indicateurs du responsable performance ARS
            $indicateurs = [
                'consolidation' => Consolidation::find($structure->consolidation_id),
                'projets_structures' => $this->get_projets_structures(clone $projets),
                'referentiel' => $this->get_projets_referentiel_ars(clone $projets),
                'referentiel_oui_non' => $this->get_projets_referentiel_oui_non(clone $projets),
                'champ_referentiel' => Structure::find(Auth::user()->structure_id)->champ_referentiel,
                'data_map_consolidations' => $this->get_consolidation(clone $projets)
            ];

            // Récupération des structures et PAAT pour les filtres de l'export Excel
            $liste_paat_annees = Paat::join('structures', 'structures.id', '=', 'paats.structure_id')
                ->where('consolidation_id', '=', Auth::user()->structure->consolidation_id)->get();
            $liste_structures = Structure::where('nom', '!=', TEXT::SUPER_ADMINISTRATION)
                ->where('consolidation_id', '=', Auth::user()->structure->consolidation_id)
                ->get();
        } else {
            // On récupère les données sur les projets de la structure de l'utilisateur
            $projets->where('projets.structure_id', Auth::user()->structure_id);

            // Récupération des données pour les indicateurs du GHT en fonction des permissions de l'utilisateur
            $indicateurs = [];
            if (Auth::user()->can('see_performance_economique') || Auth::user()->hasAnyRole([ROLE::ACHETEUR, ROLE::CONTROLEUR_GESTION])) {
                $indicateurs['montants'] = $this->get_montant_mois(clone $projets);
                $indicateurs['projets_cibles'] = $this->get_projets_cibles(clone $projets);
                $indicateurs['projets_notifies'] = $this->get_projets_notifies(clone $projets);
                $indicateurs['gains_cible'] = $this->get_projets_acheteur_gains_cible(clone $projets);
                $indicateurs['gains_notifie'] = $this->get_projets_acheteur_gains_notifie(clone $projets);
            }
            if (Auth::user()->can('see_performance_economique') || Auth::user()->hasRole(ROLE::CONTROLEUR_GESTION)) {
                $indicateurs['gains_notifies_direction'] = $this->get_gains_notifies_directions(clone $projets);
                $indicateurs['gains_notifies_famille'] = $this->get_gains_notifies_famille(clone $projets);
            }
            if (Auth::user()->can('see_performance_economique')) {
                $indicateurs['referentiel'] = $this->get_projets_referentiel(clone $projets);
                $indicateurs['champ_referentiel'] = Structure::find(Auth::user()->structure_id)->champ_referentiel;
                $indicateurs['top5famille'] = $this->get_top_5_familles(clone $projets);
                $indicateurs['table'] = (new ProjetsTable(clone $projets))->setup();
            }
            if (Auth::user()->can('see_achats_mutualises')) {
                $indicateurs['gains_notifies_niveaux_mutualisations'] = $this->get_gains_notifies_niveaux_mutualisations(clone $projets);
                $indicateurs['repartition_gains_notifies_niveaux_mutualisations'] = $this->get_repartition_gains_notifies_niveaux_mutualisations(clone $projets);
                $indicateurs['gains_notifies_operateurs_mutualisations'] = $this->get_gains_notifies_operateurs_mutualisations(clone $projets);
                $indicateurs['repartition_gains_notifies_operateurs_mutualisations'] = $this->get_repartition_gains_notifies_operateurs_mutualisations(clone $projets);
            }
            if (Auth::user()->can('see_rse')) {
                $indicateurs['rse'] = $this->get_rse(clone $projets);
            }
            if (Auth::user()->can('see_gestion_paat') || Auth::user()->hasRole(ROLE::ACHETEUR)) {
                $indicateurs['projets_statuts'] = $this->get_statuts_projets(clone $projets);
            }
            if (Auth::user()->can('see_gestion_paat')) {
                $indicateurs['enjeux_efforts'] = $this->get_matrice_enjeux_efforts(clone $projets);
                $indicateurs['leviers'] = $this->get_projets_leviers(clone $projets);
            }
            if (Auth::user()->hasRole(ROLE::ACHETEUR)) {
                $indicateurs['projet_count'] = $projets->count();
            }
            if (Auth::user()->hasAnyRole([ROLE::ACHETEUR, ROLE::CONTROLEUR_GESTION])) {
                $indicateurs['perimetre_traite'] = $projets->sum('montant_reference');
            }
        }

        // Filtres
        $filtres = [];
        if (Auth::user()->canAny(['see_performance_economique', 'see_achats_mutualises', 'see_rse', 'see_gestion_paat'])
        || Auth::user()->hasAnyRole([ROLE::RESPONSABLE_PERFORMANCE_ARS, ROLE::CONTROLEUR_GESTION, ROLE::ACHETEUR])) {
            $filtres = [
                'paats' => $paats,
                'paat_id' => $paat_id,
                'date_debut' => $date_debut,
                'date_fin' => $date_fin,
                'familles' => $familles,
                'famille_id' => $famille_id,
                'domaines' => $domaines,
                'domaine_id' => $domaine_id,
                'categories' => $categories,
                'categorie_id' => $categorie_id,
                'segments' => $segments,
                'segment_id' => $segment_id,
                'utilisateurs' => $utilisateurs ?? null,
                'utilisateur_id' => $utilisateur_id,
                'show_export_button' => $this->show_export_button($indicateurs)
            ];
        }

        // On définit cette variable dans le cas où on filtre le tableau pour rediriger en bas de la page
        $scroll_to_table = false;
        if ($refresh_table) {
            $filtres['active'] = 'refresh_table';
            $scroll_to_table = true;
        }

        // On récupère les commentaires du rapport d'activite s'il y en a
        $user_rapport_activite = CommentairesRapportActivite::get_current_monthly_rapport_activite();
        $user_liste_rapports_activite = CommentairesRapportActivite::where('user_id', Auth::user()->id)
            ->where('id', '!=', $user_rapport_activite ? $user_rapport_activite->id : -1)
            ->orderBy('date_rapport')
            ->get();

        return view('home.index', array_merge(
            ['logo' => Structure::find(Auth::user()->structure_id)->logo,],
            $filtres,
            $indicateurs,
            [
                "scroll_to_table" => $scroll_to_table,
                "liste_paat_annees" => $liste_paat_annees ?? [],
                "liste_structures" => $liste_structures ?? [],
                "user_rapport_activite" => $user_rapport_activite,
                "user_liste_rapports_activite" => $user_liste_rapports_activite
            ],
        ));
    }

    public function refresh_table(Request $request)
    {
        return $this->index(true);
    }

    /**
     * Permet de retourner les filtres selectionnés pour mettre a jour l'index
     * @param Request $request
     */
    public function filtres(Request $request)
    {
        // On split la value pour le domaine qui est de la forme famille_domaine
        $split = explode('_', $request->domaine_id);
        $domaine_id = end($split);

        // On split la value pour la categorie qui est de la forme domaine_categorie
        $split = explode('_', $request->categorie_id);
        $categorie_id = end($split);

        // On split la value pour le segment qui est de la forme categorie_segment
        $split = explode('_', $request->segment_id);
        $segment_id = end($split);

        Session::put([
            'date_debut' => $request->date_debut,
            'date_fin' => $request->date_fin,
            'famille_id' => $request->famille_id,
            'domaine_id' => $domaine_id,
            'categorie_id' => $categorie_id,
            'segment_id' => $segment_id,
            'utilisateur_id' => $request->utilisateur_id,
            'paat_id' => $request->paat_id
        ]);

        // On retourne sur l'index avec les filtres stockés dans la session
        return redirect()->route('home');
    }

    /**
     * Permet au responsable de la performance ARS de télécharger l'export toutes
     *  les données de tous les PAAT pour les GHT
     * @param Request $request
     */
    public function export_paats_resp_ars(Request $request)
    {
        if(Auth::user()->hasRole(ROLE::RESPONSABLE_PERFORMANCE_ARS)) {
            $annee = $request->query('annee-export-paats-resp-ars');
            $structure = $request->query('structure-export-paats-resp-ars');
            return Excel::download(new RespArsPaatsExport($annee, $structure), 'paats.xlsx');
        } else {
            abort(403);
        }
    }

    /**
     * Permet au responsable de la performance ARS de télécharger l'export toutes
     *  les données de tous les PAAT pour les GHT
     * @param Request $request
     */
    public function save_export_pdf(Request $request)
    {
        if (Auth::user()->can('export_indicateurs') || Auth::user()->hasRole(ROLE::RESPONSABLE_PERFORMANCE_ARS)) {
            $user_rapport = CommentairesRapportActivite::get_current_monthly_rapport_activite();

            if ($user_rapport != null) {
                $user_rapport->titre = $request->input('modal-export-pdf-titre');
                $user_rapport->date_paat = $request->input('modal-export-pdf-date-paat');
                $user_rapport->periode_reference = $request->input('modal-export-pdf-periode-reference');
                $user_rapport->commentaires = $request->input('modal-export-pdf-commentaires');
                $user_rapport->save();

            } else {
                CommentairesRapportActivite::create([
                    'titre' => $request->input('modal-export-pdf-titre'),
                    'date_paat' => $request->input('modal-export-pdf-date-paat'),
                    'periode_reference' => $request->input('modal-export-pdf-periode-reference'),
                    'commentaires' => $request->input('modal-export-pdf-commentaires'),
                    'date_rapport' => Carbon::today(),
                    'user_id' => Auth::user()->id,
                ]);
            }

            return redirect()->route('home')->with('success', 'Les commentaires ont été enregistrés avec succès.');
        } else {
            abort(403);
        }
    }

    /**
     * Retourne le nombre de projet par structure
     * @param $query
     * @return mixed
     */
    private function get_projets_structures($query)
    {
        return $query->select('structures.nom', DB::raw('COUNT(projets.id) AS total_projets'))
            ->groupBy('structures.nom')->pluck('total_projets', 'structures.nom')->toArray();
    }

    /**
     * Retourne le nombre de projet avec le referentiel armen par structure
     * @param $query
     * @return mixed
     */
    private function get_projets_referentiel_ars($query)
    {
        return $query->select('structures.nom', DB::raw('COUNT(projets.id) AS total_projets'))
            ->where('referentiel', true)->groupBy('structures.nom')
            ->pluck('total_projets', 'structures.nom')->toArray();
    }

    private function get_projets_referentiel_oui_non($query)
    {
        // On récupère les données en DBB
        $results = $query->select('structures.nom', DB::raw('IFNULL(SUM(referentiel = true), 0) AS oui'), DB::raw('IFNULL(SUM(referentiel = false), 0) AS non'))
            ->groupBy('structures.nom')->get();

        // On formatte les résultats pour qu'ils collent aux format du graphe chartjs
        $results_formatted = array();
        $results_formatted['structures'] = $results_formatted['oui'] = $results_formatted['non'] = array();
        foreach ($results as $r) {
            array_push($results_formatted['structures'], $r->nom);
            array_push($results_formatted['oui'], $r->oui);
            array_push($results_formatted['non'], $r->non);
        }

        return $results_formatted;
    }

    private function get_consolidation($query)
    {
        // On récupère toutes les infos que l'on souhaite afficher sur la carte
        return $query->select(
            'structures.nom',
            'structures.latitude',
            'structures.longitude',
            DB::raw('COUNT(projets.date_mise_en_oeuvre) AS total_notifies'),
            DB::raw('IFNULL(SUM(projets.referentiel = true), 0) AS total_referentiel'),
            DB::raw('COUNT(projets.id) AS total_projets'),
            DB::raw('IFNULL(SUM(CASE WHEN ondam = true THEN gains_notifie ELSE 0 END), 0) AS total_gains_notifie_ondam'),
            DB::raw('IFNULL(SUM(CASE WHEN ondam = true THEN montant_reference ELSE 0 END), 0) AS total_montant_reference_ondam')
        )
            ->groupBy('structures.nom', 'structures.latitude', 'structures.longitude')->get();
    }

    /**
     * Retourne le nombre de projet programmé et non programmé si la date de fin prévisionnelle est set -> Comme le champs est required on sépare juste en programme / non programme
     * @param $query
     * @return mixed
     */
    private function get_projets_cibles($query)
    {
        return $query->select(DB::raw('IFNULL(SUM(programme = true), 0) AS programmes'), DB::raw('IFNULL(SUM(programme = false), 0) AS non_programmes'))
            ->first();
    }

    /**
     * Retourne la somme des gains cibles
     * @param $query
     * @return mixed
     */
    private function get_projets_acheteur_gains_cible($query)
    {
        return $query->sum('gains_cible');
    }

    /**
     * Retourne la somme des gains notifies
     * @param $query
     * @return mixed
     */
    private function get_projets_acheteur_gains_notifie($query)
    {
        return $query->sum('gains_notifie');
    }

    /**
     * Retourne le nombre de projet programmé et non programmé si la date de notification est set -> si notifié
     * @param $query
     * @return mixed
     */
    private function get_projets_notifies($query)
    {
        return $query->select(DB::raw('IFNULL(SUM(programme = true), 0) AS programmes'), DB::raw('IFNULL(SUM(programme = false), 0) AS non_programmes'))
            ->whereNotNull('date_mise_en_oeuvre')->first();
    }

    /**
     * Retourne pour chaque direction les gains notifies
     * @param $query
     * @return mixed
     */
    private function get_gains_notifies_directions($query)
    {
        return $query->select('directions.nom', DB::raw('IFNULL(SUM(projets.gains_notifie), 0) AS total_gains_notifies'))
            ->join('directions', 'directions.id', '=', 'projets.direction_id')->having('total_gains_notifies', '>', 0)->groupBy('directions.nom')
            ->pluck('total_gains_notifies', 'directions.nom')->toArray();
    }

    /**
     * Retourne pour chaque service les gains notifies
     * @param $query
     * @return mixed
     */
    private function get_gains_notifies_services($query)
    {
        return $query->select('services.nom', DB::raw('IFNULL(SUM(projets.gains_notifie), 0) AS total_gains_notifies'))
            ->join('services', 'services.id', '=', 'projets.service_id')->having('total_gains_notifies', '>', 0)
            ->groupBy('services.nom')->pluck('total_gains_notifies', 'services.nom')->toArray();
    }

    /**
     * Retourne le nombre de projet par statut. Pour un projet qui possède plusieurs statuts, on prend le plus récent
     * @param $query
     * @return mixed
     */
    private function get_statuts_projets($query)
    {
        return $query->select('statuts.nom', DB::raw('COUNT(*) AS total'))
            ->join('projets_statuts', function ($query) {
                $query->on('projets_statuts.projet_id', '=', 'projets.id');
                // On récupère la dernière ligne du statut
                $query->whereRaw('projets_statuts.id IN (SELECT MAX(ps2.id) FROM projets_statuts AS ps2 JOIN projets AS p2 ON ps2.projet_id = p2.id GROUP BY p2.id)');
            })
            ->join('statuts', 'statuts.id', '=', 'projets_statuts.statut_id')->groupBy('statuts.nom')->pluck('total', 'statuts.nom')->toArray();
    }

    /**
     * Retourne pour chaque thématique le nombre de projet par action
     * @param $query
     * @return array
     */
    private function get_rse($query)
    {
        // On récupère les données en BDD
        $results = $query->select('thematiques.nom AS thematique', 'actions.nom AS action', DB::raw('COUNT(actions.nom) AS total'))
            ->join('projets_actions_resp_soc_env', 'projets_actions_resp_soc_env.projet_id', '=', 'projets.id')
            ->join('actions', 'actions.id', '=', 'projets_actions_resp_soc_env.action_id')
            ->join('thematiques', 'thematiques.id', '=', 'actions.thematique_id')->groupBy('thematique', 'action')->get();

        // On formatte les données pour pouvoir les utiliser simplement dans la vue
        $results_formatted = array();
        foreach ($results as $r) {
            if (!isset($results_formatted[$r->thematique])) {
                $results_formatted[$r->thematique] = array();
            }

            $results_formatted[$r->thematique][$r->action] = $r->total;
        }

        return $results_formatted;
    }

    /**
     * Retourne la sommes des gains notifiés par niveaux de mutualisation
     * @param $query
     * @return mixed
     */
    private function get_gains_notifies_niveaux_mutualisations($query)
    {
        return $query->select('niveaux_mutualisations.nom', DB::raw('IFNULL(SUM(projets.gains_notifie), 0) AS total_gains_notifies_mutualisation'))
            ->join('niveaux_mutualisations', 'niveaux_mutualisations.id', '=', 'projets.niveau_mutualisation_id')
            ->having('total_gains_notifies_mutualisation', '>', 0)->groupBy('niveaux_mutualisations.nom')
            ->pluck('total_gains_notifies_mutualisation', 'niveaux_mutualisations.nom')->toArray();
    }

    /**
     * Retourne la répartition en % des gains notifies par niveaux de mutualisation
     * @param $query
     * @return mixed
     */
    private function get_repartition_gains_notifies_niveaux_mutualisations($query)
    {
        $res = $query->select('niveaux_mutualisations.nom', DB::raw('IFNULL(SUM(projets.gains_notifie), 0) AS total_gains_notifies_mutualisation'))
            ->join('niveaux_mutualisations', 'niveaux_mutualisations.id', '=', 'projets.niveau_mutualisation_id')
            ->having('total_gains_notifies_mutualisation', '>', 0)->groupBy('niveaux_mutualisations.nom')
            ->pluck('total_gains_notifies_mutualisation', 'niveaux_mutualisations.nom')->toArray();
        $total_gains_notifies = array_sum(array_values($res));


        foreach ($res as $key => $value) {
            $res[$key] = round(($value / $total_gains_notifies) * 100, 2);
        }
        return $res;
    }

    /**
     * Retourne la sommes des gains notifiés par opérateur de mutualisation
     * @param $query
     * @return mixed
     */
    private function get_gains_notifies_operateurs_mutualisations($query)
    {
        return $query->select('operateurs_mutualisations.nom', DB::raw('IFNULL(SUM(projets.gains_notifie), 0) AS total_gains_notifies_operateur_mutualisation'))
            ->join('operateurs_mutualisations', 'operateurs_mutualisations.id', '=', 'projets.operateur_mutualisation_id')
            ->having('total_gains_notifies_operateur_mutualisation', '>', 0)->groupBy('operateurs_mutualisations.nom')
            ->pluck('total_gains_notifies_operateur_mutualisation', 'operateurs_mutualisations.nom')->toArray();
    }

    /**
     * Retourne la répartition en % des gains notifies par opérateurs de mutualisation
     * @param $query
     * @return mixed
     */
    private function get_repartition_gains_notifies_operateurs_mutualisations($query)
    {
        $res = $query->select('operateurs_mutualisations.nom', DB::raw('SUM(projets.gains_notifie) AS total_gains_notifies_operateur_mutualisation'))
            ->join('operateurs_mutualisations', 'operateurs_mutualisations.id', '=', 'projets.operateur_mutualisation_id')
            ->having('total_gains_notifies_operateur_mutualisation', '>', 0)->groupBy('operateurs_mutualisations.nom')
            ->pluck('total_gains_notifies_operateur_mutualisation', 'operateurs_mutualisations.nom')->toArray();
        $total_gains_notifies = array_sum(array_values($res));

        foreach ($res as $key => $value) {
            $res[$key] = round(($value / $total_gains_notifies) * 100, 2);
        }
        return $res;
    }

    /**
     * Retourne pour chaque mois les montant de référence, gains cibles et gains notifies
     * @param $query
     * @return array
     */
    private function get_montant_mois($query)
    {
        // On récupère les stats en BDD
        $results = $query->select(
            DB::raw('MONTH(date_debut) AS mois'),
            DB::raw('YEAR(date_debut) AS annee'),
            DB::raw('IFNULL(SUM(montant_reference), 0) AS total_montant_reference'),
            DB::raw('IFNULL(SUM(gains_cible), 0) AS total_gains_cible'),
            DB::raw('IFNULL(SUM(gains_notifie), 0) AS total_gains_notifie')
        )
            ->groupBy('mois', 'annee')->orderBy(DB::raw('mois, annee'))
            ->get();

        // On formatte les resultats pour qu'ils collent au format chartjs
        // Ici on veut plusieurs tableaux
        // On procède également au calcul du cumul des valeurs -> Trop complexe a faire en SQL
        $results_formatted = array();
        $results_formatted['mois'] = $results_formatted['montant_reference'] = $results_formatted['gains_cible'] = $results_formatted['gains_notifie'] = array();
        foreach ($results as $r) {
            array_push($results_formatted['mois'], TEXT::FRENCH_MONTH[$r->mois - 1] . ' ' . $r->annee);
            array_push($results_formatted['montant_reference'], array_sum($results_formatted['montant_reference']) + $r->total_montant_reference);
            array_push($results_formatted['gains_cible'], array_sum($results_formatted['gains_cible']) + $r->total_gains_cible);
            array_push($results_formatted['gains_notifie'], array_sum($results_formatted['gains_notifie']) + $r->total_gains_notifie);
        }

        // On retourne nos resultats
        return $results_formatted;
    }

    /**
     * Retourne le top 5 des familles en fonction du montant notifié et des gains notifiés
     * @param $query
     * @return mixed
     */
    private function get_top_5_familles($query)
    {
        return $query->select('familles.nom', DB::raw('IFNULL(SUM(montant_notifie), 0) AS total_montant_notifie'), DB::raw('IFNULL(SUM(gains_notifie), 0) AS total_gains_notifie'))
            ->join('familles', 'familles.id', '=', 'projets.famille_id')->groupBy('familles.nom')
            ->orderBy('total_montant_notifie', 'DESC')->orderBy('total_gains_notifie', 'DESC')->limit(5)->get();
    }
    /**
     * Permet d'obtenir le nombre de projet par levier
     * @param $query
     * @return mixed
     */
    private function get_projets_leviers($query)
    {
        return $query->select('leviers.nom', DB::raw('COUNT(*) AS total'))
            ->join('leviers_projets', 'leviers_projets.projet_id', '=', 'projets.id')
            ->join('leviers', 'leviers.id', '=', 'leviers_projets.levier_id')
            ->groupBy('leviers.nom')->pluck('total', 'leviers.nom')->toArray();
    }

    /**
     * Permet de retourner le nombre de projet avec le referentiel
     * @param $query
     * @return mixed
     */
    private function get_projets_referentiel($query)
    {
        return $query->where('referentiel', true)->count();
    }

    private function get_matrice_enjeux_efforts($query)
    {
        $results = $query->select('projets.objet', 'projets.gains_cible', DB::raw('IFNULL(SUM(taches_gestion_projet.nb_jours), 0) AS nb_jours'))
            ->leftJoin('taches_gestion_projet', 'taches_gestion_projet.projet_id', '=', 'projets.id')
            ->whereNotNull('projets.gains_cible')
            ->groupBy('projets.objet', 'projets.gains_cible')->get();

        $results_formatted = [];
        foreach ($results as $r) {
            // On associe les valeurs pour l'objet du projet
            $results_formatted[$r->objet] = ['x' => $r->nb_jours, 'y' => $r->gains_cible];
        }
        return $results_formatted;
    }

    /**
     * Retourne pour chacune des familles les gains notifiés des projets
     * @param $query
     * @return mixed
     */
    private function get_gains_notifies_famille($query)
    {
        return $query->select(DB::raw('IFNULL(familles.nom, \'Aucune\') AS nom'), DB::raw('IFNULL(SUM(projets.gains_notifie), 0) AS total_gains_notifies'))
            ->leftJoin('familles', 'familles.id', '=', 'projets.famille_id')->having('total_gains_notifies', '>', 0)
            ->groupBy('nom')->pluck('total_gains_notifies', 'nom')->toArray();
    }

    /**
     * Permet de ne pas afficher le bouton exporter dans la vue s'il y a aucune donnée
     * @param $indicateurs
     * @return bool
     */
    private function show_export_button($indicateurs)
    {
        if (Auth::user()->hasRole(ROLE::RESPONSABLE_PERFORMANCE_ARS)) {
            return (isset($indicateurs['projets_structures']) && sizeof($indicateurs['projets_structures']) > 0)
                || (isset($indicateurs['referentiel']) && sizeof($indicateurs['referentiel']) > 0)
                || (isset($indicateurs['referentiel_oui_non']) && !!array_filter(array_values($indicateurs['referentiel_oui_non'])));
        } else {
            return (isset($indicateurs['gains_notifies_direction']) && sizeof($indicateurs['gains_notifies_direction']) > 0)
                || (isset($indicateurs['gains_notifies_service']) && sizeof($indicateurs['gains_notifies_service']) > 0)
                || (isset($indicateurs['projets_statuts']) && sizeof($indicateurs['projets_statuts']) > 0)
                || (isset($indicateurs['rse']) && sizeof($indicateurs['rse']) > 0)
                || (isset($indicateurs['gains_notifies_niveaux_mutualisations']) && sizeof($indicateurs['gains_notifies_niveaux_mutualisations']) > 0)
                || (isset($indicateurs['gains_notifies_operateurs_mutualisations']) && sizeof($indicateurs['gains_notifies_operateurs_mutualisations']) > 0)
                || (isset($indicateurs['montants']) && !!array_filter(array_values($indicateurs['montants'])))
                || (isset($indicateurs['leviers']) && sizeof($indicateurs['leviers']) > 0);
        }
    }
}
