<?php

namespace App\Services\Reports;

use App\AkruNetPecahan;
use App\Cawangan;
use App\CawanganDetail;
use App\Lelong;
use App\Gadai;
use App\StokAudit1;
use App\StokAudit10;
use App\StokAudit11;
use App\StokAudit12;
use App\StokAudit2;
use App\StokAudit3;
use App\StokAudit4;
use App\StokAudit5;
use App\StokAudit6;
use App\StokAudit7;
use App\StokAudit8;
use App\StokAudit9;
use App\TransaksiKeuntungan;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use App\Support\v2\Calculation as V2Calculation;
use Carbon\Carbon;
use Exception;

class OnePercentService
{

    // `B` stands for balance sheet and `L` stands for Ledger
    private $kod_cawangan;
    private $cawangan;
    public function __construct($kod_cawangan){
        $this->kod_cawangan = $kod_cawangan;
        $this->cawangan = Cawangan::where('kodcaw',$kod_cawangan)->first();
    }


    public function getTotalRounded($type='B',$start = '2023-12-14',$end = '2023-12-14'){
        if($type == 'B'){
            $rounded = TransaksiKeuntungan::on('mysql7')
            ->leftJoin('transaction as trans', function($join)
            {
                    $join->on('trans.norujukan', '=', 'transaksi_keuntungan.norujukan');
                    $join->on('trans.created_at', '=', 'transaksi_keuntungan.tarikh_bayaran');
            })
            ->where('trans.trans_type','T')
            ->sum('transaksi_keuntungan.rounded');

        }else if($type == 'L'){
            $rounded = TransaksiKeuntungan::on('mysql7')
                ->whereDate('tarikh_bayaran','>=',$start)
                ->whereDate('tarikh_bayaran','<=',$end)
                ->sum('rounded');;
        }

        return $rounded;

    }

    public function getTotalKeuntungan($type = 'B',$start = '2023-12-14',$end = '2023-12-14') : Float{
        if($type == 'B'){
            if($start == null){
                $akrual = Gadai::on($this->cawangan['mysql'])->where([['sttebus',''],['tagbaru',1]])->sum('tunggakanonepercent');
                $norujukan = Gadai::on($this->cawangan['mysql'])->where('sttebus','T')->where('tagbaru',1)->pluck('norujukan');

                $keuntungan = TransaksiKeuntungan::on('mysql7')
                ->whereIn('norujukan',$norujukan)
                ->sum('onepercent_rebet');

            }else{
                // $akrual = Gadai::on($this->cawangan['mysql'])
                //         ->where([['tagpalsu','=',0],['t_gadai','<=',$start],['sttebus','=',''],['tagbaru',1]])
                //         ->orWhere([['tagbaru',1],['tagpalsu','=',0],['t_update','>',$start],['sttebus','!=',''],['t_gadai','<=',$start]])
                //         ->orderBy('t_gadai', 'ASC')
                //         ->orderBy('sirig', 'ASC')
                //         ->get();


                // $keuntungan = $this->calculateTotalProfit($akrual,$start);
                // $keuntungan = $keuntungan['onepercent'];

                $date = new Carbon($start);
                $year = $date->year;
                $month = $date->month;

                $total_akru = AkruNetPecahan::on($this->cawangan['mysql'])
                ->where('tahun','=',$year)
                ->where('bulan','<',$month)
                ->sum('pend_akru_1persen');

                $formData = [
                    'kodcaw' => $this->cawangan['kodcaw'],
                    'tarikh' => $start,
                ];
                
                $request = new Request($formData);
                
                $akru = $this->calculateAccruedIncome($request);

                $keuntungan = $akru['accrual_income_onepercent'];
                $keuntungan += $total_akru;
            }
            return $keuntungan;

        }else if($type == 'L'){
            /* Keuntungan Semasa */
            $keuntungan_semasa = $this->CurrentProfit($start,$end,$this->cawangan['kodcaw']);
            $totalkeuntungan=$keuntungan_semasa['onepercent'];
        }

        return $totalkeuntungan;
    }

    public function getTotalUjrah($type = 'B',$start = '2023-12-14',$end = '2023-12-14') : Float{


        if($type == 'B'){
            // $akrual = Gadai::on($this->cawangan['mysql'])->where([['sttebus',''],['tagbaru',1]])->sum('tunggakanujrah');

            // $norujukan = Gadai::on($this->cawangan['mysql'])->where('sttebus','T')->where('tagbaru',1)->pluck('norujukan');

            // $ujrah = TransaksiKeuntungan::on('mysql7')
            // ->whereIn('norujukan',$norujukan)
            // ->sum('ujrah_rebet');

            if($start == null){
                $akrual = Gadai::on($this->cawangan['mysql'])->where([['sttebus',''],['tagbaru',1]])->sum('tunggakanujrah');
                $norujukan = Gadai::on($this->cawangan['mysql'])->where('sttebus','T')->where('tagbaru',1)->pluck('norujukan');

                $keuntungan = TransaksiKeuntungan::on('mysql7')
                ->whereIn('norujukan',$norujukan)
                ->sum('ujrah_rebet');
            }else{
                // $akrual = Gadai::on($this->cawangan['mysql'])
                //     ->where([['tagpalsu','=',0],['t_gadai','<=',$start],['sttebus','=',''],['tagbaru',1]])
                //     ->orWhere([['tagbaru',1],['tagpalsu','=',0],['t_update','>',$start],['sttebus','!=',''],['t_gadai','<=',$start]])
                //     ->orderBy('t_gadai', 'ASC')
                //     ->orderBy('sirig', 'ASC')
                //     ->get();

                // $keuntungan = $this->calculateTotalProfit($akrual,$start);
                // $keuntungan = $keuntungan['ujrah'];

                $date = new Carbon($start);
                $year = $date->year;
                $month = $date->month;

                $total_akru = AkruNetPecahan::on($this->cawangan['mysql'])
                ->where('tahun','=',$year)
                ->where('bulan','<',$month)
                ->sum('pend_akru_ujrah');

                $formData = [
                    'kodcaw' => $this->cawangan['kodcaw'],
                    'tarikh' => $start,
                ];
                
                $request = new Request($formData);
                
                $akru = $this->calculateAccruedIncome($request);

                $keuntungan = $akru['accrual_income_ujrah'];
                $keuntungan += $total_akru;
            }
            return $keuntungan;

        }else if($type == 'L'){
            /* Keuntungan Semasa */
            $keuntungan_semasa = $this->CurrentProfit($start,$end,$this->cawangan['kodcaw']);
            $totalujrah = $keuntungan_semasa['ujrah'];
        }

        return $totalujrah;
    }

    public function calculateTotalProfit($akrual,$tarikh){
        $chunkSize = 100;
        $summationonepercent = 0;
        $summationujrah = 0;
        $count = 0;
        $summationbkpjm = 0;
        $array_test = [];

        $akrual->chunk($chunkSize)->each(function ($chunk) use(&$array_test,$tarikh,&$summationonepercent,&$summationujrah,&$count,&$summationbkpjm) {
            // Process each chunk of items
            foreach ($chunk as $item) {
                $trans_keun = TransaksiKeuntungan::on('mysql7')->where([['norujukan','=',$item->norujukan],['bayaran_pembiayaan','>=',0]])->whereDate('tarikh_bayaran','<=',$tarikh)->get();
                $calculation = new V2Calculation();

                if($trans_keun->isNotEmpty()){
                    $bakipinjaman = $item->pinjaman;
                    $last_transaction = Carbon::parse($trans_keun->last()->tarikh_bayaran)->toDateString();
                    if($last_transaction > $tarikh){
                        $last_transaction = $tarikh;
                    }

                    $trans_keun->each(function($trans) use(&$bakipinjaman){
                      $bakipinjaman -= $trans['bayaran_pembiayaan'];
                    });
                    $kiraan = $calculation->kiraanKeuntunganRebet($bakipinjaman,$item->nilaimarhun,$item->kadarupah,(($bakipinjaman/$item->nilaimarhun) * 100));
                    $tempoh = $this->kiraanTarikhJBG($item->t_gadai,$tarikh);
                    $tempoh_last_transaction = $this->kiraanTarikhJBG($item->t_gadai,$last_transaction);
                    $tempoh_belum_bayar = $tempoh - $tempoh_last_transaction;
                    $onepercent = $calculation->getRoundedMethod($kiraan['onepercent'] * $tempoh_belum_bayar);
                    $ujrah = $calculation->getRoundedMethod($kiraan['ujrah'] * $tempoh_belum_bayar);
                    $summationonepercent += $onepercent;
                    $summationujrah += $ujrah;
                    $summationbkpjm += $bakipinjaman;
                    array_push($array_test,['norujukan' => $item->norujukan,'ujrah' => $ujrah,'onepercent' => $onepercent,'pinjaman' => $item->pinjaman, 'bakipjm' => $bakipinjaman]);

                }else{
                    $kiraan = $calculation->kiraanKeuntunganRebet($item->pinjaman,$item->nilaimarhun,$item->kadarupah,(($item->pinjaman/$item->nilaimarhun) * 100));
                    $tempoh = $this->kiraanTarikhJBG($item->t_gadai,$tarikh);
                    $onepercent = $calculation->getRoundedMethod($kiraan['onepercent'] * $tempoh);
                    $ujrah = $calculation->getRoundedMethod($kiraan['ujrah'] * $tempoh);
                    $summationonepercent += $onepercent;
                    $summationujrah += $ujrah;
                    $summationbkpjm += $item->pinjaman;

                    array_push($array_test,['norujukan' => $item->norujukan,'ujrah' => $ujrah,'onepercent' => $onepercent,'pinjaman' => $item->pinjaman, 'bakipjm' => $item->pinjaman]);
                }
                $count++;

            }

        });
        // return response()->json($array_test);
        // dd($summationonepercent,$summationujrah,$count,$summationbkpjm,$array_test);
        // dd('test');
        return ['onepercent' => $summationonepercent,'ujrah' => $summationujrah];

    }



    public function getAllCawanganAccruedIncome(Request $request){
        $cawangan = Cawangan::on('mysql7')->where('version','v2')->get();

        $array_cawangan = [];
        foreach($cawangan as $caw){
                $akru = AkruNetPecahan::on($caw['mysql'])->where('tahun',$request->year)->orderBy('bulan')->orderBy('tahun')->get()->toArray();
                for($i=0;$i<=11;$i++){
                        $array_akru = array_filter($akru,function($e) use($i){
                            return ($i+1) == $e['bulan'];
                        });

                        if(!empty($array_akru)){
                            foreach($array_akru as $ak){
                                $array_cawangan[$caw['details_caw']]['ujrah'][$i] = $ak['pend_akru_ujrah'];
                                $array_cawangan[$caw['details_caw']]['onepercent'][$i] = $ak['pend_akru_1persen'];
                            }
                        }
                        else{
                            $array_cawangan[$caw['details_caw']]['ujrah'][$i] = 0;
                            $array_cawangan[$caw['details_caw']]['onepercent'][$i] = 0; 
                        }
                }

        }

        return $array_cawangan;
    }

    public function calculateAccruedIncome(Request $request){
        /* (A) Stok Audit Bulan Sekarang | (B) Stok Audit Bulan Sebelum | (C) Keuntungan Bayaran Semasa Pecahan | (D) = (B) - (C) | (E) = (A) - (D)  */
        $cawangan = Cawangan::on('mysql7')->where('kodcaw','=',$request->kodcaw)->first();

        $date = new Carbon($request->tarikh);
        $date_sebelum = clone $date;

        $date_sebelum = $date_sebelum->firstOfMonth(); 
        $month_sebelum = $date_sebelum->subMonth()->format('m');

        $month_sekarang = $date->format('m');
        $year_generate = $date->format('Y');

        /* generate for month */
        $first_month_current = new Carbon($request->tarikh);
        $first_month_current = $first_month_current->firstOfMonth();
        $last_month_current = new Carbon($request->tarikh);
        $last_month_current = $last_month_current->lastOfMonth();

        /* A */
        if($date->isToday()){
            $audit_now = Gadai::on($cawangan['mysql'])
            ->where([['tagpalsu','=',0],['t_gadai','<=',$request->tarikh],['sttebus','=','']])
            ->orWhere([['tagpalsu','=',0],['t_update','>',$request->tarikh],['sttebus','!=',''],['t_gadai','<=',$request->tarikh]])
            ->orderBy('t_gadai', 'ASC')
            ->orderBy('sirig', 'ASC');

            $onepercent_current = $audit_now->sum('tunggakanonepercent');
            $ujrah_current = $audit_now->sum('tunggakanujrah');
        }else{
            $result_audit_current = $this->StokAuditGenerateTerakru($month_sekarang,$cawangan,$year_generate);
            $onepercent_current = $result_audit_current->sum('utgonepercent');
            $ujrah_current = $result_audit_current->sum('ujrah');
        }
        /* B */
        $year_sebelum = $date_sebelum->format('Y');
        $year_publish = ($month_sekarang == 1) ? $year_sebelum : $year_generate;
        $result_audit_previous = $this->StokAuditGenerateTerakru($month_sebelum,$cawangan,$year_publish);
        $onepercent_previous = $result_audit_previous->sum('utgonepercent');
        $ujrah_previous = $result_audit_previous->sum('ujrah');

        /* C */
        $keuntungan_semasa = $this->CurrentProfit($first_month_current->toDateString(),$last_month_current->toDateString(),$request->kodcaw);

        /* D & E */
        $accrual_income_onepercent = $onepercent_current - ($onepercent_previous - $keuntungan_semasa['onepercent']);
        $accrual_income_ujrah = $ujrah_current - ($ujrah_previous - $keuntungan_semasa['ujrah']);

        $available_akru = AkruNetPecahan::on($cawangan['mysql'])
        ->where('bulan', (int)$month_sekarang)
        ->where('tahun', $year_generate)
        ->get()->toArray();
        
        if(sizeof($available_akru) == 0)
        {
            $akrunet = new AkruNetPecahan();
            $akrunet->setConnection($cawangan['mysql']);
            $akrunet->tahun = $year_generate;
            $akrunet->bulan = (int)$month_sekarang;
            $akrunet->persen_semasa = $onepercent_current;
            $akrunet->ujrah_semasa = $ujrah_current;
            $akrunet->persen_sebelum = $onepercent_previous;
            $akrunet->ujrah_sebelum = $ujrah_previous;
            $akrunet->keuntungan_semasa_1persen = $keuntungan_semasa['onepercent'];
            $akrunet->keuntungan_semasa_ujrah = $keuntungan_semasa['ujrah'];
            $akrunet->baki_keun_blm_byr_1persen = ($onepercent_previous - $keuntungan_semasa['onepercent']);
            $akrunet->baki_keun_blm_byr_ujrah = ($ujrah_previous - $keuntungan_semasa['ujrah']);
            $akrunet->pend_akru_1persen = $accrual_income_onepercent;
            $akrunet->pend_akru_ujrah = $accrual_income_ujrah;
            $akrunet->save();
        }else{
            if($available_akru[0]['pend_akru_1persen'] !== $accrual_income_onepercent){
                AkruNetPecahan::on($cawangan['mysql'])
                ->where('bulan','=',(int)$month_sekarang)
                ->where('tahun',$year_generate)
                ->update([
                    'persen_semasa' => $onepercent_current,
                    'ujrah_semasa' => $ujrah_current,
                    'persen_sebelum' => $onepercent_previous,
                    'ujrah_sebelum' => $ujrah_previous,
                    'keuntungan_semasa_1persen' => $keuntungan_semasa['onepercent'],
                    'keuntungan_semasa_ujrah' => $keuntungan_semasa['ujrah'],
                    'baki_keun_blm_byr_1persen' => ($onepercent_previous - $keuntungan_semasa['onepercent']),
                    'baki_keun_blm_byr_ujrah' => ($ujrah_previous - $keuntungan_semasa['ujrah']),
                    'pend_akru_1persen' => $accrual_income_onepercent,
                    'pend_akru_ujrah' => $accrual_income_ujrah,
                ]);
            }
        }


        $array_result = ['onepercent_current' => $onepercent_current,'ujrah_current' => $ujrah_current,
                        'onepercent_previous' => $onepercent_previous,'ujrah_previous' => $ujrah_previous,
                        'current_profit' => $keuntungan_semasa, 'accrual_income_onepercent' => $accrual_income_onepercent,
                        'accrual_income_ujrah' => $accrual_income_ujrah];

        return $array_result;
        
    }

    public function CurrentProfit($start,$end,$kodcaw){

        $start = new Carbon($start);
        $year = $start->format('Y');

        $cawangan = Cawangan::on('mysql7')->where('kodcaw','=',$kodcaw)->first();

        $collection_trans = TransaksiKeuntungan::on('mysql7')
                ->leftJoin('transaction as trans', function($join)
                {
                    $join->on('transaksi_keuntungan.norujukan', '=', 'trans.norujukan');
                    $join->on('transaksi_keuntungan.tarikh_bayaran', '=', 'trans.created_at');
                })
                ->where('trans.kodcaw','=',$kodcaw)
                ->whereDate('transaksi_keuntungan.tarikh_bayaran' ,'<=', $end)
                ->whereDate('transaksi_keuntungan.tarikh_bayaran' ,'>=', $start)
                ->whereYear('transaksi_keuntungan.tarikh_bayaran','=',$year)
                ->get();

        $array_norujukan = $collection_trans->pluck('norujukan')->toArray();

        $collection_gadai = Gadai::on($cawangan['mysql'])->whereIn('norujukan',$array_norujukan)->get();

        /* filtering untuk gadai yang ditebus pada bukan bulan yang sama */
        $keuntungan_semasa_collection = $collection_trans->filter(function ($trans) use ($collection_gadai) {
            
            foreach ($collection_gadai as $gadai) {
                if($gadai->norujukan === $trans->norujukan){
                    $t_gadai = Carbon::parse($gadai->t_gadai);
                    $t_bayaran = Carbon::parse($trans->tarikh_bayaran);
                    
                    if ($t_gadai->month === $t_bayaran->month && $t_gadai->year === $t_bayaran->year) {
                        return false;
                    }else{
                        return true;
                    }
                }
            }
            return false;
        });


        $ujrah = $this->filterCollection($keuntungan_semasa_collection,'A','ujrah');
        $onepercent = $this->filterCollection($keuntungan_semasa_collection,'A','onepercent');
        $ujrah_rebet = $this->filterCollection($keuntungan_semasa_collection,'T','ujrah_rebet');
        $onepercent_rebet = $this->filterCollection($keuntungan_semasa_collection,'T','onepercent_rebet');

        $upahlelong = Lelong::on($cawangan['mysql'])
        ->selectRaw('SUM(ujrah) as ujrah,SUM(onepercent) as onepercent')
        ->where([['tagujrah','=',1],['t_jual','>=',$start],['t_jual','<=',$end]])
        ->whereYear('t_jual','=',$year)
        ->get()->toArray();

        $ujrah_lelong = (empty($upahlelong)) ? 0 : $upahlelong[0]['ujrah'];
        $onepercent_lelong = (empty($upahlelong)) ? 0 : $upahlelong[0]['onepercent'];

        $total_onepercent = $onepercent + $onepercent_rebet + $onepercent_lelong;
        $total_ujrah = $ujrah + $ujrah_rebet + $ujrah_lelong;

        return ['ujrah' => $total_ujrah,'onepercent' => $total_onepercent];
    }

    private function kiraanTarikhJBG($tarikhgadai,$tarikh){
        $tarikh_gadai = Carbon::parse($tarikhgadai. ' 00:00:00');
        $tarikh = new Carbon($tarikh);
        $tahun_gadai = $tarikh_gadai->year;
        $bulan_gadai = $tarikh_gadai->month;
        $hari_gadai = $tarikh_gadai->day;
        $tahun_semasa = $tarikh->year;
        $bulan_semasa = $tarikh->month;
        $hari_semasa = $tarikh->day;
        if($hari_semasa >= $hari_gadai){
            $beza_hari = $hari_semasa - $hari_gadai + 1;
        }else if($hari_semasa < $hari_gadai){
            $bulan_semasa = $bulan_semasa - 1;
            $beza_hari = ($hari_semasa + 30) - $hari_gadai + 1;
        }
        $extensivemonth_gadai = 0;
        if($beza_hari >= 1 && $beza_hari <= 15){
            $extensivemonth_gadai = 0.5;
        }else if($beza_hari >= 16){
            $extensivemonth_gadai = 1;
        }else{
            $extensivemonth_gadai = 0;
        }
        $beza_tahun = $tahun_semasa - $tahun_gadai;
        $beza_bulan = ($bulan_semasa + ($beza_tahun * 12)) - $bulan_gadai;
        $tempoh_gadai = $beza_bulan + $extensivemonth_gadai;

        return $tempoh_gadai;
    }

    private function StokAuditGenerateTerakru($Month = null, $cawangan = [], $year_generate = null) : Object{
        switch($Month){
            case '01': return StokAudit1::on($cawangan['mysql'])->where('tahun',$year_generate);
                        break;
            case '02': return StokAudit2::on($cawangan['mysql'])->where('tahun',$year_generate);
                        break;
            case '03': return StokAudit3::on($cawangan['mysql'])->where('tahun',$year_generate);
                        break;
            case '04': return StokAudit4::on($cawangan['mysql'])->where('tahun',$year_generate);
                        break;
            case '05': return StokAudit5::on($cawangan['mysql'])->where('tahun',$year_generate);
                        break;
            case '06': return StokAudit6::on($cawangan['mysql'])->where('tahun',$year_generate);
                        break;
            case '07': return StokAudit7::on($cawangan['mysql'])->where('tahun',$year_generate);
                        break;
            case '08': return StokAudit8::on($cawangan['mysql'])->where('tahun',$year_generate);
                        break;
            case '09': return StokAudit9::on($cawangan['mysql'])->where('tahun',$year_generate);
                        break;
            case '10': return StokAudit10::on($cawangan['mysql'])->where('tahun',$year_generate);
                        break;
            case '11': return StokAudit11::on($cawangan['mysql'])->where('tahun',$year_generate);
                        break;
            case '12': return StokAudit12::on($cawangan['mysql'])->where('tahun',$year_generate);
                        break;                               
        }
    }

    private function filterCollection($collection,$type,$sumtype) : Float{

        $array_type = ['T','S','P','AT'];
        return $collection->filter(function ($item) use($type,$array_type) {
            if($type == 'T')
                return in_array($item->trans_type, $array_type);

            return $item->trans_type === $type;
        })->sum($sumtype);
    }


}
