<?php

namespace App\Http\Controllers;

use App\Cawangan;
use App\GlDetail;
use App\Transaction;
use App\TransactionOnline;
use App\TransaksiKeuntungan;
use Carbon\Carbon;
use Illuminate\Http\Request;

class TransactionOnlineTrailController extends Controller
{

    public function index(Request $request)
    {

        $transactionsOnline = $this->getTransactionOnlineQuery($request);

        $list_norujukan = [];
        
        if($request->isGroupedByNorujukan){
            $list_norujukan = array_map(fn($x) => ['norujukan' => reset($x)['norujukan'],  'kodcaw' => reset($x)['kodcaw']], $transactionsOnline);
        } else {
            $list_norujukan = array_map(fn($x) => ['norujukan' => $x['norujukan'],  'kodcaw' => $x['kodcaw']], $transactionsOnline);
        }

        $transaction = $this->getTransactionQuery($list_norujukan, $request);
        $transaksiKeuntungan = $this->getTransaksiKeuntunganQuery($list_norujukan, $request);
        $glDetail = $this->getGlDetailQuery($list_norujukan, $request);

        return response()->json([
            'transactionsOnline' => $transactionsOnline,
            'transaction' => $transaction,
            'transaksiKeuntungan' => $transaksiKeuntungan,
            'glDetail' => $glDetail,
        ]);
    }

    private function getTransactionOnlineQuery($request)
    {
        $startDate = $request->startDate ? Carbon::parse($request->startDate)->startOfDay() : Carbon::now()->startOfDay();
        $endDate = $request->endDate ? Carbon::parse($request->endDate)->endOfDay() : Carbon::now()->endOfDay();

        $transactionOnline = TransactionOnline::whereBetween('tarikh', [$startDate, $endDate])
            ->when($request->filled('branch'), function ($query) use ($request) {
                return $query->where('kodcaw', $request->branch);
            })
            ->when($request->filled('billplzBillId'), function ($query) use ($request) {
                return $query->where('billplz_id', $request->billplzBillId);
            })
            ->when($request->filled('norujukan'), function ($query) use ($request) {
                return $query->where('norujukan', $request->norujukan);
            })
            ->get();

        if ($transactionOnline->isEmpty()) {
            $transactionOnline = TransactionOnline::whereBetween('tarikh', [$startDate, $endDate])
                ->when($request->filled('branch'), function ($query) use ($request) {
                    return $query->where('kodcaw', $request->branch);
                })
                ->when($request->filled('norujukan'), function ($query) use ($request) {
                    return $query->where('norujukan', 'LIKE', '%' . $request->norujukan . '%');
                })
                ->get();
        }

        $transactionOnline = $transactionOnline
            ->sortByDesc('tarikh')
            ->sortByDesc('masa')
            ->when($request->filled('status'), function ($query) use ($request) {
                return $query->where('status', $request->status);
            })
            ->when($request->filled('isGroupedByNorujukan') && $request->isGroupedByNorujukan === '1', function ($query) {
                return $query->groupBy('norujukan')->sortKeysDesc();
            })
            ->toArray();

        return $transactionOnline;
    }

    private function getTransactionQuery($list_norujukan, $request)
    {
        $extract_norujukan = array_column($list_norujukan, 'norujukan');
        $startDate = $request->startDate ? Carbon::parse($request->startDate)->startOfDay() : Carbon::now()->startOfDay();
        $endDate = $request->endDate ? Carbon::parse($request->endDate)->endOfDay() : Carbon::now()->endOfDay();

        $transaction = Transaction::whereIn('norujukan', $extract_norujukan)
                                    ->whereBetween('created_at', [$startDate, $endDate])
                                    ->where('teller', 'online')
                                    ->get();

        return $transaction
            ->when($request->filled('isGroupedByNorujukan') && $request->isGroupedByNorujukan === '1', function ($query) {
                return $query->groupBy('norujukan')->sortKeysDesc();
            })
            ->sortByDesc('created_at')->toArray();
    }

    private function getTransaksiKeuntunganQuery($list_norujukan, $request)
    {
        $extract_norujukan = array_column($list_norujukan, 'norujukan');
        $startDate = $request->startDate ? Carbon::parse($request->startDate)->startOfDay() : Carbon::now()->startOfDay();
        $endDate = $request->endDate ? Carbon::parse($request->endDate)->endOfDay() : Carbon::now()->endOfDay();

        $transaksiKeuntungan = TransaksiKeuntungan::whereIn('norujukan', $extract_norujukan)
                                                    ->whereBetween('tarikh_bayaran', [$startDate, $endDate])
                                                    ->whereHas('transaction', fn($query) => $query->where('teller', 'online'))
                                                    ->get();

        return $transaksiKeuntungan
            ->when($request->filled('isGroupedByNorujukan') && $request->isGroupedByNorujukan === '1', function ($query) {
                return $query->groupBy('norujukan')->sortKeysDesc();
            })
            ->toArray();
    }

    public function getGlDetailQuery($list_norujukan, $request)
    {
        $startDate = $request->startDate ? Carbon::parse($request->startDate)->startOfDay() : Carbon::now()->startOfDay();
        $endDate = $request->endDate ? Carbon::parse($request->endDate)->endOfDay() : Carbon::now()->endOfDay();

        $extract_norujukan = array_unique(array_column($list_norujukan, 'norujukan'));
        $extract_kodcaw = array_unique(array_column($list_norujukan, 'kodcaw'));

        $isGroupByNorujukan = $request->filled('isGroupedByNorujukan') && $request->isGroupedByNorujukan === '1';

        $connectionCawangan = Cawangan::on('mysql7')->whereIn('kodcaw', $extract_kodcaw)->get()->pluck('mysql');

        $glDetail = $connectionCawangan->map(fn($x) => GlDetail::on($x)->where('teller', 'ONLINE')->whereBetween('tarikh', [$startDate, $endDate])
            ->orderBy('recno')->get())
            ->flatten()
            ->when($isGroupByNorujukan, function ($glDetail) {
                return $glDetail->groupBy('descpt')
                    ->keyBy(function ($group, $key) {
                        $array = explode(' ', $key);
                        return end($array);
                    });
            })
            ->when($request->filled('norujukan'), function ($glDetail) use ($request) {
                return $glDetail->filter(fn($x) => strpos($x->descpt, $request->norujukan) !== false);
            })
            ->when($request->filled('billplzBillId'), function ($glDetail) use ($extract_norujukan) {
                return $glDetail->filter(function ($x) use ($extract_norujukan) {
                    return collect($extract_norujukan)->contains(function ($norujukan) use ($x) {
                        return strpos($x->descpt, $norujukan) !== false;
                    });
                });
            })
            ->toArray();

        return $glDetail;
    }
}
