<?php

namespace App\Services\CashFlow;

use App\AddTunai;
use App\Audit;
use App\Cawangan;
use App\Denominasi;
use App\DenoPanjar;
use App\Panjar;
use App\RequestTeller;
use App\Tunai;
use App\Vault;
use Carbon\Carbon;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class TellerServices
{
    protected $cawangan;

    public function __construct($kodcaw){
        $this->cawangan = $kodcaw;
    }

    private function CheckTunai(Request $request){
        $cawangan = Cawangan::on('mysql7')->where('kodcaw','=',$this->cawangan)->first();
        $current = Carbon::now();
        $current = new Carbon();

        try{
            /* Checking Status Data include Tunai */
            $tunai = Tunai::on($cawangan['mysql'])
            ->where([['kodcaw','=',$this->cawangan],['tarikh','=',$current->toDateString()],['kodlaluan','=',$request->teller]]);
            $tunai = optional($tunai->first())->toArray();

            if(empty($tunai)){
                // Create transaction of cash in teller
                $tunai = Tunai::on($cawangan['mysql'])->create([
                    'tarikh' => $current->toDateString(),
                    'kodcaw'=> $this->cawangan,
                    'kodlaluan'=>$request->teller,
                    'bakiawal'=>$request->bakiawal,
                    'masuk'=>$request->masuk,
                    'yuran'=>$request->yuran,
                    'keluar'=>$request->keluar,
                    'baki'=>$request->baki,
                    'tambah'=>$request->amt,
                    'kurang'=>$request->kurang
                ]);
            }

        } catch (\Exception $e) {
            DB::connection($cawangan['mysql'])->rollBack();
        
            // Handle the exception or re-throw
            throw $e;
        }

    }

    private function checkAddTunai(Request $request){
        $cawangan = Cawangan::on('mysql7')->where('kodcaw','=',$this->cawangan)->first();
        $current = Carbon::now();
        $current = new Carbon();

        /* Checking AddTunai */
            
        //Same Note e.g P1 and S1
        $same_note = AddTunai::on($cawangan['mysql'])
        ->where('kodlaluan', $request->teller)
        ->where('nota',$request->nota)
        ->where('tarikh',$current->toDateString())->first();

        if($same_note){
            //Throw this
            Log::error('Error: same-note :' . $this->cawangan . ': Name :' . $request->teller);
            return 'same-note';
        }

        //Time Interval
        $latestRecord = AddTunai::on($cawangan['mysql'])->where('kodlaluan', $request->teller)->latest()->first();
        if($latestRecord){
            $time = Carbon::parse($latestRecord->created_at);
            $time_end = $time->copy()->addMinutes(1);

            if($current->between($time,$time_end)){
                //Throw this
                Log::error('Error: within 1 minute :' . $this->cawangan . ': Name :' . $request->teller);
                return 'within 1 minute';
            }
        }

        return 'success';
    }

    private function getDenoTotal(Request $request,$operator){
        $cawangan = Cawangan::on('mysql7')->where('kodcaw','=',$this->cawangan)->first();
        $current = Carbon::now();
        $current = new Carbon();

        $deno = Denominasi::on($cawangan['mysql'])->where('tarikh','=',$current->toDateString());
        $deno = optional($deno->first())->toArray();

        if(empty($deno)){
            return "empty";
            Log::error("Empty Denominasi Data");
        }

        $deno['txtsen1'] += ($operator == 'add') ? intval($request->ambilansen1) : -intval($request->ambilansen1);
        $deno['txtsen5'] += ($operator == 'add') ? intval($request->ambilansen5) : -intval($request->ambilansen5);
        $deno['txtsen10'] += ($operator == 'add') ? intval($request->ambilansen10) : -intval($request->ambilansen10);
        $deno['txtsen20'] += ($operator == 'add') ? intval($request->ambilansen20) : -intval($request->ambilansen20);
        $deno['txtsen50'] += ($operator == 'add') ? intval($request->ambilansen50) : -intval($request->ambilansen50);

        $deno['txtring1'] += ($operator == 'add') ? intval($request->ambilanring1) : -intval($request->ambilanring1);
        $deno['txtring5'] += ($operator == 'add') ? intval($request->ambilanring5) : -intval($request->ambilanring5);
        $deno['txtring10'] += ($operator == 'add') ? intval($request->ambilanring10) : -intval($request->ambilanring10);
        $deno['txtring20'] += ($operator == 'add') ? intval($request->ambilanring20) : -intval($request->ambilanring20);
        $deno['txtring50'] += ($operator == 'add') ? intval($request->ambilanring50) : -intval($request->ambilanring50);
        $deno['txtring100'] += ($operator == 'add') ? intval($request->ambilanring100) : -intval($request->ambilanring100);

        $k01 = ($deno['txtsen1'] * 0.01);
        $k05 = ($deno['txtsen5'] * 0.05);
        $k010 = ($deno['txtsen10'] * 0.10);
        $k020 = ($deno['txtsen20'] * 0.20);
        $k050 = ($deno['txtsen50'] * 0.50);
        $k1 = ($deno['txtring1'] * 1);
        $k5 = ($deno['txtring5'] * 5);
        $k10 = ($deno['txtring10'] * 10);
        $k20 = ($deno['txtring20'] * 20);
        $k50 = ($deno['txtring50'] * 50);
        $k100 = ($deno['txtring100'] * 100);

        $totalkeping =  $k01 + $k05 + $k010 + $k020 +
                        $k050 + $k1 + $k5 + $k10 + $k20 +
                        $k50 + $k100;

        $array_total_cash = [
            'syiling1' => $k01,
            'syiling5' => $k05,
            'syiling10' => $k010,
            'syiling20' => $k020,
            'syiling50' => $k050,
            'kertas1' => $k1,
            'kertas5' => $k5,
            'kertas10' => $k10,
            'kertas20' => $k20,
            'kertas50' => $k50,
            'kertas100' => $k100,
        ];

        return ['deno' => $deno,'total' => $totalkeping,'cash' => $array_total_cash];
    }


    public function CashDeposit(Request $request){

        $cawangan = Cawangan::on('mysql7')->where('kodcaw','=',$this->cawangan)->first();
        $current = Carbon::now();
        $current = new Carbon();
        
        try {
            // Start transaction
            DB::connection($cawangan['mysql'])->beginTransaction();
            DB::connection('mysql7')->beginTransaction();

            /* Addtunai Transaction */
            $response_addtunai = $this->checkAddTunai($request);

            if($response_addtunai !== 'success'){
                // Log::error("Unsuccessful Tunai");
                Log::debug($response_addtunai);
                throw new Exception('Unsuccessful Tunai');
            }

            $addtunai = AddTunai::on($cawangan['mysql'])->create([
                'tarikh' => $current->toDateString(),
                'kodcaw'=> $this->cawangan,
                'kodlaluan'=>$request->teller,
                'tambah'=>$request->amt,
                'kurang'=> 0,
                'nota'=>$request->nota,
                'created_at'=>$current
            ]);

            /* Tunai Transaction */
            $tunai = Tunai::on($cawangan['mysql'])
                    ->where([['kodcaw','=',$this->cawangan],['tarikh','=',$current->toDateString()],['kodlaluan','=',$request->teller]]);
            $tunai = optional($tunai->first())->toArray();

            if(empty($tunai)){
                Log::debug($this->cawangan);
                Log::debug($current->toDateString());
                Log::debug($request->teller);
                throw new Exception("Empty Tunai Data");
            }

            $total_teller_deposit = $tunai['tambah'] + $request->amt;
            $remaining_teller_cashflow = $tunai['baki'] + $request->amt;

            Tunai::on($cawangan['mysql'])->where( [['tarikh','=', $current->toDateString()],['kodlaluan','=', $request->teller] ])->
            update(array(
                'tambah' => $total_teller_deposit,
                'baki' => $remaining_teller_cashflow
            ));

            /* Vault Transaction */
            $vault = Vault::on($cawangan['mysql'])
                ->where('kodcaw','=',$this->cawangan)
                ->where('tarikh','=',$current->toDateString());
            $vault = optional($vault->first())->toArray();

            if(empty($vault)){
                throw new Exception("Empty Vault Data");
            }

            $total_vault_deposit = $vault['keluar'] + $request->amt;
            $remaining_vault = $vault['bakiawal'] - $total_vault_deposit + $vault['masuk'] + $vault['pendahuluan'] - $vault['serahan'] - $vault['totpanjar'];

            Vault::on($cawangan['mysql'])->where([['tarikh','=',$current->toDateString()],['kodcaw','=', $this->cawangan]])->update(array(
                'keluar' => $total_vault_deposit,
                'bakiakhir' => $remaining_vault,
                'bakieod' => $remaining_vault
             ));

            /* Denominasi Transaction */

            $response_deno = $this->getDenoTotal($request,'subtract');

            if($response_deno == 'empty')
                throw new Exception("Empty Denominasi Data");
            
            $deno = $response_deno['deno'];
            $total = $response_deno['total'];
            $cash = $response_deno['cash'];
            
            Denominasi::on($cawangan['mysql'])->where([['tarikh','=',$current->toDateString()]])->update(array(
                'txtring1'=> $deno['txtring1'],
                'k1'=> $cash['kertas1'],
                'txtring5'=> $deno['txtring5'],
                'k5'=> $cash['kertas5'],
                'txtsen1'=> $deno['txtsen1'],
                'k01'=> $cash['syiling1'],
                'txtsen5'=> $deno['txtsen5'],
                'k05'=> $cash['syiling5'],
                'txtsen10'=> $deno['txtsen10'],
                'k010'=> $cash['syiling10'],
                'txtsen20'=> $deno['txtsen20'],
                'k020'=> $cash['syiling20'],
                'txtsen50'=> $deno['txtsen50'],
                'k050'=> $cash['syiling50'],
                'txtring10'=> $deno['txtring10'],
                'k10'=> $cash['kertas10'],
                'txtring20'=> $deno['txtring20'],
                'k20'=> $cash['kertas20'],
                'txtring50'=> $deno['txtring50'],
                'k50'=> $cash['kertas50'],
                'txtring100'=> $deno['txtring100'],
                'k100'=> $cash['kertas100'],
                'txtjumlah'=> $total,
                'jumlahkeping' => $total
             ) );

            /* RequestTeller Transaction */
            $requestteller = RequestTeller::on('mysql7')->where([['no','=',$request->no],['kodcaw','=',$this->cawangan],['kodlaluan','=',$request->teller],['update','=',0]])->update(array(
                'update' => 1,
                'bd1' => 0,
                'bd5' => 0,
                'bd10' => 0,
                'bd20' => 0,
                'bd50' => 0,
                'bd100' => 0,
                'txtring1' => ($request->ambilanring1) ? $request->ambilanring1 : 0,
                'txtring5' => ($request->ambilanring5) ? $request->ambilanring5 : 0,
                'txtring10' => ($request->ambilanring10) ? $request->ambilanring10 : 0,
                'txtring20' => ($request->ambilanring20) ? $request->ambilanring20 : 0,
                'txtring50' => ($request->ambilanring50) ? $request->ambilanring50 : 0,
                'txtring100' => ($request->ambilanring100) ? $request->ambilanring100 : 0,
                'txtring1000' => 0,
                'txtsen1' => ($request->ambilansen1) ? $request->ambilansen1 : 0,
                'txtsen5' => ($request->ambilansen5) ? $request->ambilansen5 : 0,
                'txtsen10' => ($request->ambilansen10) ? $request->ambilansen10 : 0,
                'txtsen20' => ($request->ambilansen20) ? $request->ambilansen20 : 0,
                'txtsen50' => ($request->ambilansen50) ? $request->ambilansen50 : 0,
                'recno' => $addtunai['id']
             ) );

            // Commit transactions
            DB::connection($cawangan['mysql'])->commit();
            DB::connection('mysql7')->commit();

            return 'success';
           
        } catch (\Exception $e) {
            DB::connection($cawangan['mysql'])->rollBack();
            DB::connection('mysql7')->rollBack();
            Log::error("Transaction failed: " . $e->getMessage());
        
            return 'error';
        }
        
    }

    public function CashWithdrawals(Request $request){
        $cawangan = Cawangan::on('mysql7')->where('kodcaw','=',$this->cawangan)->first();
        $current = Carbon::now();
        $current = new Carbon();

        try {

            // Start transaction
            DB::connection($cawangan['mysql'])->beginTransaction();
            DB::connection('mysql7')->beginTransaction();
            
            /* Addtunai Transaction */
            $response_addtunai = $this->checkAddTunai($request);

            if($response_addtunai !== 'success'){
                // Log::error("Unsuccessful Tunai");
                Log::debug($response_addtunai);
                throw new Exception('Unsuccessful Tunai');
            }

            $addtunai = AddTunai::on($cawangan['mysql'])->create([
                'tarikh' => $current->toDateString(),
                'kodcaw'=> $this->cawangan,
                'kodlaluan'=>$request->teller,
                'tambah'=>0,
                'kurang'=> $request->amt,
                'nota'=>$request->nota,
                'created_at'=>$current
            ]);

            /* Tunai Transaction */
            $tunai = Tunai::on($cawangan['mysql'])
                    ->where([['kodcaw','=',$this->cawangan],['tarikh','=',$current->toDateString()],['kodlaluan','=',$request->teller]]);
            $tunai = optional($tunai->first())->toArray();

            if(empty($tunai)){
                Log::debug($this->cawangan);
                Log::debug($current->toDateString());
                Log::debug($request->teller);
                throw new Exception("Empty Tunai Data");
            }

            $total_teller_deposit = $tunai['kurang'] + $request->amt;
            $remaining_teller_cashflow = $tunai['baki'] - $request->amt;

            Tunai::on($cawangan['mysql'])->where( [['tarikh','=', $current->toDateString()],['kodlaluan','=', $request->teller] ])->
            update(array(
                'kurang' => $total_teller_deposit,
                'baki' => $remaining_teller_cashflow
            ));

            /* Vault Transaction */
            $vault = Vault::on($cawangan['mysql'])
                ->where('kodcaw','=',$this->cawangan)
                ->where('tarikh','=',$current->toDateString());
            $vault = optional($vault->first())->toArray();

            if(empty($vault)){
                throw new Exception("Empty Vault Data");
            }

            $total_vault_deposit = $vault['masuk'] + $request->amt;
            $remaining_vault = $vault['bakiawal'] - $vault['keluar'] + $total_vault_deposit + $vault['pendahuluan'] - $vault['serahan'] - $vault['totpanjar'];

            Vault::on($cawangan['mysql'])->where([['tarikh','=',$current->toDateString()],['kodcaw','=', $this->cawangan]])->update(array(
                'masuk' => $total_vault_deposit,
                'bakiakhir' => $remaining_vault,
                'bakieod' => $remaining_vault
             ));

            /* Denominasi Transaction */
            $response_deno = $this->getDenoTotal($request,'add');

            if($response_deno == 'empty')
                throw new Exception("Empty Denominasi Data");
            
            $deno = $response_deno['deno'];
            $total = $response_deno['total'];
            $cash = $response_deno['cash'];
            
            Denominasi::on($cawangan['mysql'])->where([['tarikh','=',$current->toDateString()]])->update(array(
                'txtring1'=> $deno['txtring1'],
                'k1'=> $cash['kertas1'],
                'txtring5'=> $deno['txtring5'],
                'k5'=> $cash['kertas5'],
                'txtsen1'=> $deno['txtsen1'],
                'k01'=> $cash['syiling1'],
                'txtsen5'=> $deno['txtsen5'],
                'k05'=> $cash['syiling5'],
                'txtsen10'=> $deno['txtsen10'],
                'k010'=> $cash['syiling10'],
                'txtsen20'=> $deno['txtsen20'],
                'k020'=> $cash['syiling20'],
                'txtsen50'=> $deno['txtsen50'],
                'k050'=> $cash['syiling50'],
                'txtring10'=> $deno['txtring10'],
                'k10'=> $cash['kertas10'],
                'txtring20'=> $deno['txtring20'],
                'k20'=> $cash['kertas20'],
                'txtring50'=> $deno['txtring50'],
                'k50'=> $cash['kertas50'],
                'txtring100'=> $deno['txtring100'],
                'k100'=> $cash['kertas100'],
                'txtjumlah'=> $total,
                'jumlahkeping' => $total
             ) );

            /* RequestTeller Transaction */
            $requestteller = RequestTeller::on('mysql7')->where([['no','=',$request->no],['kodcaw','=',$this->cawangan],['kodlaluan','=',$request->teller],['update','=',0]])->update(array(
                'update' => 1,
                'recno' => $addtunai['id']
             ) );

            // Commit transactions
            DB::connection($cawangan['mysql'])->commit();
            DB::connection('mysql7')->commit();

            return 'success';
        }catch(\Exception $e){
            DB::connection($cawangan['mysql'])->rollBack();
            DB::connection('mysql7')->rollBack();
            Log::error("Transaction failed: " . $e->getMessage());
        
            return 'error';
        }
    }

}
