<?php

namespace App\Http\Controllers;

use App\Models\Classe;
use App\Models\Setting;
use App\Models\Student;
use App\Models\SubMatter;
use App\Models\SchoolYear;
use App\Models\LevelMatter;
use App\Models\PrimaryNote;
use App\Models\MoyenneBilan;
use App\Models\MoyenneMatiere;
use App\Models\EvaluatedLevel;
use App\Models\MoyenneSubMatter;
use App\Models\ClasseEnseignant;
use App\Models\ResultatPrimaire;
use App\Models\CuttingSchoolYear;
use App\Models\LevelPrimaryMatters;
use App\Models\MoyenneTrimestrielle;
use App\Models\MoyenneDecoupageMatiere;
use App\Jobs\BonnusMoyenneMatiereJob;
use App\Jobs\CalculResultatClasseJob;
use App\Jobs\NonClasseeRangTrimestreJob;
use App\Jobs\NonClasseeRangMatiereJob;
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.'
            ]);
        }
    }


    public function show(Request $request)
    {
        try{
            $val = $request->validate([
                'select' => 'required|string',
                'class' => 'required|string'
            ]);
            $class = Classe::find($val['class']);
            if($class->type == 'primaire'){
                $matters = LevelPrimaryMatters::where('level_id', $class['level_id'])->get();
                $evaluated = EvaluatedLevel::find($val['select']);
                return view('pages.composition.detail',[
                    'evaluated' => $evaluated,
                    'classe' => $class,
                    'matters' => $matters,
                    'datas' => $this->getNoteEvaluated($val['class'], $val['select'], $matters)
                ]);
            }
            else{
                $data = $this->studentMoyenneList($class, $val['select']);
                $cutting = CuttingSchoolYear::find($val['select']);
                $matters = !$this->verifyLevel($class['level_id']) ? 
                $this->classeMatterLevel($class):
                array_merge($this->subMatterLevel(), $this->classeMatterLevel($class));
                $prof = ClasseEnseignant::where('classe_id', $class['level_id'])->where('prof_prl', '1')->first();
                return view('pages.moyenne.detail',[
                    'datas' => $data,
                    'classe' => $class,
                    'enseignant' => $prof,
                    'matters' => $matters,
                    'cutting' => $cutting
                ]);
            }
        }
        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('A3', 'landscape');// ou 'A4', 'A3', etc.
            return $pdf->stream($name.'.pdf');
        }
        catch (\Exception $e) {
            return back()->with([
                'str' => 'danger',
                'msg' => 'Une erreur est survenue.'
            ]);
        }
    }


    public function primaryPdf($str){
        try{
            list($id1, $id2) = explode('_', $str);
            $class = Classe::find($id1);
            $matters = LevelPrimaryMatters::where('level_id', $class['level_id'])->get();
            $evaluated = EvaluatedLevel::find($id2);
            $school = Setting::where('school_id', $class['school_id'])->first();
            $evul = str_replace(' ', '_', $evaluated->evaluated->libelle);
            $name = $evul.'_'.$class->libelle;
            $pdf = PDF::loadView('pages.composition.pdf_list',[
                'class' => $class,
                'school' => $school,
                'matters' => $matters,
                'evaluated' => $evaluated,
                'datas' => $this->getNoteEvaluated($id1, $id2, $matters)
            ])->setPaper('A3', 'landscape');// ou 'A4', 'A3', etc.
            return $pdf->stream($name.'.pdf');
        }
        catch (\Exception $e) {
            return back()->with([
                'str' => 'danger',
                'msg' => 'Une erreur est survenue.'
            ]);
        }
    }

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



    public function matters(Request $request)
    {
        try{
            $val = $request->validate([
                'class' => 'required|string',
                'cutting' => 'required|string'
            ]);
            $data = DB::table('matters')
            ->join('level_matter', 'matters.id', '=', 'level_matter.matter_id')
            ->join('approved_moyennes', 'level_matter.id', '=', 'approved_moyennes.level_matter_id')
            ->select('level_matter.id', 'matters.libelle', 'matters.abbreviated', DB::raw("IF(abbreviated = 'All/Esp', 'LV2', abbreviated) as abbreviated"))
            ->where('approved_moyennes.cutting_school_year_id', $val['cutting'])
            ->where('approved_moyennes.classe_id', $val['class'])
            ->orderBy('matters.libelle')->get();
            $cutting = CuttingSchoolYear::where('id', $val['cutting'])->first();
            return (['cutting' => ucfirst($cutting->cutting['libelle']), 'matters' => $data]);
        }
        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{
            $val = $request->validate([
                'classe' => 'required|string',
                'cutting' => 'required|string',
                'student' => 'required|array',
                'moyen' => 'required|array',
            ]);
            $table = []; $i = 0;
            while($i < sizeof($val['student'])){
                list($item, $sexe) = explode('_', $val['student'][$i]);
                $table[] = [
                    'id' => $item,
                    'sexe' => $sexe,
                    'moyen' => formatMoyenne($val['moyen'][$i])
                ];
                $i++;
            }
            if(count($table)){
                Bus::chain([new BonnusMoyenneMatiereJob($table, $matter, $val['cutting'], $val['classe'], true)])->dispatch();
            }
            return to_route('moyenne.return', $val['classe'].'_'.$val['cutting'])->with([
                'str' => 'info',
                'msg' => 'Modification effectuée, Traitement en cours de finition'
            ]);
        }
        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'])->update([
                    'moyenne' => 'nc' // Update sur le champ moyenne .........
                ]);
                MoyenneBilan::where('inscription_id', $item)->where('cutting_school_year_id', $vals['cutting'])->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'], $vals['cutting']),
                new NonClasseeRangTrimestreJob($vals['classe'], $vals['cutting']),
                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 => 'myTable1', 2 => 'myTable2', 3 => 'myTable3', 4 => 'myTable1', 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;
    }



    /**
     * 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 ? ($moyen['moyenne'] == 'nc' ? $compte++:null):$compte++; // 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'],
                'photo' => $item['photo'],
                'moyen' => $moyen['moyenne'] ?? 'nc'
            ];
        }
        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'],
                'photo' => $item['photo'],
                '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 = Student::join('inscriptions', 'students.id', '=', 'inscriptions.student_id')
            ->select('inscriptions.id', 'students.first_name', 'students.last_name', 'students.matricule', 'students.sexe', 'students.photo', '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'],
                'photo' => $item['photo'],
                '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 = Student::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;
    }


    protected function getNoteEvaluated($class, $evalId, $matters) {
        $student = $this->getStudentPrimary($class);
        $tabs = [];
        foreach($student as $item){
            $tabs[] = [
                'id' => $item->id,
                'name' => strtoupper($item->first_name).' '.ucwords($item->last_name),
                'sexe' => strtoupper($item->sexe),
                'matricule' => $item->matricule,
                'photo' => $item->photo,
                'resultat' => ResultatPrimaire::where('inscription_id', $item->id)->where('evaluated_level_id', $evalId)->first(),
                'notes' => $this->noteStudent($item->id, $evalId, $matters)
            ];
        }
        return $tabs;
    }
    

    protected function noteStudent($id, $evalId, $matters) {
        $data = [];
        foreach($matters as $matter){
            $data[] = [
                'note' => PrimaryNote::where('inscription_id', $id)->where('evaluated_level_id', $evalId)->where('level_primary_matter_id', $matter->id)->first(),
                'valeur' => $matter->points
            ];
        }
        return $data;
    }


    protected function getStudentPrimary($id) {
        $year = $this->yearActif();
        $data = Student::join('inscriptions', 'students.id', '=', 'inscriptions.student_id')
        ->select('inscriptions.id', 'students.first_name', 'students.last_name', 'students.matricule', 'students.sexe', 'students.photo', 'inscriptions.redoublant')
        ->where('inscriptions.school_year_id', '=', $year->id)
        ->where('inscriptions.classe_id', '=', $id)
        ->orderBy('students.first_name')
        ->orderBy('students.last_name')
        ->get();
        return $data;
    }

    
    protected function yearActif(){
        $dts = SchoolYear::where('status', '1')->first();
        return $dts;
    }
}