<?php

namespace App\Http\Controllers;

use App\Models\Classe;
use App\Models\Setting;
use App\Models\SubMatter;
use App\Models\SchoolYear;
use App\Models\LevelMatter;
use App\Models\MoyenneBilan;
use App\Models\MoyenneMatiere;
use App\Models\MoyenneSubMatter;
use App\Models\ClasseEnseignant;
use App\Models\CuttingSchoolYear;
use App\Models\MoyenneTrimestrielle;
use App\Models\MoyenneDecoupageMatiere;
use App\Jobs\CalculMoyenneTrimestielleJob;
use App\Jobs\BonnusMoyenneMatiereJob;
use App\Jobs\CalculMoyenneBilanJob;
use App\Jobs\CalculResultatClasseJob;
use App\Jobs\NonClasseeRangTrimestreJob;
use App\Jobs\NonClasseeRangMatiereJob;
use App\Jobs\NonClasseeRangBilanJob;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Bus;
use Illuminate\Http\Request;
use PDF;

class GetMoyenneController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index()
    {
        try{
            $data = Setting::where('school_id', auth()->user()->school_id)->first();
            return view('pages.moyenne.index',[
                'data' => $this->typeEnseignement($data)
            ]);                 
        }
        catch (\Exception $e) {
            return back()->with([
                'str' => 'danger',
                'msg' => 'Une erreur est survenue.'
            ]);
        }
    }

    /**
     * Show the form for creating a new resource.
     */
    public function filePdf(string $str)
    {
        try{
            $id = explode('_', $str);
            $class = Classe::where('id', $id[0])->where('school_id', auth()->user()->school_id)->first();
            $cutting = CuttingSchoolYear::where('id', $id[1])->where('school_year_id', $class['school_year_id'])->first();
            $setting = Setting::where('school_id', $class['school_id'])->first();
            $matters = !$this->verifyLevel($class['level_id']) ? $this->classeMatterLevel($class):array_merge($this->subMatterLevel(), $this->classeMatterLevel($class));
            $name = 'liste_moyenne_'.$cutting->cutting->libelle.'_'.$class->libelle;
            $pdf = PDF::loadView('pdf.list_moyenne',[
                'class' => $class,
                'school' => $setting,
                'decoup' => $cutting,
                'matters' => $matters,
                'datas' => $this->studentMoyenneList($class,$cutting['id'])
            ])->setPaper('A4', 'landscape');// ou 'A4', 'A3', etc.
            // ->setOptions(['isHtml5ParserEnabled' => true]);

            // return $pdf->download($name.'.pdf');
            return $pdf->stream($name.'.pdf');
        }
        catch (\Exception $e) {
            return back()->with([
                'str' => 'danger',
                'msg' => 'Une erreur est survenue.'
            ]);
        }
    }

    /**
     * Display the specified resource.
     */
    public function show(string $id)
    {
        try{
            $type = ['secondaire' => 'general', 'technique' => 'technique', 'superieur' => 'superieur'];
            $class = Classe::find($id);
            $cutting = CuttingSchoolYear::where('type', $type[$class['type']])->where('school_year_id', $class['school_year_id'])->get();
            $prof = ClasseEnseignant::where('classe_id', $id)->where('prof_prl', '1')->first();
            // 
            return view('pages.moyenne.detail',[
                'classe' => $class,
                'enseignant' => $prof,
                'matters' => !$this->verifyLevel($class['level_id']) ? $this->classeMatterLevel($class):array_merge($this->subMatterLevel(), $this->classeMatterLevel($class)),
                'datas' => $this->getCutting($cutting, $class)
            ]);
        }
        catch (\Exception $e) {
            return back()->with([
                'str' => 'danger',
                'msg' => 'Une erreur est survenue.'
            ]);
        }
    }



    public function matters(Request $request)
    {
        try{
            $val = $request->validate([
                'idClasse' => 'required|string',
                'idCutting' => 'required|string'
            ]);

            $class = Classe::find($val['idClasse']);
            $cutting = CuttingSchoolYear::where('id', $val['idCutting'])->first();
            return (['cutting' => ucfirst($cutting->cutting['libelle']), 'matters' => $this->classeMatterLevel($class)]);
        }
        catch (\Exception $e) {
            return back()->with([
                'str' => 'danger',
                'msg' => 'Une erreur est survenue.'
            ]);
        }
    }

    /**
     * Show the form for editing the specified resource.
     */
    public function edit(Request $request)
    {
        try{
            $val = $request->validate([
                'classe' => 'required|string',
                'cutting' => 'required|string',
                'matter' => 'required|string'
            ]);
            $class = Classe::find($val['classe']);
            $cutting = CuttingSchoolYear::where('id', $val['cutting'])->first();
            $matter = LevelMatter::find($val['matter']);
            $dtas = $this->editMoyenneMatter($class, $val['matter'], $val['cutting']);
            return view('pages.moyenne.edit',[
                'class' => $class,
                'matter' => $matter,
                'decoup' => $cutting,
                'datas' => $this->editMoyenneMatter($class, $val['matter'], $val['cutting'])
            ]);
            
        }
        catch (\Exception $e) {
            return back()->with([
                'str' => 'danger',
                'msg' => 'Une erreur est survenue.'
            ]);
        }
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(Request $request, string $matter)
    {
        try{
            $data = []; $i = 0;
            while($i < sizeof($request['student'])){
                $data[] = [
                    'id' => explode('_', $request['student'][$i])[0],
                    'sexe' => explode('_', $request['student'][$i])[1],
                    'moyen' => $request['moyen'][$i]
                ];
                $i++;
            }

            // Les traitements pour les jobs
            Bus::chain([
                new BonnusMoyenneMatiereJob($data, $matter, $request['cutting'], $request['classe']),
                new CalculMoyenneTrimestielleJob($this->getStudent($request['classe']), $request['classe'], $request['cutting'], auth()->user()->school_id),
                new CalculMoyenneBilanJob($this->getStudent($request['classe']), $request['classe'], $request['cutting'], $this->bilanMatter($matter), auth()->user()->school_id),
                new CalculResultatClasseJob($request['classe'], auth()->user()->school_id, $request['cutting'])
            ])->dispatch();
            
            return to_route('moyenne.show', $request['classe'])->with([
                'str' => 'info',
                'msg' => 'Les modifications seront disponibles dans quelque temps'
            ]);
        }
        catch (\Exception $e) {
            return back()->with([
                'str' => 'danger',
                'msg' => 'Une erreur est survenue.'
            ]);
        }
    }

    /**
     * Unclassified Get data moyen the specified resource from storage.
     */
    public function unclassified($string)
    {
        try{
            $str = explode('_', $string);
            $data = $this->studentUnClassified($str[0], $str[1]);
            return view('pages.moyenne.unclassified',[
                'classe' => Classe::find($str[0]),
                'cutting' => CuttingSchoolYear::find($str[1]),
                'datas' => $data[0],
                'nombre' => $data[1]
            ]);
        }
        catch (\Exception $e) {
            return back()->with([
                'str' => 'danger',
                'msg' => 'Une erreur est survenue.'
            ]);
        }
    }


    public function submit(Request $request)
    {
        try{
            $vals = $request->validate([
                'classe' => 'required|string',
                'cutting' => 'required|string',
                'tags' => 'required|Array',
            ]);
            foreach ($vals['tags'] as $item) {
                MoyenneTrimestrielle::where('inscription_id', $item)->where('cutting_school_year_id', $vals['cutting'])->where('school_id', auth()->user()->school_id)->update([
                    'moyenne' => 'nc' // Update sur le champ moyenne .........
                ]);
                MoyenneBilan::where('inscription_id', $item)->where('cutting_school_year_id', $vals['cutting'])->where('school_id', auth()->user()->school_id)->update([
                    'moyenne' => 'nc', // Update sur le champ moyenne .........
                    'coeffs' => 'nc', // Update sur le champ moyenne .........
                    'points' => 'nc' // Update sur le champ moyenne .........
                ]);
                MoyenneDecoupageMatiere::where('inscription_id', $item)->where('cutting_school_year_id', $vals['cutting'])->update([
                    'moyenne' => 'nc' // Update sur le champ moyenne .........
                ]);
                MoyenneMatiere::where('inscription_id', $item)->where('cutting_school_year_id', $vals['cutting'])->update([
                    'moyenne' => 'nc', // Update sur le champ moyenne .........
                ]);
                MoyenneSubMatter::where('inscription_id', $item)->where('cutting_school_year_id', $vals['cutting'])->update([
                    'moyenne' => 'nc', // Update sur le champ moyenne .........
                    'coefficient' => 'nc'
                ]); 
            }

            $class = Classe::find($vals['classe']);
            Bus::chain([
                new CalculResultatClasseJob($vals['classe'], auth()->user()->school_id, $vals['cutting']),
                new NonClasseeRangTrimestreJob($this->getStudentClasse($vals['classe']), $vals['cutting'], auth()->user()->school_id),
                new NonClasseeRangBilanJob($this->getStudentClasse($vals['classe']), $vals['cutting'], auth()->user()->school_id),
                new NonClasseeRangMatiereJob($this->getStudentClasse($vals['classe']), $vals['cutting'], $this->classeMatterLevel($class), $this->verifyLevel($class['level_id']), $class)
            ])->dispatch();
            // Traitement du formulaire... 
            return back()->with([
                'str' => 'success',
                'msg' => 'Mise à jour en cour de traitement !'
            ]);
        }
        catch (\Exception $e) {
            return back()->with([
                'str' => 'danger',
                'msg' => 'Une erreur est survenue.'
            ]);
        }
    }

    
    protected function verifyLevel($val)
    {
        return in_array($val, [10,11,12,13]);
    }


    /**
     * Get data class the specified resource from storage.
     */
    protected function typeEnseignement($dts)
    {
        $tab = []; $i = 0; $primaire = 0; $cycle = 0;
        $school = auth()->user()->school_id;
        $year = $this->yearActif();
        $data = [1 => 'realtime-reorder', 2 => 'basic-col-reorder', 3 => 'saving-reorder', 4 => 'predefine-reorder', 5 => null];
        foreach ($dts->school->typeEnseignements as $item) {
            if(!$primaire && ($item['id'] == 1 || $item['id'] == 2)){
                $tab[] = [
                    'nbre' => $i+=1, 
                    'tab' => $data[$i], 
                    'libelle' => verifyPrimaire($dts->school->typeEnseignements),
                    'data' => Classe::where('type', 'primaire')->where('school_year_id', $year['id'])->where('status', '1')->where('school_id', $school)->orderBy('level_id')->get()
                ];$primaire++;
            }
            elseif(!$cycle && ($item['id'] == 3 || $item['id'] == 4)){
                $tab[] = [
                    'nbre' => $i+=1,
                    'tab' => $data[$i], 
                    'libelle' => verifySeconde($dts->school->typeEnseignements),
                    'data' => Classe::where('type', 'secondaire')->where('school_year_id', $year['id'])->where('status', '1')->where('school_id', $school)->orderBy('level_id')->get(),
                ];$cycle++;
            }
            elseif($item['id'] == 5){
                $val = $item['type_enseignement'];
                $tab[] =[
                    'nbre' => $i+=1, 
                    'tab' => $data[$i], 
                    'libelle' => $val,
                    'data' => Classe::where('type', 'technique')->where('school_year_id', $year['id'])->where('status', '1')->where('school_id', $school)->orderBy('level_id')->get(),
                ];
            }
            elseif($item['id'] == 6){
                $val = $item['type_enseignement'];
                $tab[] =[
                    'nbre' => $i+=1, 
                    'tab' => $data[$i], 
                    'libelle' => $val,
                    'data' => Classe::where('type', 'superieur')->where('school_year_id', $year['id'])->where('status', '1')->where('school_id', $school)->orderBy('level_id')->get(),
                ];
            }
        }
        return $tab;
    }


    /**
     * Gestion the cutting school year the specified resource from storage.
     */
    protected function getCutting($cutting, $class)
    {
        $tabs = []; $i = 1;
        $data = [1 => 'realtime-reorder', 2 => 'basic-col-reorder', 3 => 'saving-reorder', 4 => 'predefine-reorder', 5 => null];
        foreach($cutting as $item){
            $tabs[] = [
                'id' => $item->id,
                'libelle' => $item->cutting['libelle'],
                'actif' => $item->status,
                'tab' => $data[$i], 
                'data' => $this->studentMoyenneList($class, $item->id)
            ];
            $i++;
        }
        return $tabs;
    }



    /**
     * Get liste note end student the specified resource from storage.
     */
    protected function studentUnClassified($class, $cutting)
    {
        $dts = $this->getStudentClasse($class);
        $tab = []; $compte = 0;
        foreach($dts as $item){
            $moyen = $this->moyenTrimestre($item, $cutting);
            $moyen['moyenne'] == 'nc' ? $compte++:null; // Comptage des eleves non classés
            $tab[] = [
                'id' => $item['id'],
                'first_name' => strtoupper($item['first_name']),
                'last_name' => ucwords($item['last_name']),
                'matricule' => $item['matricule'],
                'sexe' => $item['sexe'],
                'moyen' => $moyen['moyenne'] ?? '--'
            ];
        }
        return [$tab, $compte];
    }


    /**
     * Get liste note end student the specified resource from storage.
     */
    protected function studentMoyenneList($class, $cutting)
    {
        $dts = $this->getStudentClasse($class->id);
        $tab = [];
        foreach($dts as $item){
            $moyen = $this->moyenTrimestre($item['id'], $cutting);
            $tab[] = [
                'id' => $item['id'],
                'name' => strtoupper($item['first_name']).' '.ucwords($item['last_name']),
                'matricule' => $item['matricule'],
                'sexe' => $item['sexe'],
                'moyens' => $this->getMoyenneStudent($item['id'], $cutting, $class, $item['lv2']),
                'moyen' => $moyen['moyenne'] ?? '--',
                'rang' => $moyen['rang'] ?? '--',
            ];
        }
        return $tab;
    }


    /**
     * Get school year actif the specified resource from storage.
     */
    protected function getStudentClasse($idclasse)
    {
        $year = $this->yearActif();
        $data = DB::table('students')
            ->join('inscriptions', 'students.id', '=', 'inscriptions.student_id')
            ->select('inscriptions.id', 'students.first_name', 'students.last_name', 'students.matricule', 'students.sexe', 'inscriptions.redoublant', 'inscriptions.lv2')
            ->where('inscriptions.classe_id', '=', $idclasse)
            ->where('inscriptions.school_year_id', '=', $year->id)
            ->orderBy('students.first_name')->orderBy('students.last_name')
            ->get();
        return json_decode($data, true);
    }


    /**
     * Get school year actif the specified resource from storage.
     */
    protected function getMoyenneStudent($student, $cutting, $class, $lv2 = null)
    {
        $matters = $this->classeMatterLevel($class);
        $moyens = [];
        foreach($matters as $item){
            if($class['type'] == 'secondaire' && $item['abbreviated'] == 'LV2'){
                $moyens[] = $this->moyenneStudentLv2($student, $cutting, $class, $lv2);  
            }
            else{
                $moyens[] = MoyenneDecoupageMatiere::where('inscription_id', $student)->where('level_matter_id', $item['id'])->where('cutting_school_year_id', $cutting)->first('moyenne');
            }
        }
        return !$this->verifyLevel($class['level_id']) ? $moyens:array_merge($this->subMatterMoyenne($student, $cutting), $moyens);
    }


    // Recuperation des moyennes des sous matieres en français .........................
    protected function subMatterMoyenne($student, $cutting)
    {
        $matters = SubMatter::get(['id', 'abbreviated', 'libelle']);
        $data = [];
        foreach($matters as $item){
            $data[] = MoyenneSubMatter::where('inscription_id', $student)->where('sub_matter_id', $item['id'])->where('cutting_school_year_id', $cutting)->first();
        }
        return $data;
    }


    protected function editMoyenneMatter($class, $matter, $cutting)
    {
        $dts = $this->getStudentClasse($class->id);
        $tab = [];
        foreach($dts as $item){
            $tab[] = [
                'id' => $item['id'],
                'first_name' => strtoupper($item['first_name']),
                'last_name' => ucfirst($item['last_name']),
                'matricule' => $item['matricule'],
                'sexe' => $item['sexe'],
                'moyen' => MoyenneDecoupageMatiere::where('inscription_id',  $item['id'])->where('level_matter_id', $matter)->where('cutting_school_year_id', $cutting)->first('moyenne')
            ];
        }
        return $tab;
    }


    protected function subMatterLevel(){

        return json_decode(SubMatter::get(['id', 'abbreviated', 'libelle']), true);
    }


    protected function classeMatterLevel($class){

        return array_merge($this->getMatieres($class, 1), $this->getMatieres($class, 2), $this->getMatieres($class, 3));
    }


    protected function getMatieres($class, $bilan){
        if($class['additif']){
            $additif = $class['additif'] == 'AP' ? 'Mus':'AP';
            $matters =  DB::table('matters')
            ->join('level_matter', 'matters.id', '=', 'level_matter.matter_id')
            ->join('libelle_bilan_matter', 'matters.id', '=', 'libelle_bilan_matter.matter_id')
            ->select('level_matter.id', 'matters.libelle', 'matters.abbreviated', DB::raw("IF(abbreviated = 'All/Esp', 'LV2', abbreviated) as abbreviated"))
            ->where('level_matter.school_id', '=', auth()->user()->school_id)
            ->where('level_matter.level_id', '=', $class['level_id'])
            ->where('level_matter.type', '=', $class['type'])
            ->where('level_matter.serie_id', '=', $class['serie_id'])
            // ->where('matters.libelle', '!=', 'Mixte') // Les classes mixte
            ->where('matters.libelle', '!=', 'Allemand') // Les classes mixte
            ->where('matters.libelle', '!=', 'Espagnol') // Les classes mixte
            ->where('abbreviated', '!=', $additif)
            ->where('libelle_bilan_matter.libelle_bilan_id', '=', $bilan)
            ->orderBy('libelle_bilan_matter.bilan')->get();
        }
        else{
            $matters =  DB::table('matters')
            ->join('level_matter', 'matters.id', '=', 'level_matter.matter_id')
            ->join('libelle_bilan_matter', 'matters.id', '=', 'libelle_bilan_matter.matter_id')
            ->select('level_matter.id', 'matters.libelle', 'matters.abbreviated', DB::raw("IF(abbreviated = 'All/Esp', 'LV2', abbreviated) as abbreviated"))
            ->where('level_matter.school_id', '=', auth()->user()->school_id)
            ->where('level_matter.level_id', '=', $class['level_id'])
            ->where('level_matter.type', '=', $class['type'])
            ->where('level_matter.serie_id', '=', $class['serie_id'])
            // ->where('matters.libelle', '!=', 'Mixte') // Les classes mixte
            ->where('matters.libelle', '!=', 'Allemand') // Les classes mixte
            ->where('matters.libelle', '!=', 'Espagnol') // Les classes mixte
            ->where('libelle', '!=','Arts plastique')->where('libelle', '!=','Musique')
            ->where('libelle_bilan_matter.libelle_bilan_id', '=', $bilan)
            ->orderBy('libelle_bilan_matter.bilan')->get();
        }
        return json_decode($matters, true);
    }



    protected function moyenneStudentLv2($student, $cutting, $class, $lv2)
    {
        $matter =  DB::table('matters')
        ->join('level_matter', 'matters.id', '=', 'level_matter.matter_id')
        ->select('level_matter.id')
        ->where('level_matter.school_id', '=', auth()->user()->school_id)
        ->where('level_matter.level_id', '=', $class['level_id'])
        ->where('level_matter.type', '=', $class['type'])
        ->where('level_matter.serie_id', '=', $class['serie_id'])
        ->where('matters.libelle', '=', ucfirst($lv2))
        ->orderBy('matters.libelle')->first();
        if($matter){
            $moyen = MoyenneDecoupageMatiere::where('inscription_id', $student)->where('level_matter_id', $matter->id)->where('cutting_school_year_id', $cutting)->first('moyenne');
        }
        return $moyen ?? null;
    }
    

    protected function moyenTrimestre($student, $cutting)
    {
        $data = MoyenneTrimestrielle::where('inscription_id', $student)->where('cutting_school_year_id', $cutting)->where('school_id', auth()->user()->school_id)->first();
        return $data;
    }


    protected function getStudent($class)
    {
        $year = $this->yearActif();
        $dts = DB::table('students')
        ->join('inscriptions', 'students.id', '=', 'inscriptions.student_id')
        ->select('inscriptions.id', 'students.first_name', 'students.last_name', 'students.matricule', 'students.sexe', 'inscriptions.redoublant')
        ->where('inscriptions.classe_id', '=', $class)
        ->where('inscriptions.school_year_id', '=', $year->id)
        ->orderBy('students.first_name')->orderBy('students.last_name')
        ->get();
        return $dts;
    }


    protected function bilanMatter($valeur)
    {
        $val = DB::table('matters')
        ->join('level_matter', 'matters.id', '=', 'level_matter.matter_id')
        ->join('libelle_bilan_matter', 'matters.id', '=', 'libelle_bilan_matter.matter_id')
        ->select('libelle_bilan_matter.libelle_bilan_id')->where('level_matter.id', '=', $valeur)->first();
        return $val->libelle_bilan_id;
    }


    /**
     * Get school year actif the specified resource from storage.
     */
    protected function yearActif(){
        $dts = SchoolYear::where('status', '1')->first();
        return $dts;
    }
}