<?php

namespace App\Http\Controllers;

use App\Models\Level;
use App\Models\Canteen;
use App\Models\Setting;
use App\Models\Payment;
use App\Models\Transport;
use App\Models\SchoolYear;
use App\Models\ScolarityFee;
use App\Models\PaymentCanteen;
use App\Models\PaymentTransport;
use App\Models\PaymentScolarity;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Carbon\Carbon;

// Facultatif : s'assurer que l'application est en français
App::setLocale('fr');
class PaymentController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index()
    {
        try{
            $data = Payment::where('school_id', auth()->user()->school_id)->where('school_year_id', $this->yearActif()->id)->orderBy('created_at', 'DESC')->get();
            return view('pages.payment.index',[
                'year' => $this->yearActif(),
                'datas' => $data,
                'scolarity' => $this->getScolarityTotalDay(),
                'annexFee' => $this->getAnnexFeeTotalDay(),
                'transport' => VerifyBox(auth()->user()->school->setting, 'transport') ? $this->transportBusTotalDay():0,
                'canteen' => VerifyBox(auth()->user()->school->setting, 'canteen') ? $this->cantineTotalDay():0,
            ]);
        }
        catch (\Exception $e) {
            return back()->with([
                'str' => 'danger',
                'msg' => 'Une erreur est survenue !'
            ]);
        }
    }

    /**
     * Show the form for creating a new resource.
     */
    public function create(Request $request)
    {
        $val = Payment::find($request['id']);
        if($request['val'] == 4){
            $payer = $val->scolaritie->amount->montant - collect($val->payment_scolarities)->sum('amount');
        }
        $montant = $request['val'] == 3 ? $val->annex_fee->amount->montant:$payer;
        return json_decode($val ? $montant:null);
    }


    public function verify(Request $request){
        $payer = Payment::find($request['id']);
        $result = $this->compareAmount($request['val'], $payer);
        return json_decode($result);
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(Request $request)
    {
        try{
            $val = $request->validate([
                'payment' => 'required|string',
                'year' => 'required|string',
                'type' => 'required|integer',
                'amount' => 'nullable|string',
            ]);
            switch ($val['type']) {
                case 4:
                    $result = $this->saveScolarity($val['payment'], $val['amount'], $val['year']);
                    break;
                case 3:
                    $result = $this->saveAnnexFee($val['payment']);
                    break;
                case 2:
                    $result = $this->saveCantine($request);
                    break;
                case 1:
                    $result = $this->saveTransport($request);
                    break;
                default:
                    $result = ['str' => 'danger','msg' => 'Une erreur est survenue !'];
            }
            return back()->with([
                'str' => $result['str'],
                'msg' => $result['msg']
            ]);
        } 
        catch (\Exception $e) {
            return back()->with([
                'str' => 'danger',
                'msg' => 'Une erreur est survenue !'
            ]);
        }
    }

    /**
     * Display the specified resource.
     */
    public function show(string $id)
    {
        try{
            $payment = Payment::where('id', $id)->where('school_id', auth()->user()->school_id)->first();
            $bus = PaymentTransport::where('payment_id', $payment['id'])->first();
            $canteen = PaymentCanteen::where('payment_id', $payment['id'])->first();
            return view('pages.payment.detail',[
                'annee' => $this->yearActif(),
                'payment' => $payment,
                'infoBus' => VerifyBox(auth()->user()->school->setting, 'transport') ? $bus:null,
                'canteen' => VerifyBox(auth()->user()->school->setting, 'canteen') ? $canteen:null,
                'transports' => VerifyBox(auth()->user()->school->setting, 'transport') ? $this->getTransport($payment['type']):null
            ]);
        }
        catch (\Exception $e) {
            return back()->with([
                'str' => 'danger',
                'msg' => 'Une erreur est survenue !'
            ]);
        }
    }

    /**
     * Show the form for editing the specified resource.
     */
    public function detail()
    {
        try{
            $setting = Setting::where('school_id', auth()->user()->school_id)->first();
            return view('pages.payment.show',[
                'datas' => $this->typeEnseignement($setting),
                'payerScolarity' => $this->payerScolarity(),
                'scolarity' => $this->payerScolarityPourCent(),
                'payerFeeAnnex' => $this->payerFeeAnnex(),
                'annexFee' => $this->payerFeeAnnexPourCent(),
                'transport' => VerifyBox(auth()->user()->school->setting, 'transport') ? $this->payerTransport():null,
                'canteen' => VerifyBox(auth()->user()->school->setting, 'canteen') ? $this->payerCanteen():null,
            ]);
        }
        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 $id)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy(string $id)
    {
        //
    }


    /**
     * Update the specified resource in storage.
     */
    public function search(Request $request)
    {
        try{
            $val = $request->validate([
                'type' => 'required|string',
                'year' => 'required|string'
            ]);
            $vals = Canteen::where($val['type'], '1')->where('school_id', auth()->user()->school_id)->where('school_year_id', $val['year'])->first();
            return $vals ? (int)$vals->amount->montant:null;
        }
        catch (\Exception $e) {
            return back()->with([
                'str' => 'danger',
                'msg' => 'Une erreur est survenue.'
            ]);
        }
    }

    /**
     * Remove 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' => $this->getAmountLevel(verifyGetId($dts->school->typeEnseignements, 1, 2) == 1 ? Level::where('type_enseignement_id', $item['id'])->where('status', '1')->get():Level::where('type_enseignement_id', 1)->orWhere('type_enseignement_id', 2)->where('status', '1')->get())
                ];$primaire++;
            }
            elseif(!$cycle && ($item['id'] == 3 || $item['id'] == 4)){
                $tab[] = [
                    'nbre' => $i+=1,
                    'tab' => $data[$i], 
                    'libelle' => verifySeconde($dts->school->typeEnseignements),
                    'data' => $this->getAmountLevel(verifyGetId($dts->school->typeEnseignements, 3, 4) == 1 ? Level::where('type_enseignement_id', $item['id'])->where('status', '1')->get():Level::where('type_enseignement_id', '3')->orWhere('type_enseignement_id', '4')->where('status', '1')->get())
                ]; $cycle++;
            }
            elseif($item['id'] == 5){
                $val = $item['type_enseignement'];
                $tab[] =[
                    'nbre' => $i+=1, 
                    'tab' => $data[$i], 
                    'libelle' => $val,
                    'data' => $this->getAmountLevel(Level::where('type_enseignement_id', $item['id'] == 5 ? '4':$item['id'])->where('status', '1')->get())
                ];
            }
            elseif($item['id'] == 6){
                $val = $item['type_enseignement'];
                $tab[] =[
                    'nbre' => $i+=1, 
                    'tab' => $data[$i], 
                    'libelle' => $val,
                    'data' => $this->getAmountLevel($dts->school->levels)
                ];
            }
        }
        return $tab;
    }



    protected function getAmountLevel($datas)
    {
        $table = [];
        foreach($datas as $item){
            $table[] = [
                'libelle' => ucwords($item->level),
                'totalS' => $this->getTotalScolarity($item->id),
                'payerS' => $this->getTotalPayerScolarity($item->id),
                'totalF' => $this->getTotalFeesAnnex($item->id),
                'payerF' => $this->countTotalFeesAnnex($item->id),
                'effectif' => $this->countEffectif($item->id),
                'transport' => $this->getTotalTransport($item->id),
                'canteen' => $this->getTotalCanteen($item->id)
            ];
        }
        return $table;
    }


    protected function countEffectif($level)
    {
        $totals = Payment::join('inscriptions', 'inscriptions.id', '=', 'payments.inscription_id')
        ->join('scolarities', 'scolarities.id', '=', 'payments.scolaritie_id')
        ->join('amounts', 'amounts.id', '=', 'scolarities.amount_id')
        ->where('inscriptions.level_id', $level)->where('inscriptions.school_year_id', $this->yearActif()->id)
        ->select('amounts.montant')->count();
        return $totals;
    }



    protected function getTotalScolarity($level)
    {
        $totals = Payment::join('inscriptions', 'inscriptions.id', '=', 'payments.inscription_id')
        ->join('scolarities', 'scolarities.id', '=', 'payments.scolaritie_id')
        ->join('amounts', 'amounts.id', '=', 'scolarities.amount_id')
        ->where('inscriptions.level_id', $level)->where('inscriptions.school_year_id', $this->yearActif()->id)
        ->select('amounts.montant')->get();
        $mnt = collect($totals)->sum('montant');
        return $mnt ?? '00';
    }


    protected function getTotalPayerScolarity($level)
    {
        $payer = Payment::join('inscriptions', 'inscriptions.id', '=', 'payments.inscription_id')
        ->join('payment_scolarities', 'payments.id', '=', 'payment_scolarities.payment_id')
        ->where('inscriptions.level_id', $level)->where('inscriptions.school_year_id', $this->yearActif()->id)
        ->select('payment_scolarities.amount')->get();
        $mnt = collect($payer)->sum('amount');
        return $mnt ?? '00';
    }


    protected function getTotalFeesAnnex($level)
    {
        $totals = Payment::join('inscriptions', 'inscriptions.id', '=', 'payments.inscription_id')
        ->join('annex_fees', 'annex_fees.id', '=', 'payments.annex_fee_id')
        ->join('amounts', 'amounts.id', '=', 'annex_fees.amount_id')
        ->where('inscriptions.level_id', $level)->where('inscriptions.school_year_id', $this->yearActif()->id)
        ->select('amounts.montant')->get();
        $mnt = collect($totals)->sum('montant');
        return $mnt ?? '00';
    }


    protected function getTotalTransport($level)
    {
        $totals = PaymentTransport::join('payments', 'payments.id', '=', 'payment_transports.payment_id')
        ->join('inscriptions', 'inscriptions.id', '=', 'payments.inscription_id')
        ->where('inscriptions.level_id', $level)->where('inscriptions.school_year_id', $this->yearActif()->id)
        ->select('payment_transports.payer')->get();
        $mnt = collect($totals)->sum('payer');
        return $mnt ?? '00';
    }



    protected function getTotalCanteen($level)
    {
        $totals = PaymentCanteen::join('payments', 'payments.id', '=', 'payment_canteens.payment_id')
        ->join('inscriptions', 'inscriptions.id', '=', 'payments.inscription_id')
        ->where('inscriptions.level_id', $level)->where('inscriptions.school_year_id', $this->yearActif()->id)
        ->select('payment_canteens.montant')->get();
        $mnt = collect($totals)->sum('montant');
        return $mnt ?? '00';
    }



    protected function countTotalFeesAnnex($level)
    {
        $count = Payment::join('inscriptions', 'inscriptions.id', '=', 'payments.inscription_id')
        ->join('scolarity_fees', 'payments.id', '=', 'scolarity_fees.payment_id')
        ->where('inscriptions.level_id', $level)->where('inscriptions.school_year_id', $this->yearActif()->id)->count();
        if($count){
            $val = Payment::join('inscriptions', 'inscriptions.id', '=', 'payments.inscription_id')
            ->join('annex_fees', 'annex_fees.id', '=', 'payments.annex_fee_id')
            ->join('amounts', 'amounts.id', '=', 'annex_fees.amount_id')
            ->where('inscriptions.level_id', $level)->where('inscriptions.school_year_id', $this->yearActif()->id)
            ->select('amounts.montant')->first();
        }
        return $count ? $count * $val['montant']:0;
    }



    protected function payerScolarity()
    {
        $payer = Payment::join('payment_scolarities', 'payments.id', '=', 'payment_scolarities.payment_id')
        ->where('payments.school_id', auth()->user()->school_id)->where('payments.school_year_id', $this->yearActif()->id)
        ->select('payment_scolarities.amount')->get();
        $mnt = collect($payer)->sum('amount');
        return $mnt ?? '00';
    }


    protected function payerFeeAnnex()
    {
        $totals = Payment::join('scolarity_fees', 'payments.id', '=', 'scolarity_fees.payment_id')
        ->join('annex_fees', 'annex_fees.id', '=', 'payments.annex_fee_id')
        ->join('amounts', 'amounts.id', '=', 'annex_fees.amount_id')
        ->where('payments.school_id', auth()->user()->school_id)
        ->where('payments.school_year_id', $this->yearActif()->id)
        ->select('amounts.montant')->get();
        $mnt = collect($totals)->sum('montant');
        return $mnt ?? '00';
    }


    protected function payerTransport()
    {
        $totals = PaymentTransport::join('payments', 'payments.id', '=', 'payment_transports.payment_id')
        ->where('payments.school_id', auth()->user()->school_id)
        ->where('payments.school_year_id', $this->yearActif()->id)
        ->select('payment_transports.payer')->get();
        $mnt = collect($totals)->sum('payer');
        return $mnt ?? '00';
    }



    protected function payerCanteen()
    {
        $totals = PaymentCanteen::join('payments', 'payments.id', '=', 'payment_canteens.payment_id')
        ->where('payments.school_id', auth()->user()->school_id)
        ->where('payments.school_year_id', $this->yearActif()->id)
        ->select('payment_canteens.montant')->get();
        $mnt = collect($totals)->sum('montant');
        return $mnt ?? '00';
    }


    protected function payerScolarityPourCent()
    {
        $totals = Payment::join('inscriptions', 'inscriptions.id', '=', 'payments.inscription_id')
        ->join('scolarities', 'scolarities.id', '=', 'payments.scolaritie_id')
        ->join('amounts', 'amounts.id', '=', 'scolarities.amount_id')
        ->where('payments.school_id', auth()->user()->school_id)
        ->where('payments.school_year_id', $this->yearActif()->id)
        ->select('amounts.montant')->get();
        $mnt = collect($totals)->sum('montant');
        $payer = $this->payerScolarity();
        $vals = $payer ? round(($payer/$mnt)*100):0;
        return $vals ? ($vals < 10 ? '0'.$vals:$vals):$vals;
    }



    protected function payerFeeAnnexPourCent()
    {
        $totals = Payment::join('annex_fees', 'annex_fees.id', '=', 'payments.annex_fee_id')
        ->join('amounts', 'amounts.id', '=', 'annex_fees.amount_id')
        ->where('payments.school_id', auth()->user()->school_id)
        ->where('payments.school_year_id', $this->yearActif()->id)
        ->select('amounts.montant')->get();
        $mnt = collect($totals)->sum('montant');
        $payer = $this->payerFeeAnnex();
        $vals = $payer ? round(($payer/$mnt)*100):0;
        return $vals ? ($vals < 10 ? '0'.$vals:$vals):$vals;
    }


    protected function saveScolarity($item, $amount, $year){
        $payment = Payment::where('id', $item)->where('school_id', auth()->user()->school_id)->first();
        if($this->compareAmount($amount, $payment)){
            PaymentScolarity::create([
                'payment_id' => $item,
                'user_id' => auth()->user()->id,
                'amount' => str_replace(' ', '', $amount)
            ]);
            if(!$this->resteApayer($amount, $payment)){
                Payment::where('id',  $item)->update(['status' => '1']);
            }
            $str = 'success';
            $msg = 'Payement effectué scolarité.';
        }
        else{
            $str = 'info';
            $msg = 'Le montant saisait est très élévé !';
        }
        return ['str' => $str, 'msg' => $msg];
    }



    protected function getScolarityTotalDay()
    {
        $totals = PaymentScolarity::join('payments', 'payments.id', '=', 'payment_scolarities.payment_id')
        ->join('scolarities', 'scolarities.id', '=', 'payments.scolaritie_id')
        ->where('payment_scolarities.user_id', auth()->user()->id)
        ->where('payments.school_id', auth()->user()->school_id)
        ->where('payments.school_year_id', $this->yearActif()->id)
        ->whereDate('payment_scolarities.created_at', now()->toDateString())
        ->select('payment_scolarities.amount')->get();
        $mnt = collect($totals)->sum('amount');
        return $mnt ?? '0';
    }



    protected function getAnnexFeeTotalDay()
    {
        $totals = ScolarityFee::join('payments', 'payments.id', '=', 'scolarity_fees.payment_id')
        ->join('annex_fees', 'annex_fees.id', '=', 'payments.annex_fee_id')
        ->join('amounts', 'amounts.id', '=', 'annex_fees.amount_id')
        ->where('scolarity_fees.user_id', auth()->user()->id)
        ->where('payments.school_id', auth()->user()->school_id)
        ->where('payments.school_year_id', $this->yearActif()->id)
        ->whereDate('scolarity_fees.created_at', now()->toDateString())
        ->select('amounts.montant')->get();
        $mnt = collect($totals)->sum('montant');
        return $mnt ?? '0';
    }



    protected function transportBusTotalDay()
    {
        $totals = PaymentTransport::join('payments', 'payments.id', '=', 'payment_transports.payment_id')
        ->where('payment_transports.user_id', auth()->user()->id)
        ->where('payments.school_id', auth()->user()->school_id)
        ->where('payments.school_year_id', $this->yearActif()->id)
        ->whereDate('payment_transports.created_at', now()->toDateString())
        ->select('payment_transports.payer')->get();
        $mnt = collect($totals)->sum('payer');
        return $mnt ?? '0';
    }



    protected function cantineTotalDay()
    {
        $totals = PaymentCanteen::where('user_id', auth()->user()->id)
        ->where('school_id', auth()->user()->school_id)
        ->where('school_year_id', $this->yearActif()->id)
        ->whereDate('created_at', now()->toDateString())->get();
        $mnt = collect($totals)->sum('montant');
        return $mnt ?? '0';
    }


    protected function saveAnnexFee($payment){
        $verify = ScolarityFee::where('payment_id', $payment)->where('status', '1')->count();
        if(!$verify){
            ScolarityFee::create(['payment_id' => $payment, 'user_id' => auth()->user()->id]);
            $str = 'success';
            $msg = 'Payement effectué frais annexe.';
        }
        else{
            $str = 'info';
            $msg = 'Payement déjà effetué frais annexe !';
        }
        return ['str' => $str, 'msg' => $msg];
    }


    protected function saveTransport($data){
       $verify = PaymentTransport::where('payment_id', $data['payment'])->first();
        if($verify){
            $verify->update([
                'payer' => $verify['payer']+$data['amount'],
                'tours' => $data['tours'],
                'trim_1' => $data['trim_1'] ? '1':'0',
                'trim_2' => $data['trim_2'] ? '1':'0',
                'trim_3' => $data['trim_3'] ? '1':'0',
                'semest_1' => $data['semest_1'] ? '1':'0',
                'semest_2' => $data['semest_1'] ? '1':'0'
            ]);
        }
        else{
            PaymentTransport::create([
                'payer' => $data['amount'],
                'tours' => $data['tours'],
                'trim_1' => $data['trim_1'] ? '1':'0',
                'trim_2' => $data['trim_2'] ? '1':'0',
                'trim_3' => $data['trim_3'] ? '1':'0',
                'semest_1' => $data['semest_1'] ? '1':'0',
                'semest_2' => $data['semest_1'] ? '1':'0',
                'user_id' => auth()->user()->id,
                'payment_id' => $data['payment'],
                'transport_id' => explode('_', $data['bus'])[0]
            ]);
        }
        return ['str' => 'info', 'msg' => 'Payement effetué bus !']; 
    }


    protected function saveCantine($data){
        $verify = PaymentCanteen::where('payment_id', $data['payment'])->first();
        $date = $this->valueDay((int)$data['number'], $data['delai']);
        if(!$verify){
            PaymentCanteen::create([
                'montant' => $data['amount'],
                'number' => $data['number'],
                'debut' => $date['debut'],
                'fin' => $date['fin'],
                'statut' => $date['status'] ? '2':'1',
                'user_id' => auth()->user()->id,
                'school_id' => auth()->user()->school_id,
                'payment_id' => $data['payment'],
                'school_year_id' => $data['year']
            ]);
            $str = 'info';
            $msg = 'Payement effetué Cantine !';
        }
        else{
            $number = $verify['number']+$data['number'];
            $number <= 10 ? // Sur 10 mois pour une année scolaire ....
            $verify->update([
                'montant' => $verify['amount']+$data['amount'],
                'number' => $verify['number']+$data['number'],
                'debut' => $date['debut'],
                'fin' => $date['fin'],
                'statut' => $date['status'] ? '2':'1', 
            ]):
            null;
            $str = $number <= 10 ? 'info':'warning';
            $msg = $number <= 10 ? 'Payement déjà effetué Cantine !':'Nombre de mois restant est peu par rapport à celui saisi !';
        }
        return ['str' => $str, 'msg' => $msg]; 
    }


    protected function compareAmount($montant, $val){
        $mntnt = str_replace(' ', '', $montant);
        $exist = $val->scolaritie->amount->montant - collect($val->payment_scolarities)->sum('amount');
        return ($exist >= $mntnt) ? true:false;
    }


    protected function resteApayer($montant, $val){
        $mntnt = str_replace(' ', '', $montant);
        $result = $val->scolaritie->amount->montant - (collect($val->payment_scolarities)->sum('amount') + $mntnt);
        return $result;
    }


    protected function getTransport($type){
        $data = Transport::join('school_zones', 'school_zones.id', '=', 'transports.school_zone_id')
        ->join('zones', 'zones.id', '=', 'school_zones.zone_id')
        ->join('amounts', 'amounts.id', '=', 'transports.amount_id')
        ->where('transports.type', $type)
        ->where('school_zones.school_id', auth()->user()->school_id)
        ->where('transports.school_year_id', $this->yearActif()->id)
        ->select('transports.id', 'transports.libelle', 'zones.libelle as zone', 'amounts.montant')
        ->get();
        return $data;
    }


    protected function valueDay($number, $status = null){

        if($status){ // A partir du mois actuel $debut .....
            $debut = Carbon::now();
            $end = Carbon::now()->addMonth($number-1);
            $status = true;
        }
        else{ // A partir du mois prochain $debut .......
            $debut = Carbon::now()->addMonth();
            $end = $debut->copy()->addMonths($number-1);
            $status = false;
        }
        return ['status' => $status, 'debut' => $debut->translatedFormat('F Y'), 'fin' => $end->translatedFormat('F Y')];
    }

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