<?php

namespace App\Jobs;

use App\Models\Classe;
use App\Models\Inscription;
use App\Models\LevelMatter;
use App\Models\MoyenneTrimestrielle;
use App\Models\MoyenneDecoupageMatiere;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Bus;

class CalculMoyenneTrimestielleJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $class, $cutting, $bilan;
    public function __construct($class, $cutting, $bilan)
    {
        $this->class = $class;
        $this->cutting = $cutting;
        $this->bilan = $bilan;
    }


    public function handle(): void
    {
        $dts = getClassement($this->getMoyenne());
        foreach($dts as $item){
            $exist = $this->verifyMoyen($item['id']);
            if($exist){
                $exist->update([
                    'rang' => $item['rang'],
                    'coeffs' => $item['coeff'],
                    'points' => $item['point'],
                    'moyenne' => $item['moyen']
                ]);
            }
            else{
                $this->saveMoyen($item['id'], $item['moyen'], $item['rang'], $item['coeff'], $item['point']);
            }
        }

        Bus::chain([
            new CalculMoyenneBilanJob($this->class, $this->cutting, $this->bilan, $this->school()),
            new CalculResultatClasseJob($this->class, $this->school(), $this->cutting)
        ])->dispatch();
    }


    private function getMoyenne() {
        $table = []; $data = $this->getStudent();
        foreach ($data as $item) {
            $val = $this->calculMoyenne($item['id']);
            $table[] = [
                'id' => $item['id'],
                'sexe' => $item['sexe'],
                'moyen' => $val['moyen'],
                'point' => $val['point'],
                'coeff' => $val['coeff']
            ];
        }
        return $table;
    }


    private function calculMoyenne($item) {
        $point = 0; $coefs = 0; $exist = false;
        $data = $this->setMoyen($item);
        foreach($data as $val){
            $coef = $this->getCoeff($val['level_matter_id']);
            if($val['moyenne'] != 'nc'){
                $point += ($val['moyenne'] * $coef); $coefs += $coef; $exist = true;
            }
        }
        $moyen = $exist ? ($point ? number_format(($point / $coefs), 2, '.', ' '):'0'):'nc';
        return ['point' => $point, 'coeff' => $coefs, 'moyen' => $exist ? ($moyen < 10 ? '0'.$moyen:$moyen):$moyen];
    }


    private function getCoeff($matter) {
        $class = Classe::where('id', $this->class)->first();
        $coeff = LevelMatter::where('id', $matter)->where('level_id', $class['level_id'])->where('serie_id', $class['serie_id'])->where('type', $class['type'])->where('school_id', $this->school())->first();
        return $coeff ? $coeff->coefficient->valeur:null;
    }


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


    private function saveMoyen($item, $moyen, $rang, $coeff, $pnt) {
        MoyenneTrimestrielle::create([
            'rang' => $rang,
            'points' => $pnt,
            'coeffs' => $coeff,
            'moyenne' => $moyen,
            'inscription_id' => $item,
            'school_id' => $this->school(),
            'cutting_school_year_id' => $this->cutting
        ]);
    }


    private function setMoyen($item) {
        $dts = MoyenneDecoupageMatiere::where('inscription_id', $item)->where('cutting_school_year_id', $this->cutting)->get();
        return json_decode($dts, true) ?? null;
    }


    private function verifyMoyen($item) {
        $dta = MoyenneTrimestrielle::where('inscription_id', $item)->where('cutting_school_year_id', $this->cutting)->first();
        return $dta ?? null;
    }

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