<?php

namespace App\Jobs;

use App\Models\Classe;
use App\Models\Matter;
use App\Models\SubMatter;
use App\Models\Inscription;
use App\Models\MoyenneMatiere;
use App\Models\MoyenneSubMatter;
use App\Models\MoyenneDecoupageMatiere;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class NonClasseeRangMatiereJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
    protected $students, $cutting, $matieres, $submatiere, $class;

    /**
     * Create a new job instance.
     */
    public function __construct($students, $cutting, $matieres, $submatiere = null, $class)
    {
        $this->students = $students;
        $this->cutting = $cutting;
        $this->matieres = $matieres;
        $this->submatiere = $submatiere;
        $this->class = $class;
    }

    /**
     * Execute the job.
     */
    public function handle(): void
    {
        foreach($this->matieres as $item){
            $this->updateRang($item['id']);
        }
        // Sous matiere en français 
        if($this->submatiere){
            $matters = SubMatter::get(['id']);
            foreach($matters as $item){
                $this->updateRangSubMatter($item['id']);
            }
        }
        if($this->class['lv2']){
            $this->updateRangLv2();
        }
    }


    private function updateRang($matter) {
        $dts = getClassement($this->getMoyenne($matter, false));
        foreach($dts as $item){
            $this->getUpdated($item['id'], $matter, $item['rang']); // update du champ rang
        }
    }


    private function updateRangLv2() {
        $dts = getClassement($this->getLv2Moyenne());
        foreach($dts as $item){
            $this->getUpdated($item['id'], $item['matter'], $item['rang']); // update du champ rang
        }
    }


    protected function updateRangSubMatter($matter) {
        $dts = getClassement($this->getMoyenne($matter, true));
        foreach($dts as $items){
            MoyenneSubMatter::where('inscription_id', $items['id'])->where('sub_matter_id', $matter)->where('cutting_school_year_id', $this->cutting)->update([
                'rang' => $items['rang'] // update du champ rang
            ]);
        }
    }


    private function getMoyenne($matter, $sub) {
        $table = []; $data = $this->getStudent();
        foreach($data as $item){
            $table[] = [
                'id' => $item['id'],
                'sexe' => $item['sexe'],
                'moyen' => $this->moyenne($item['id'], $matter, $sub)
            ];
        }
        return $table;
    }


    private function getLv2Moyenne() {
        $table = []; $data = $this->getStudent();
        foreach($data as $item){
            $val = $this->moyenne($item['id'], $item['lv2'], null);
            $table[] = [
                'id' => $item['id'],
                'sexe' => $item['sexe'],
                'moyen' => $val['moyenne'],
                'matter' => $val['matter'],
            ];
        }
        return $table;
    }
    

    private function moyenne($item, $matter, $sub = null) {
        if($sub){
            $val = MoyenneSubMatter::where('inscription_id', $item)->where('sub_matter_id', $matter)->where('cutting_school_year_id', $this->cutting)->first();
        }
        else{
            $val = MoyenneDecoupageMatiere::where('inscription_id', $item)->where('level_matter_id', $matter)->where('cutting_school_year_id', $this->cutting)->first();
        }
        return $val ? $val['moyenne']:'nc';
    }


    private function moyenLv2($item, $lv2) {
        $matter =  $this->matterLv2($lv2);
        if($matter){
            $val = MoyenneDecoupageMatiere::where('inscription_id', $item)->where('level_matter_id', $matter)->where('cutting_school_year_id', $this->cutting)->first();
        }
        return ['matter' => $matter, 'moyenne' => $val ? $val['moyenne']:'nc'];
    }


    private function getStudent() {
        $data = Inscription::join('students', 'students.id', 'inscriptions.student_id')
        ->select('inscriptions.id', 'students.sexe', 'inscriptions.lv2')
        ->where('inscriptions.classe_id', '=', $this->class)
        ->orderBy('students.first_name')
        ->orderBy('students.last_name')
        ->get();
        return json_decode($data, true);
    }


    private function matterLv2($lv2) {
        $class = $this->classe();
        $matter =  Matter::join('level_matter', 'matters.id', '=', 'level_matter.matter_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))
        ->select('level_matter.id')
        ->first();
        return $matter ? $matter['id']:null;
    }


    private function getUpdated($student, $matter, $rang) {
        MoyenneDecoupageMatiere::where('inscription_id', $student)->where('level_matter_id', $matter)->where('cutting_school_year_id', $this->cutting)->update([
            'rang' => $rang // update du champ rang
        ]);
        MoyenneMatiere::where('inscription_id', $student)->where('level_matter_id', $matter)->where('cutting_school_year_id', $this->cutting)->update([
            'rang' => $rang // update du champ rang
        ]);
    }

    private function classe() {
        $class = Classe::find($this->class);
        return $class ? $class:null;
    }
}
