<?php


namespace App\Http\Controllers\api;


use App\Http\Controllers\Controller;
use App\Models\Coupon;
use App\Models\Customer;
use App\Models\CustomerCoupon;
use App\Models\DataGadai;
use App\Models\DataGadaiDetail;
use App\Models\Gerai;
use App\Models\HistoryExtend;
use App\Models\HistoryExtendDetail;
use App\Models\Notification;
use App\Models\PromoPoint;

use App\Models\JobLog;
use App\Models\Level;
use App\Models\OauthClient;
use App\Models\Payment;
use App\Models\Point;
use App\Models\RiwayatPoint;
use App\Models\PointReferalCode;
use Carbon\Carbon;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use App\Http\Controllers\api\RajaGadaiOutController;

class RajaGadaiInController extends Controller
{
    public $logKey; //agar bisa diakses lewat CLI (ini saat test prelive)
    public function __construct()
    {
        $this->middleware('whitelist');
        $route = request()->route();
        if ($route) {
            $action = $route->getActionName(); // misalnya "App\Http\Controllers\HomeController@index"
            $this->logKey = [
                'log_key' => (int) $this->keyLogs(),
                'caller'  => $action
            ];
        } else {
            // default logKey kalau dipanggil dari CLI (job/command)
            $this->logKey = [
                'log_key' => (int) $this->keyLogs(),
                'caller'  => 'CLI'
            ];
        }
    }

    public function referalPaid($id, $nomor_member)
    {
        try {
            $pointReferal = PointReferalCode::where('customer_id', $id)->where('status', '!=', 'Terkirim')->first();
            if ($pointReferal) {
                $customerGetRef = Customer::where('referal_code', $pointReferal->referal_code)->first();
                if ($customerGetRef) {
                    $customerGetRef->update([
                        'point' => DB::raw('point +' .  $pointReferal->point),
                        'sumber_mutasi' => 'Komisi Referal ' . $nomor_member
                    ]);
                }
                $pointReferal->update([
                    'status' => 'Terkirim'
                ]);
                Log::channel('rgapps')->info('Point Berhasil Dikirim');
            } else {
                Log::channel('rgapps')->info('Tidak ada point yang dikirim');
            }
        } catch (Exception $e) {
            Log::channel('rgapps')->error($e->getMessage());
            Log::channel('rgapps')->error($e->getTraceAsString());
        }
    }

    public function payment(Request $request)
    {
        $data = $request->json()->all();
        Log::channel('rgapps')->info('url: ' . $request->url(), $this->logKey);
        Log::channel('rgapps')->info('Request: ' . json_encode($data), $this->logKey);

        try {
            DB::beginTransaction();
            $cust = Customer::where('nomor_member', $data['memberNumber'])->first();
            $voucher = null;
            $tipe_notif = Notification::where('type_id', 3)->first();
            $now = Carbon::now();
            $date_now = $now->format('Y-m-d H:i:s');
            $validator = Validator::make($data, [
                'paymentDate' => 'required|date|before_or_equal:today',
                'transactionNumber' => 'required',
                'memberNumber' => 'required',
                'paymentType' => 'required',
                'amount' => 'required|integer'
            ]);
            if ($validator->fails()) {
                throw new Exception($validator->errors(), 400);
            }
            if ($cust == null) {
                throw new Exception('Customer dengan nomor member ini tidak ada', 400);
            }

            $payment = Payment::where('nomor_transaksi', $data['transactionNumber'])
                ->where('status', '=', 'Pelunasan')->first();

            if ($payment == null) {
                $response = [
                    'customer_id' => $cust->customer_id,
                    'notification_id' => $tipe_notif->id,
                    'status' => 0,
                    'tipe_proses' => 'Pembayaran',
                    'created_who' => 'cronjob',
                    'tgl_proses' => $date_now,
                    'gadai_number' => $data['transactionNumber'],
                    'count_sending' => 0
                ];

                Payment::create([
                    'tgl_bayar' => $data['paymentDate'],
                    'nomor_transaksi' => $data['transactionNumber'],
                    'nominal' => $data['amount'],
                    'tipe_pembayaran' => $data['paymentType'],
                    'metode_pembayaran' => $data['paymentMethod'],
                    'nota_hilang' => $data['noteLost'] ?? 0,
                    'status' => $data['type'],
                ]);
            } else {
                Log::channel('repair')->info('Response: ' . json_encode(['message' => 'Gadai dengan nomor transaksi ' . $data['transactionNumber'] . ' sudah lunas']), $this->logKey);
                return response()->json(['message' => 'Gadai dengan nomor transaksi ' . $data['transactionNumber'] . ' sudah lunas'], 400);
            }
            $dataGadai = DataGadai::where('nomor_transaksi', $data['transactionNumber'])
                ->where('customer_id', $cust->customer_id)->first();
            if ($dataGadai == null) {
                throw new Exception('Customer: ' . $cust->nama_customer . ' tidak memiliki data gadai dengan nomor ' . $data['transactionNumber'], 400);
            }
            $dataGadai->update([
                'status' => 'Close'
            ]);

            if ($data['usedPoint'] != null && $data['usedPoint'] > 0) {
                if ($data['usedPoint'] > $cust->point) {
                    throw new Exception('Poin Tidak Mencukupi', 400);
                }
                $mutasi = 'Redeem PoinPelunasan Gadai ' . $data['transactionNumber'];
                Customer::where('customer_id', $cust->customer_id)
                    ->lockForUpdate()
                    ->update([
                        'point' => DB::raw('point - ' . abs($data['usedPoint'])),
                        'sumber_mutasi' => $mutasi,
                        'updated_who' => 'api-rajagadai'
                    ]);
                $settledPoint = abs($data['usedPoint']);
                $this->settledPoint($settledPoint, $cust->customer_id, $mutasi);
            }
            if ($data['codeVoucher'] != null) {
                $codeVouchers = explode(',', $data['codeVoucher']);
                foreach ($codeVouchers as $vouchers) {
                    $codeVoucher = CustomerCoupon::where('customer_id', $cust->customer_id)
                        ->where('code_coupon', $vouchers)
                        ->first();
                    if ($codeVoucher != null) {
                        if ($codeVoucher->status_aktif == FALSE) {
                            throw new Exception('Voucher Sudah Tidak Aktif', 400);
                        }

                        $codeVoucher->update([
                            'status_aktif' => false,
                            'updated_who' => 'api-rajagadai',
                            'used_for' => 'Pelunasan Gadai ' . $dataGadai->nomor_transaksi
                        ]);
                    } else {
                        throw new Exception('Kode Voucher Tidak Valid', 400);
                    }
                }
            }


            $point = Point::where('tipe_gadai', 'Pelunasan')->first();
            if (!empty($point)) {
                if ($data['paymentDate'] <= $dataGadai->tgl_jatuh_tempo) {
                    DB::table('customer')
                        ->where('customer_id', $cust->customer_id)
                        ->lockForUpdate()
                        ->update([
                            'point' => DB::raw('point +' . $point->point),
                            'sumber_mutasi' => 'Bonus Poin Pelunasan Gadai ' . $data['transactionNumber'],
                        ]);
                }
            }
            $jobReminder = JobLog::where('customer_id', $cust->customer_id)
                ->where('tipe_proses', 'Reminder')
                ->where('gadai_number', $data['transactionNumber'])->get();
            foreach ($jobReminder as $job) {
                $job->delete();
            }
            $this->referalPaid($cust->customer_id, $data['memberNumber']);
            JobLog::create($response);
            DB::commit();
            Log::channel('rgapps')->info('Response: Data Pembayaran Berhasil Disimpan', $this->logKey);
            return response()->json('Data Pembayaran Berhasil Disimpan', 200);
        } catch (Exception $e) {
            DB::rollBack();
            $errorMessage = $this->responseError($e, 'rgapps', $this->logKey);
            return response()->json($errorMessage, ($e->getCode() >= 100 && $e->getCode() < 600) ? $e->getCode() : Response::HTTP_INTERNAL_SERVER_ERROR);
        }
    }

    public function cancelPayment(Request $request)
    {
        $data = $request->json()->all();
        Log::channel('rgapps')->info('url: ' . $request->url(), $this->logKey);
        Log::channel('rgapps')->info('Request: ' . json_encode($data), $this->logKey);

        try {
            DB::beginTransaction();
            $cust = Customer::where('nomor_member', $data['memberNumber'])->first();
            $voucher = null;
            $now = Carbon::now();
            $date_now = $now->format('Y-m-d H:i:s');
            $gadai = DataGadai::where('nomor_transaksi', $data['transactionNumber'])->first();
            if ($gadai) {
                $gadai->update([
                    'status' => 'Gadai',
                    'updated_who' => 'api-rajagadai'
                ]);

                Payment::where('nomor_transaksi', $data['transactionNumber'])
                    ->where('status', '=', 'Pelunasan')
                    ->update([
                        'status' => 'Cancel',
                        'updated_who' => 'api-rajagadai',
                        'tgl_cancel' => Carbon::now()->format('Y-m-d')
                    ]);
                $mutasi = 'Cancel Pelunasan Gadai ' . $data['transactionNumber'];
                if ($data['usedPoint'] > 0 || $data['usedPoint'] != null) {
                    Customer::where('customer_id', $cust->customer_id)
                        ->lockForUpdate()
                        ->update([
                            'point' => DB::raw('point + ' . abs($data['usedPoint'])),
                            'sumber_mutasi' => $mutasi,
                            'updated_who' => 'api-rajagadai'
                        ]);
                }

                if ($data['codeVoucher'] != null) {
                    $codeVouchers = explode(',', $data['codeVoucher']);
                    foreach ($codeVouchers as $vouchers) {
                        $codeVoucher = CustomerCoupon::where('customer_id', $cust->customer_id)
                            ->where('code_coupon', $vouchers)
                            ->first();
                        if ($codeVoucher != null) {
                            $codeVoucher->update([
                                'status_aktif' => true,
                                'updated_who' => 'api-rajagadai',
                                'used_for' => null
                            ]);
                        } else {
                            throw new Exception('Kode Voucher Tidak Valid', 400);
                        }
                    }
                }

                // $point = Point::where('tipe_gadai', 'Pelunasan')->first();
                // Customer::where('customer_id', $cust->customer_id)
                //     ->lockForUpdate()
                //     ->update([
                //         'point' => DB::raw('point - ' . $point->point),
                //         'sumber_mutasi' => $mutasi,
                //         'updated_who' => 'api-rajagadai'
                //     ]);
                // $settledPoint = $point->point;
                // $this->settledPoint($settledPoint, $cust->customer_id, $mutasi);
                DB::commit();
                Log::channel('rgapps')->info('Response: Cancel Pelunasan Gadai Berhasil Dilakukan', $this->logKey);
                return response()->json('Cancel Pelunasan Gadai Berhasil Dilakukan', 200);
            } else {
                throw new Exception('Gadai dengan nomor transaksi ' . $data['transactionNumber'] . ' tidak tersedia', 400);
            }
        } catch (Exception $e) {
            DB::rollBack();
            $errorMessage = $this->responseError($e, 'rgapps', $this->logKey);
            return response()->json($errorMessage, ($e->getCode() >= 100 && $e->getCode() < 600) ? $e->getCode() : Response::HTTP_INTERNAL_SERVER_ERROR);
        }
    }

    public function generateExtend()
    {
        $year = Carbon::now()->format('y');
        $month = Carbon::now()->format('ym');
        $count = DB::select("select * from fn_getid('extend_$year')");
        $data = json_encode($count);
        $id = json_decode($data, true);
        $fourDigit = str_pad($id[0]['fn_getid'], 6, '0', STR_PAD_LEFT);

        return 'EXT-' . $month . $fourDigit;
    }

    public function gadai(Request $request)
    {
        $data = $request->json()->all();
        Log::channel('rgapps')->info('url: ' . $request->url(), $this->logKey);
        Log::channel('rgapps')->info('Request: ' . json_encode($data), $this->logKey);

        try {
            DB::beginTransaction();
            $cust = Customer::where('nomor_member', $data['memberNumber'])->first();
            $tipe_notif = Notification::where('type_id', 2)->first();
            $now = Carbon::now();
            $date_now = $now->format('Y-m-d H:i:s');
            $tanggal_sekarang = Carbon::now()->format('Y-m-d');
            $promo_point =  PromoPoint::where('tgl_mulai_pengumpulan_point', '<=', $data['pawnDate'])
                ->where('tgl_selesai_pengumpulan_point', '>=', $data['pawnDate'])
                ->where('status', 'Aktif')
                ->where('minimum_transaksi', '<', $data['amount'])
                ->first();
            $validator = Validator::make($data, [
                'pawnDate' => 'required|date|before_or_equal:today',
                'dueDate' => 'required|date|after_or_equal:pawnDate',
                'auctionDate' => 'required|date|after_or_equal:dueDate',
                'transactionNumber' => 'required',
                'memberNumber' => 'required',
                'status' => 'required|in:Gadai,Close,Lelang',
                'item' => 'required|array'
            ]);
            if ($validator->fails()) {
                throw new Exception($validator->errors(), 400);
            }
            if ($cust == null) {
                throw new Exception('Tidak ada customer dengan nomor member tersebut', 400);
            }
            if ($cust->ext_member_id == null) {
                $ctrl_rg_out = new RajaGadaiOutController();
                $getExtMemberID = $ctrl_rg_out->register($cust->nomor_member, $cust->no_hp);
                $responseArray = json_decode($getExtMemberID, true);
                if ($responseArray['status'] == true) {
                    $responseMessage = $responseArray['data'];
                    $extMemberID = $responseMessage['externalMemberID'];
                    $cust->update([
                        'ext_member_id' => $extMemberID,
                        'updated_who' => 'api-rajagadai'
                    ]);
                }
            }

            $transaksi = DataGadai::where('nomor_transaksi', $data['transactionNumber'])->whereNull('deleted_at')->count();
            if ($transaksi > 0) {
                throw new Exception('Nomor Transaksi Sudah Terdaftar', 400);
            }
            $level = Level::where('point', '<=', $cust->level_point)
                ->orderBy('point', 'desc')->first();
            $point = $data['calculateRewardAmount'] / $level->point_conversion;
            $xp = $data['calculateRewardAmount'] / $level->xp_conversion;
            $gerai = Gerai::where('outletidrgapp', $data['outletIDRGApp'])->first();
            if ($gerai != null) {
                $gadai = DataGadai::create([
                    'customer_id' => $cust->customer_id,
                    'nomor_transaksi' => $data['transactionNumber'],
                    'tgl_gadai' => $data['pawnDate'],
                    'tgl_jatuh_tempo' => $data['dueDate'],
                    'tgl_lelang' => $data['auctionDate'],
                    'nominal' => $data['amount'],
                    'status' => ucwords(strtolower($data['status'])),
                    'poin' => (int)$point ?? 0,
                    'lokasi_gerai' => $gerai->nama_gerai,
                    'outletidrgapp' => $data['outletIDRGApp'],
                    'get_point' => abs((int)$point),
                    'get_xp' => abs((int)$xp),
                    'calculate_reward_amount' => $data['calculateRewardAmount']
                ]);
                foreach ($data['item'] as $item) {

                    DataGadaiDetail::create([
                        'data_gadai_id' => $gadai->id,
                        'jenis_barang' => $item['itemType'],
                        'merk_barang' => $item['itemBrand'],
                        'nama_barang' => $item['itemName'],
                        'attribut' => $item['itemAttribute'],
                        'created_who' => 'api_rajagadai'
                    ]);
                }
                $data_coin = $cust->coin;
                if ($cust->coin == null) {
                    $data_coin = 0;
                }
                if ($promo_point != null) {
                    if ($promo_point->kelipatan == "Y") {
                        $result_kelipatan = floor($data['amount'] / $promo_point->minimum_transaksi);
                        $result_coin =   $result_kelipatan * $promo_point->point;
                        $result_valid_coin = $result_coin + $data_coin;
                        Customer::where('customer_id', $cust->customer_id)
                            ->update([
                                'coin' => $result_valid_coin,
                                'promo_point_id' => $promo_point->id,
                                'sumber_mutasi' => 'Gadai Baru ' . $data['transactionNumber'],
                            ]);
                    } else {
                        $result_valid_coin = $promo_point->point + $data_coin;
                        Customer::where('customer_id', $cust->customer_id)
                            ->update([
                                'coin' => $result_valid_coin,
                                'promo_point_id' => $promo_point->id,
                                'sumber_mutasi' => 'Gadai Baru ' . $data['transactionNumber'],
                            ]);
                    }
                }
                if ($data['vouchers'] != null) {
                    foreach ($data['vouchers'] as $voucher) {
                        if ($voucher['externalCodeVoucher'] != null && $voucher['codeVoucher'] != null) {
                            $vouchers = Coupon::where('external_code', $voucher['externalCodeVoucher'])->first();
                            if ($vouchers == null) {
                                throw new Exception('Kode External Voucher ' . $voucher['externalCodeVoucher'] . ' Salah', 400);
                            }
                            $ownVoucher = CustomerCoupon::where('code_coupon', $voucher['codeVoucher'])
                                ->first();
                            if (!empty($ownVoucher)) {
                                throw new Exception('Voucher ' . $voucher['codeVoucher'] . ' sudah pernah diberikan', 400);
                            }

                            CustomerCoupon::create([
                                'customer_id' => $cust->customer_id,
                                'coupon_id' => $vouchers->coupon_id,
                                'code_coupon' => $voucher['codeVoucher'],
                                'tgl_redeem' => $voucher['startEffective'],
                                'masa_berlaku' => $voucher['expired'],
                                'nominal' => $voucher['amountVoucher'],
                                'status_aktif' => true
                            ]);
                        }
                    }
                }

                if ($data['usedVoucher'] != null) {
                    $usedVouchers = explode(',', $data['usedVoucher']);
                    foreach ($usedVouchers as $usedVoucher) {
                        $ownVoucher = CustomerCoupon::where('code_coupon', $usedVoucher)
                            ->where('customer_id', $cust->customer_id)->first();
                        if ($ownVoucher) {
                            if ($ownVoucher->status_aktif == FALSE) {
                                throw new Exception('Voucher ' . $usedVoucher . ' Sudah Digunakan Sebelumnya');
                            } else {
                                $ownVoucher->update([
                                    'status_aktif' => false,
                                    'updated_who' => 'api-rajagadai',
                                    'used_for' => 'Gadai Baru ' . $data['transactionNumber']
                                ]);
                            }
                        } else {
                            throw new Exception('Code voucher ' . $data['usedVoucher'] . ' tidak tersedia');
                        }
                    }
                }

                if ($data['usedPoint'] != null && $data['usedPoint'] > 0) {
                    if ($data['usedPoint'] > $cust->point) {
                        throw new Exception('Poin Tidak Mencukupi', 400);
                    }
                    $mutasi = 'Gadai Baru ' . $data['transactionNumber'];
                    Customer::where('customer_id', $cust->customer_id)
                        ->lockForUpdate()
                        ->update([
                            'point' => DB::raw('point - ' . abs($data['usedPoint'])),
                            'sumber_mutasi' => $mutasi,
                        ]);
                    $settledPoint = abs($data['usedPoint']);
                    $this->settledPoint($settledPoint, $cust->customer_id, $mutasi);
                }

                DB::table('customer')
                    ->where('customer_id', $cust->customer_id)
                    ->lockForUpdate()
                    ->update([
                        'point' => DB::raw('point +' . abs((int)$point)),
                        'level_point' => DB::raw('level_point + ' . abs((int)$xp)),
                        'sumber_mutasi' => 'Gadai Baru ' . $data['transactionNumber'],
                    ]);
                JobLog::create([
                    'customer_id' => $cust->customer_id,
                    'notification_id' => $tipe_notif->id,
                    'status' => 0,
                    'tipe_proses' => 'Penggadaian',
                    'created_who' => 'cronjob',
                    'tgl_proses' => $date_now,
                    'gadai_number' => $data['transactionNumber'],
                    'count_sending' => 0
                ]);
                Log::channel('rgapps')->info('Point : ' . $point . 'XP: ' . $xp);
            } else {
                throw new Exception('Location ID belum di set', 400);
            }
            $this->referalPaid($cust->customer_id, $data['memberNumber']);
            DB::commit();
            Log::channel('rgapps')->info('Response: Data berhasil dibuat', $this->logKey);
            return response()->json('Data berhasil dibuat', 200);
        } catch (Exception $e) {
            DB::rollBack();
            $errorMessage = $this->responseError($e, 'rgapps', $this->logKey);
            return response()->json($errorMessage, ($e->getCode() >= 100 && $e->getCode() < 600) ? $e->getCode() : Response::HTTP_INTERNAL_SERVER_ERROR);
        }
    }

    public function cancelGadai(Request $request)
    {
        $data = $request->json()->all();
        Log::channel('rgapps')->info('url: ' . $request->url(), $this->logKey);
        Log::channel('rgapps')->info('Request: ' . json_encode($data), $this->logKey);

        try {
            DB::beginTransaction();
            $cust = Customer::where('nomor_member', $data['memberNumber'])->first();
            $gadai = DataGadai::where('nomor_transaksi', $data['transactionNumber'])->first();
            $promo_point = PromoPoint::find($cust->promo_point_id);
            if ($gadai) {
                if ($promo_point != null) {
                    $data_coin = $cust->coin;
                    if ($cust->coin == null) {
                        $data_coin = 0;
                    }
                    if ($promo_point->kelipatan == "Y") {
                        $result_kelipatan = floor($data['amount'] / $promo_point->minimum_transaksi);
                        $result_coin =   $result_kelipatan * $promo_point->point;
                        $result_valid_coin = $data_coin - $result_coin;
                        Customer::where('customer_id', $cust->customer_id)
                            ->update([
                                'coin' => $result_valid_coin,
                                'promo_point_id' => null,
                                'sumber_mutasi' => 'Cancel Gadai ' . $data['transactionNumber'],
                            ]);
                    } else {
                        $result_valid_coin = $data_coin - $promo_point->point;
                        Customer::where('customer_id', $cust->customer_id)
                            ->update([
                                'coin' => $result_valid_coin,
                                'promo_point_id' => null,
                                'sumber_mutasi' => 'Cancel Gadai ' . $data['transactionNumber'],
                            ]);
                    }
                }
                $gadai->update([
                    'status' => 'Close',
                    'updated_who' => 'api-rajagadai'
                ]);
                $mutasi = 'Cancel Gadai ' . $data['transactionNumber'];
                DB::table('customer')
                    ->where('customer_id', $cust->customer_id)
                    ->lockForUpdate()
                    ->update([
                        'point' => DB::raw('point -' . abs($gadai->get_point)),
                        'level_point' => DB::raw('level_point -' . abs($gadai->get_xp)),
                        'sumber_mutasi' => $mutasi,
                    ]);
                $settledPoint = $gadai->get_point;
                $this->settledPoint($settledPoint, $cust->customer_id, $mutasi);
                $usedPoint = $data['usedPoint'];
                $usedVoucher = $data['usedVoucher'];
                $getVoucher = $data['vouchers'];
                if ($usedPoint > 0 || $usedPoint != null) {
                    DB::table('customer')
                        ->where('customer_id', $cust->customer_id)
                        ->lockForUpdate()
                        ->update([
                            'point' => DB::raw('point +' . abs($usedPoint)),
                            'sumber_mutasi' => $mutasi,
                        ]);
                }
                if ($usedVoucher != null) {
                    $codeVouchers = explode(',', $usedVoucher);
                    foreach ($codeVouchers as $vouchers) {
                        $codeVoucher = CustomerCoupon::where('customer_id', $cust->customer_id)
                            ->where('code_coupon', $vouchers)
                            ->first();
                        if ($codeVoucher != null) {

                            $codeVoucher->update([
                                'status_aktif' => true,
                                'updated_who' => 'api-rajagadai',
                                'used_for' => null
                            ]);
                        } else {
                            throw new Exception('Kode Voucher Tidak Valid', 400);
                        }
                    }
                }
                if ($getVoucher != null) {
                    foreach ($getVoucher as $voucher) {
                        $vouchers = CustomerCoupon::where('code_coupon', $voucher['codeVoucher'])
                            ->where('customer_id', $cust->customer_id)->first();
                        if ($vouchers != null) {
                            $vouchers->update([
                                'status_aktif' => false,
                                'updated_who' => 'api-rajagadai',
                                'used_for' => $mutasi
                            ]);
                        }
                    }
                }
                $jobReminder = JobLog::where('customer_id', $cust->customer_id)
                    ->where('tipe_proses', 'Reminder')
                    ->where('gadai_number', $data['transactionNumber'])->get();
                foreach ($jobReminder as $job) {
                    $job->delete();
                }
                DB::commit();

                Log::channel('rgapps')->info('Response: Gadai berhasil di cancel', $this->logKey);
                return response()->json('Gadai berhasil di cancel', 200);
            } else {
                throw new Exception('Gadai dengan nomor transaksi ' . $data['transactionNumber'] . ' tidak tersedia', 400);
            }
        } catch (Exception $e) {
            DB::rollBack();
            $errorMessage = $this->responseError($e, 'rgapps', $this->logKey);
            return response()->json($errorMessage, ($e->getCode() >= 100 && $e->getCode() < 600) ? $e->getCode() : Response::HTTP_INTERNAL_SERVER_ERROR);
        }
    }

    public function settledPoint($settledPoint, $customer_id, $sumber)
    {
        while ($settledPoint > 0) {

            $riwayatPoint = RiwayatPoint::where('customer_id', $customer_id)
                //->where('expired_at', '>=', Carbon::today()->format('Y-m-d')) // diremark sementara selama 30 hari sejak 25/06/2025
                ->where('settled_point', '<', DB::raw('point'))
                ->orderBy('created_at', 'asc')
                ->first();

            if (!$riwayatPoint) {
                $totalPoint = RiwayatPoint::where('customer_id', $customer_id)
                    //->where('expired_at', '>=', Carbon::today()) 
                    ->whereColumn('settled_point', '<', 'point')
                    ->sum('point');
                if (!$totalPoint) $totalPoint = 0;
                throw new \Exception("point tidak mencukupi. Total point yang tersedia saat ini : $totalPoint");
            }
            $settled = $riwayatPoint->point - $riwayatPoint->settled_point;
            if ($settled >= $settledPoint) {
                $pointFinal = $settledPoint;
            } else {
                $pointFinal = $settled;
            }
            if ($riwayatPoint->sumber_penggunaan_point == null) {
                $mutasi = $sumber;
            } else {
                $mutasi = $riwayatPoint->sumber_penggunaan_point . ', ' . $sumber;
            }
            $riwayatPoint->update([
                'settled_point' =>  $riwayatPoint->settled_point + $pointFinal,
                'sumber_penggunaan_point' => $mutasi
            ]);

            $settledPoint -= $pointFinal;

            if ($settledPoint == 0) {
                break;
            }
        }
    }

    public function cancelPaymentExtend(Request $request)
    {
        $data = $request->json()->all();
        Log::channel('rgapps')->info('url: ' . $request->url(), $this->logKey);
        Log::channel('rgapps')->info('Request: ' . json_encode($data), $this->logKey);

        try {
            DB::beginTransaction();
            $customer = Customer::where('nomor_member', $data['memberNumber'])->first();
            // if ($data['extendDocNumber'] == null) {
            //  $historyExtend = HistoryExtend::where('no_member', $data['memberNumber'])
            //     ->where('no_transaksi', $data['transactionNumber'])
            //     ->where('status', '!=', 'Cancel')
            //     ->orderByDesc('id')->first();
            // } else {
            $historyExtend = HistoryExtend::where('doc_number', $data['extendDocNumber'])
                ->where('no_member', $data['memberNumber'])
                ->where('no_transaksi', $data['transactionNumber'])->first();
            // }
            if (empty($historyExtend)) {
                //before
                // Log::channel('rgapps')->info('Data history tidak ditemukan');
                // return response()->json('Data Tidak Ditemukan', 400);

                throw new Exception("Data Tidak Ditemukan", 400);
            } else {
                if ($historyExtend->status == "Cancel") {
                    // Log::channel('rgapps')->info('Pembayaran sudah di cancel sebelumnya');
                    // return response()->json('Pembayaran Sudah di Cancel Sebelumnya', 400);
                    throw new Exception("Pembayaran Sudah di Cancel Sebelumnya", 400);
                }
                $dataGadai = DataGadai::where('nomor_transaksi', $data['transactionNumber'])->first();
                if (empty($dataGadai)) {
                    // Log::channel('rgapps')->info('Data gadai tidak ditemukan');
                    // return response()->json('Data Gadai Tidak Ditemukan', 400);
                    throw new Exception("Data Gadai Tidak Ditemukan", 400);
                }
                $dataGadai->update([
                    'tgl_jatuh_tempo' => $data['dueDate'],
                    'tgl_lelang' => $data['auctionDate'],
                    'nominal' => $data['newAmount'],
                    'waiting_payment' => false,
                    'payment_link' => null,
                    'updated_who' => 'api-rajagadai'
                ]);

                $historyExtend->update([
                    'status' => 'Cancel',
                    'tgl_cancel' => $data['cancelDate'],
                    'updated_who' => 'api-rajagadai'
                ]);

                if ($historyExtend->get_point > 0) {
                    $mutasi = 'Cancel Perpanjangan Gadai ' . $historyExtend->doc_number;
                    $customer->update([
                        'point' => DB::raw('point -' . $historyExtend->get_point),
                        'sumber_mutasi' => $mutasi,
                    ]);
                    $settledPoint = abs($historyExtend->get_point);
                    $this->settledPoint($settledPoint, $customer->customer_id, $mutasi);
                }

                if ($historyExtend->get_xp > 0) {
                    $customer->update([
                        'level_point' => DB::raw('level_point -' . $historyExtend->get_xp),
                        'sumber_mutasi' => 'Cancel Perpanjangan Gadai ' . $historyExtend->doc_number,
                    ]);
                }

                if ($historyExtend->point > 0) {
                    $customer->update([
                        'point' => DB::raw('point +' . $historyExtend->point),
                        'sumber_mutasi' => 'Cancel Extend ' . $historyExtend->doc_number,
                    ]);
                }

                if ($historyExtend->code_voucher != null) {
                    $usedVouchers = explode(',', $historyExtend->code_voucher);
                    foreach ($usedVouchers as $usedVoucher) {
                        $voucher = CustomerCoupon::where('code_coupon', $usedVoucher)->first();
                        $voucher->update([
                            'status_aktif' => True,
                            'updated_who' => 'api-rajagadai',
                            'used_for' => null
                        ]);
                    }
                }
                DB::commit();
                Log::channel('rgapps')->info('Response: Perpanjang gadai berhasil dicancel', $this->logKey);
                return response()->json('Perpanjang Gadai Berhasil diCancel', 200);
            }
        } catch (Exception $e) {
            DB::rollBack();
            $errorMessage = $this->responseError($e, 'rgapps', $this->logKey);
            return response()->json($errorMessage, ($e->getCode() >= 100 && $e->getCode() < 600) ? $e->getCode() : Response::HTTP_INTERNAL_SERVER_ERROR);
        }
    }

    public function extend(Request $request)
    {
        $data = $request->json()->all();
        Log::channel('rgapps')->info('url: ' . $request->url(), $this->logKey);
        Log::channel('rgapps')->info('Request: ' . json_encode($data), $this->logKey);

        try {
            DB::beginTransaction();
            $cust = Customer::where('nomor_member', $data['memberNumber'])->first();
            $tipe_notif = Notification::where('type_id', 6)->first();
            $now = Carbon::now();
            $date_now = $now->format('Y-m-d H:i:s');

            $validator = Validator::make($data, [
                'extendDate' => 'required|date|after_or_equal:today',
                'dueDate' => 'required|date|after_or_equal:extendDate',
                'auctionDate' => 'required|date|after_or_equal:dueDate',
                'transactionNumber' => 'required',
                'memberNumber' => 'required',
                'newAmount' => 'required',
                'fromOutlet' => 'required',
                'payment' => 'required|array'
            ]);
            if ($validator->fails()) {
                throw new Exception($validator->errors(), 400);
            }
            if ($cust == null) {
                throw new Exception('Customer dengan member number : ' . $data['memberNumber'] . ' tidak ditemukan', 400);
            }
            $dataGadai = DataGadai::where('nomor_transaksi', $data['transactionNumber'])
                ->where('customer_id', $cust->customer_id)->first();
            if ($dataGadai == null) {
                throw new Exception('Customer : ' . $cust->nama_customer . ' tidak memiliki data gadai dengan nomor ' . $data['transactionNumber'], 400);
            }
            DataGadai::find($dataGadai->id)->update([
                'tgl_jatuh_tempo' => $data['dueDate'],
                'tgl_lelang' => $data['auctionDate'],
                'nominal' => $data['newAmount'],
                'waiting_payment' => false,
                'payment_link' => null,
                'updated_who' => 'api-rajagadai',
                'status' => 'Gadai'
            ]);

            $paymentType = null;
            $paymentMethod = null;
            $payAmount = null;
            $voucherCode = null;
            $usedPoint = null;
            foreach ($data['payment'] as $pay) {
                $paymentType = $pay['paymentType'];
                $paymentMethod = $pay['paymentMethod'];
                $payAmount = $pay['payAmount'];
                $voucherCode = $pay['voucherCode'];
                $usedPoint = $pay['usedPoint'];
            }

            $amount = $data['calculateRewardAmount'];
            if ($data['fromOutlet'] == "TRUE") {

                $docNum = $this->generateExtend();
                $history = HistoryExtend::create([
                    'no_member' => $data['memberNumber'],
                    'no_transaksi' => $data['transactionNumber'],
                    'tgl_extend' => $data['extendDate'],
                    'tgl_jatuh_tempo' => $data['dueDate'],
                    'nominal' => $payAmount,
                    'status' => 'Berhasil',
                    'point' => abs($usedPoint),
                    'code_voucher' => $voucherCode,
                    'created_who' => 'api-rajagadai',
                    'doc_number' => $docNum,
                    'from_outlet' => true,
                    'calculate_reward_amount' => $data['calculateRewardAmount']
                ]);
                $extDocNumber = $history->doc_number;
                foreach ($data['details'] as $details) {
                    HistoryExtendDetail::create([
                        'history_extend_id' => $history->id,
                        'description' => $details['description'],
                        'amount' => $details['amount'],
                        'created_who' => 'api-rajagadai'
                    ]);
                }
                if ($usedPoint != null && $usedPoint > 0) {
                    if ($usedPoint > $cust->point) {
                        throw new Exception('Poin Tidak Mencukupi', 400);
                    }
                    $mutasi = 'Redeem Poin Perpanjang Gadai ' . $history->doc_number;
                    Customer::where('customer_id', $cust->customer_id)
                        ->lockForUpdate()
                        ->update([
                            'point' => DB::raw('point - ' . abs($usedPoint)),
                            'sumber_mutasi' => $mutasi,
                        ]);
                    $settledPoint = abs($usedPoint);
                    $this->settledPoint($settledPoint, $cust->customer_id, $mutasi);
                }
                if ($voucherCode != null) {
                    $voucherCodes = explode(',', $voucherCode);
                    foreach ($voucherCodes as $vc) {
                        $ownVoucher = CustomerCoupon::where('code_coupon', $vc)
                            ->where('customer_id', $cust->customer_id)->first();
                        if ($ownVoucher) {
                            if ($ownVoucher->status_aktif == FALSE) {
                                throw new Exception('Voucher ' . $vc . ' Sudah Digunakan Sebelumnya');
                            } else {
                                $ownVoucher->update([
                                    'status_aktif' => false,
                                    'updated_who' => 'api-rajagadai',
                                    'used_for' => 'Perpanjang Gadai ' . $history->doc_number
                                ]);
                            }
                        } else {
                            throw new Exception('Code voucher salah');
                        }
                    }
                }
            } else {
                $history = HistoryExtend::where('no_transaksi', $data['transactionNumber'])->where('doc_number', $data['extendDocNumber'])->where('status', 'Pending')->first();
                if (!empty($history)) {
                    $history->update([
                        'no_member' => $data['memberNumber'],
                        'no_transaksi' => $data['transactionNumber'],
                        'tgl_jatuh_tempo' => $data['dueDate'],
                        'tgl_extend' => $data['extendDate'],
                        'nominal' => $payAmount,
                        'status' => 'Berhasil',
                        'point' => abs($usedPoint),
                        'code_voucher' => $voucherCode,
                        'from_outlet' => false,
                        'updated_who' => 'api-rajagadai', //dirubah tanggal 21/06/2025 03:02
                        'calculate_reward_amount' => $data['calculateRewardAmount']
                    ]);
                    $extDocNumber = $history->doc_number;
                } else {
                    throw new Exception('Perpanjang Gadai Sudah Terbayar Sebelumnya', 400);
                }
            }

            $level = Level::where('point', '<=', $cust->level_point)
                ->orderBy('point', 'desc')->first();

            $point = $amount / $level->point_conversion;
            $xp = $amount / $level->xp_conversion;
            $history->update([
                'get_point' => abs((int)$point),
                'get_xp' => abs((int)$xp)
            ]);
            DB::table('customer')
                ->where('customer_id', $cust->customer_id)
                ->lockForUpdate()
                ->update([
                    'point' => DB::raw('point +' . abs((int)$point)),
                    'level_point' => DB::raw('level_point + ' . abs((int)$xp)),
                    'sumber_mutasi' => 'Bonus Perpanjangan Gadai ' . $data['transactionNumber'],
                ]);

            $jobReminder = JobLog::where('customer_id', $cust->customer_id)
                ->where('tipe_proses', 'Reminder')
                ->where('gadai_number', $data['transactionNumber'])->get();

            foreach ($jobReminder as $job) {
                $job->delete();
            }

            JobLog::create([
                'customer_id' => $cust->customer_id,
                'notification_id' => $tipe_notif->id,
                'status' => 0,
                'tipe_proses' => 'Perpanjang Gadai',
                'created_who' => 'cronjob',
                'tgl_proses' => $date_now,
                'gadai_number' => $data['transactionNumber'],
                'count_sending' => 0
            ]);
            $this->referalPaid($cust->customer_id, $data['memberNumber']);
            DB::commit();
            $responseData = [
                'message' => 'Data Perpanjang Gadai Berhasil Disimpan',
                'extendDocNumber' => $extDocNumber
            ];
            Log::channel('rgapps')->info('Response: ' . json_encode($responseData), $this->logKey);
            return response()->json($responseData, 200);
        } catch (Exception $e) {
            DB::rollBack();
            $errorMessage = $this->responseError($e, 'rgapps', $this->logKey);
            return response()->json($errorMessage, ($e->getCode() >= 100 && $e->getCode() < 600) ? $e->getCode() : Response::HTTP_INTERNAL_SERVER_ERROR);
        }
    }

    public function token(Request $request)
    {
        $clientId = $request->header('CLIENT-ID');
        $timestamps = $request->header('TIMESTAMP');
        $clientSecret = $request->header('CLIENT-SECRET');
        Log::channel('rgapps')->info('url: ' . $request->url(), $this->logKey);
        Log::channel('rgapps')->info('Request: Client-ID(' . $clientId . ') Client Secret(' . $clientSecret . ')', $this->logKey);

        try {
            $credentials = OauthClient::where('client_id', $clientId)->first();
            $secret = $credentials->client_secret;
            $combinedString = $clientId . $secret . $timestamps;

            $sha256Hash = hash('sha256', $combinedString);
            if ($timestamps != null) {
                $time = Carbon::parseFromLocale($timestamps)->addMinutes('30')->format('Y-m-d H:i:s');
            } else {
                $time = Carbon::now()->addMinutes('30')->format('Y-m-d H:i:s');
            }
            $token = OauthClient::find($credentials->id)->update([
                'token' => $sha256Hash,
                'expired_at' => $time
            ]);
            $response = ['token' => $sha256Hash, 'expiredAt' => $time];
            Log::channel('rgapps')->info('Response: ' . json_encode($response), $this->logKey);
            return response()->json($response, 200);
        } catch (Exception $e) {
            $errorMessage = $this->responseError($e, 'rgapps', $this->logKey);
            return response()->json($errorMessage, ($e->getCode() >= 100 && $e->getCode() < 600) ? $e->getCode() : Response::HTTP_INTERNAL_SERVER_ERROR);
        }
    }

    public function checkPoint(Request $request)
    {
        $data = $request->json()->all();
        Log::channel('rgapps')->info('url: ' . $request->url(), $this->logKey);
        Log::channel('rgapps')->info('Request: ' . json_encode($data), $this->logKey);

        try {
            $member = $request->input('memberNumber');
            $customer = Customer::where('nomor_member', $member)->first();
            if ($customer == null) {
                Log::channel('rgapps')->info('Nomor member tidak valid');
                return response()->json('Poin dari customer dengan nomor member tersebut tidak ada', 400);
            }
            $response = ['point' => $customer->point];
            Log::channel('rgapps')->info('Response: ' . json_encode($response), $this->logKey);
            return response()->json($response, 200);
        } catch (Exception $e) {
            $errorMessage = $this->responseError($e, 'rgapps', $this->logKey);
            return response()->json($errorMessage, ($e->getCode() >= 100 && $e->getCode() < 600) ? $e->getCode() : Response::HTTP_INTERNAL_SERVER_ERROR);
        }
    }

    public function updateStatusVoucherGb(Request $request)
    {
        $data = $request->json()->all();
        Log::channel('rgapps')->info('url: ' . $request->url(), $this->logKey);
        Log::channel('rgapps')->info('Request: ' . json_encode($data), $this->logKey);

        try {
            $member = $request->input('memberNumber');
            $coupon_code = $request->input('voucherCode');
            $status = $request->input('status');
            $tipe_notif = Notification::where('type_id', 8)->first();
            $now = Carbon::now();
            $date_now = $now->format('Y-m-d H:i:s');
            $customer = Customer::where('nomor_member', $member)->first();

            if ($customer == null) {
                throw new Exception('Nomor member tidak valid', 400);
            }

            $customer_coupon = CustomerCoupon::where('customer_id', $customer->customer_id)
                ->where('code_coupon', $coupon_code)->first();
            $status_result = null;
            $status_active = null;
            if ($status == 'ACCEPTED_BY_OUTLET') {
                $outlet = Gerai::where('gerai_id', $customer_coupon->outlet_id)->first();
                $status_result = 'Sudah tersedia di ' . $outlet->nama_gerai;
                $status_active = TRUE;
            }
            if ($status == 'ACCEPTED_BY_CUSTOMER') {
                $status_result = 'Sudah diterima Nasabah';
                $status_active = FALSE;
            }

            if ($status_result != null) {

                //print_r($customer_coupon->code_coupon);exit;

                $customer_coupon->update([
                    'status_reward' => $status,
                    'status_reward_desc' => $status_result,
                    'status_aktif' => $status_active,
                ]);

                JobLog::create([
                    'customer_id' => $customer->customer_id,
                    'notification_id' => $tipe_notif->id,
                    'status' => 0,
                    'tipe_proses' => 'Remider Status Voucher Coin',
                    'created_who' => 'cronjob',
                    'tgl_proses' => $date_now,

                    'coupon_id' => $customer_coupon->customer_coupon_id,
                    'count_sending' => 0
                ]);

                $response = 'Berhasil Merubah Status Voucher GB';
                Log::channel('rgapps')->info('Response: ' . json_encode($response), $this->logKey);
                return response()->json($response, 200);
            } else {
                throw new Exception('Status tidak sama dengan ACCEPTED_BY_OUTLET atau ACCEPTED_BY_CUSTOMER', 400);
            }
        } catch (Exception $e) {
            $errorMessage = $this->responseError($e, 'rgapps', $this->logKey);
            return response()->json($errorMessage, ($e->getCode() >= 100 && $e->getCode() < 600) ? $e->getCode() : Response::HTTP_INTERNAL_SERVER_ERROR);
        }
    }

    public function checkMember(Request $request)
    {
        $data = $request->json()->all();
        Log::channel('rgapps')->info('url: ' . $request->url(), $this->logKey);
        Log::channel('rgapps')->info('Request: ' . json_encode($data), $this->logKey);

        try {
            $resdata = array();
            $phoneNumber = $request->input('phoneNumber');
            $memberId = $request->input('memberId');

            if (empty($phoneNumber) or empty($memberId)) {
                throw new Exception('Invalid parameter!', 400);
            }

            $customer = Customer::where('no_hp', $phoneNumber)->first();
            if ($customer == null) {
                $rc = 400;
                $rm = "Member tidak ditemukan!";
            } else {
                $customer->update([
                    'ext_member_id' => $memberId
                ]);
                $rc = 200;
                $rm = "Success";
                $resdata = ['memberNumber' => $customer->nomor_member];
            }

            $response = array(
                "RC" => $rc,
                "RM" => $rm,
                "Data" => $resdata
            );
            Log::channel('rgapps')->info('Response: ' . json_encode($response), $this->logKey);
            return response()->json($response, 200);
        } catch (Exception $e) {
            $errorMessage = $this->responseError($e, 'rgapps', $this->logKey);
            return response()->json($errorMessage, ($e->getCode() >= 100 && $e->getCode() < 600) ? $e->getCode() : Response::HTTP_INTERNAL_SERVER_ERROR);
        }
    }

    public function xupdateMember(Request $request)
    {
        $data = $request->json()->all();
        Log::channel('rgapps')->info('url: ' . $request->url(), $this->logKey);
        Log::channel('rgapps')->info('Request: ' . json_encode($data), $this->logKey);

        try {
            $member = $request->input('memberNumber');
            $memberId = $request->input('memberId');
            $phoneNumber = $request->input('phoneNumber');
            if (empty($phoneNumber) or empty($member) or empty($memberId)) {
                throw new Exception('Invalid parameter!', 400);
            }

            $customer = Customer::where('nomor_member', $member)->where('ext_member_id', $memberId)->first();
            if ($customer == null) {
                $rc = 400;
                $rm = "Member tidak ditemukan!";
            } else {
                $customer->update([
                    'no_hp' => $phoneNumber
                ]);
                $rc = 200;
                $rm = "Data member berhasil diperbarui.";
            }

            $response = array(
                "RC" => $rc,
                "RM" => $rm
            );
            Log::channel('rgapps')->info('Response: ' . json_encode($response), $this->logKey);
            return response()->json($response, 200);
        } catch (Exception $e) {
            $errorMessage = $this->responseError($e, 'rgapps', $this->logKey);
            return response()->json($errorMessage, ($e->getCode() >= 100 && $e->getCode() < 600) ? $e->getCode() : Response::HTTP_INTERNAL_SERVER_ERROR);
        }
    }

    public function updateMember(Request $request)
    {
        $data = $request->json()->all();
        Log::channel('rgapps')->info('url: ' . $request->url(), $this->logKey);
        Log::channel('rgapps')->info('Request: ' . json_encode($data), $this->logKey);

        try {
            $memberNumber = $request->input('memberNumber');
            $memberId     = $request->input('memberId');
            $phoneNumber  = $request->input('phoneNumber');

            if (empty($memberNumber) && empty($memberId) && empty($phoneNumber)) {
                throw new Exception('Invalid parameter!', 400);
            }

            $customer = null;
            $updateData = [];

            // 1. Cari by memberId + memberNumber
            if ($memberId && $memberNumber) {
                $customer = Customer::where('ext_member_id', $memberId)
                    ->where('nomor_member', $memberNumber)
                    ->first();

                if ($customer) {
                    $updateData['no_hp'] = $phoneNumber;
                }
            }

            // 2. Cari by memberId saja
            if (!$customer && $memberId) {
                $customer = Customer::where('ext_member_id', $memberId)->first();

                if ($customer) {
                    $updateData['no_hp'] = $phoneNumber;
                }
            }

            // 3. Cari by phoneNumber
            if (!$customer && $phoneNumber) {
                $customer = Customer::where('no_hp', $phoneNumber)->first();

                if ($customer) {
                    $updateData = [
                        'ext_member_id' => $memberId
                    ];
                }
            }

            if (!$customer) {
                $rc = 400;
                $rm = 'Member tidak ditemukan!';
                $dataResponse = [];
            } else {
                $updateData = array_filter($updateData, fn($v) => !is_null($v));

                if (!empty($updateData)) {
                    $customer->update($updateData);
                    $customer->refresh(); // ambil data terbaru
                }

                $rc = 200;
                $rm = 'Data member berhasil diperbarui.';

                $dataResponse = [
                    'nomor_member' => $customer->nomor_member,
                    'member_id'    => $customer->ext_member_id,
                    'phone_number' => $customer->no_hp,
                ];
            }

            $response = [
                'RC'   => $rc,
                'RM'   => $rm,
                'Data' => $dataResponse
            ];

            Log::channel('rgapps')->info('Response: ' . json_encode($response), $this->logKey);
            return response()->json($response, 200);
        } catch (Exception $e) {
            $errorMessage = $this->responseError($e, 'rgapps', $this->logKey);
            return response()->json(
                $errorMessage,
                ($e->getCode() >= 100 && $e->getCode() < 600)
                    ? $e->getCode()
                    : Response::HTTP_INTERNAL_SERVER_ERROR
            );
        }
    }


    public function paymentRepair(Request $request)
    {
        $data = $request->json()->all();
        Log::channel('repair')->info('url: ' . $request->url(), $this->logKey);
        Log::channel('repair')->info('Request: ' . json_encode($data), $this->logKey);

        try {
            DB::beginTransaction();
            $cust = Customer::where('nomor_member', $data['memberNumber'])->first();
            $voucher = null;
            $tipe_notif = Notification::where('type_id', 3)->first();
            $now = Carbon::now();
            $date_now = $now->format('Y-m-d H:i:s');

            $validator = Validator::make($data, [
                'paymentDate' => 'required|date|before_or_equal:today',
                'transactionNumber' => 'required',
                'memberNumber' => 'required',
                'paymentType' => 'required',
                'amount' => 'required|integer'
            ]);
            if ($validator->fails()) {
                throw new Exception($validator->errors(), 400);
            }
            if ($cust == null) {
                throw new Exception('Customer dengan nomor member ini tidak ada', 400);
            }

            $dataGadai = DataGadai::where('nomor_transaksi', $data['transactionNumber'])
                ->where('customer_id', $cust->customer_id)->first();
            if ($dataGadai == null) {
                throw new Exception('Customer: ' . $cust->nama_customer . ' tidak memiliki data gadai dengan nomor ' . $data['transactionNumber'], 400);
            }

            if ($dataGadai->status == 'Close') {
                throw new Exception('Gadai dengan Nomor ' . $dataGadai->nomor_transaksi . ' sudah lunas sebelumnya', 400);
            }

            $dataGadai->update([
                'status' => 'Close'
            ]);

            $payment = Payment::where('nomor_transaksi', $data['transactionNumber'])
                ->where('status', '=', 'Pelunasan')->first();

            if ($payment == null) {
                $response = [
                    'customer_id' => $cust->customer_id,
                    'notification_id' => $tipe_notif->id,
                    'status' => 0,
                    'tipe_proses' => 'Pembayaran',
                    'created_who' => 'cronjob',
                    'tgl_proses' => $date_now,
                    'gadai_number' => $data['transactionNumber'],
                    'count_sending' => 0
                ];

                Payment::create([
                    'tgl_bayar' => $data['paymentDate'],
                    'nomor_transaksi' => $data['transactionNumber'],
                    'nominal' => $data['amount'],
                    'tipe_pembayaran' => $data['paymentType'],
                    'metode_pembayaran' => $data['paymentMethod'],
                    'nota_hilang' => $data['noteLost'] ?? 0,
                    'status' => $data['type'],
                ]);
            } else {
                Log::channel('repair')->info('Response: ' . json_encode(['message' => 'Gadai dengan nomor transaksi ' . $data['transactionNumber'] . ' sudah lunas']), $this->logKey);
                return response()->json(['message' => 'Gadai dengan nomor transaksi ' . $data['transactionNumber'] . ' sudah lunas'], 400);
            }

            if ($data['usedPoint'] != null && $data['usedPoint'] > 0) {
                if ($data['usedPoint'] > $cust->point) {
                    throw new Exception('Poin Tidak Mencukupi', 400);
                }
                $mutasi = 'Redeem PoinPelunasan Gadai ' . $data['transactionNumber'];
                Customer::where('customer_id', $cust->customer_id)
                    ->lockForUpdate()
                    ->update([
                        'point' => DB::raw('point - ' . abs($data['usedPoint'])),
                        'sumber_mutasi' => $mutasi,
                        'updated_who' => 'api-rajagadai'
                    ]);
                $settledPoint = abs($data['usedPoint']);
                $this->settledPoint($settledPoint, $cust->customer_id, $mutasi);
            }
            if ($data['codeVoucher'] != null) {
                $codeVouchers = explode(',', $data['codeVoucher']);
                foreach ($codeVouchers as $vouchers) {
                    $codeVoucher = CustomerCoupon::where('customer_id', $cust->customer_id)
                        ->where('code_coupon', $vouchers)
                        ->first();
                    if ($codeVoucher != null) {
                        if ($codeVoucher->status_aktif == FALSE) {
                            throw new Exception('Voucher Sudah Tidak Aktif', 400);
                        }

                        $codeVoucher->update([
                            'status_aktif' => false,
                            'updated_who' => 'api-rajagadai',
                            'used_for' => 'Pelunasan Gadai ' . $dataGadai->nomor_transaksi
                        ]);
                    } else {
                        throw new Exception('Kode Voucher Tidak Valid', 400);
                    }
                }
            }


            $point = Point::where('tipe_gadai', 'Pelunasan')->first();
            if (!empty($point)) {
                if ($data['paymentDate'] <= $dataGadai->tgl_jatuh_tempo) {
                    DB::table('customer')
                        ->where('customer_id', $cust->customer_id)
                        ->lockForUpdate()
                        ->update([
                            'point' => DB::raw('point +' . $point->point),
                            'sumber_mutasi' => 'Bonus Poin Pelunasan Gadai ' . $data['transactionNumber'],
                        ]);
                }
            }
            $jobReminder = JobLog::where('customer_id', $cust->customer_id)
                ->where('tipe_proses', 'Reminder')
                ->where('gadai_number', $data['transactionNumber'])->get();
            foreach ($jobReminder as $job) {
                $job->delete();
            }
            $this->referalPaid($cust->customer_id, $data['memberNumber']);
            JobLog::create($response);
            DB::commit();

            Log::channel('repair')->info('Response: Data Pembayaran Berhasil Disimpan', $this->logKey);
            return response()->json('Data Pembayaran Berhasil Disimpan', 200);
        } catch (Exception $e) {
            DB::rollBack();
            $errorMessage = $this->responseError($e, 'repair', $this->logKey);
            return response()->json($errorMessage, ($e->getCode() >= 100 && $e->getCode() < 600) ? $e->getCode() : Response::HTTP_INTERNAL_SERVER_ERROR);
        }
    }

    public function extendRepair(Request $request)
    {
        $data = $request->json()->all();
        Log::channel('repair')->info('url: ' . $request->url(), $this->logKey);
        Log::channel('repair')->info('Request: ' . json_encode($data), $this->logKey);

        try {
            DB::beginTransaction();
            $cust = Customer::where('nomor_member', $data['memberNumber'])->first();
            $tipe_notif = Notification::where('type_id', 6)->first();
            $now = Carbon::now();
            $date_now = $now->format('Y-m-d H:i:s');

            $validator = Validator::make($data, [
                'extendDate' => 'required|date',
                'dueDate' => 'required|date|after_or_equal:extendDate',
                'auctionDate' => 'required|date|after_or_equal:dueDate',
                'transactionNumber' => 'required',
                'memberNumber' => 'required',
                'newAmount' => 'required',
                'fromOutlet' => 'required',
                'payment' => 'required|array'
            ]);
            if ($validator->fails()) {
                throw new Exception($validator->errors(), 400);
            }
            if ($cust == null) {
                throw new Exception('Customer dengan member number : ' . $data['memberNumber'] . ' tidak ditemukan', 400);
            }

            $dataGadai = DataGadai::where('nomor_transaksi', $data['transactionNumber'])
                ->where('customer_id', $cust->customer_id)->first();
            if ($dataGadai == null) {
                throw new Exception('Customer : ' . $cust->nama_customer . ' tidak memiliki data gadai dengan nomor ' . $data['transactionNumber'], 400);
            }
            DataGadai::where('id', $dataGadai->id)
                ->where('tgl_jatuh_tempo', '<', $data['dueDate'])
                ->update([
                    'tgl_jatuh_tempo' => $data['dueDate'],
                    'tgl_lelang' => $data['auctionDate'],
                    'nominal' => $data['newAmount'],
                    'waiting_payment' => false,
                    'payment_link' => null,
                    'updated_who' => 'api-rajagadai',
                    'status' => 'Gadai'
                ]);

            $paymentType = null;
            $paymentMethod = null;
            $payAmount = null;
            $voucherCode = null;
            $usedPoint = null;
            foreach ($data['payment'] as $pay) {
                $paymentType = $pay['paymentType'];
                $paymentMethod = $pay['paymentMethod'];
                $payAmount = $pay['payAmount'];
                $voucherCode = $pay['voucherCode'];
                $usedPoint = $pay['usedPoint'];
            }

            $amount = $data['calculateRewardAmount'];
            if ($data['fromOutlet'] == "TRUE") {
                $docNum = $this->generateExtend();
                $history = HistoryExtend::create([
                    'no_member' => $data['memberNumber'],
                    'no_transaksi' => $data['transactionNumber'],
                    'tgl_extend' => $data['extendDate'],
                    'tgl_jatuh_tempo' => $data['dueDate'],
                    'nominal' => $payAmount,
                    'status' => 'Berhasil',
                    'point' => abs($usedPoint),
                    'code_voucher' => $voucherCode,
                    'created_who' => 'api-rajagadai',
                    'doc_number' => $docNum,
                    'from_outlet' => true,
                    'calculate_reward_amount' => $data['calculateRewardAmount']
                ]);
                $extDocNumber = $history->doc_number;
                foreach ($data['details'] as $details) {
                    HistoryExtendDetail::create([
                        'history_extend_id' => $history->id,
                        'description' => $details['description'],
                        'amount' => $details['amount'],
                        'created_who' => 'api-rajagadai'
                    ]);
                }
                if ($usedPoint != null && $usedPoint > 0) {
                    if ($usedPoint > $cust->point) {
                        Log::channel('repair')->info('Poin tidak mencukupi');
                        // throw new Exception('Poin Tidak Mencukupi', 400);
                    }
                    $mutasi = 'Redeem Poin Perpanjang Gadai ' . $history->doc_number;
                    Customer::where('customer_id', $cust->customer_id)
                        ->lockForUpdate()
                        ->update([
                            'point' => DB::raw('point - ' . abs($usedPoint)),
                            'sumber_mutasi' => $mutasi,
                        ]);
                    $settledPoint = abs($usedPoint);
                    $this->settledPoint($settledPoint, $cust->customer_id, $mutasi);
                }
                if ($voucherCode != null) {
                    $voucherCodes = explode(',', $voucherCode);
                    foreach ($voucherCodes as $vc) {
                        $ownVoucher = CustomerCoupon::where('code_coupon', $vc)
                            ->where('customer_id', $cust->customer_id)->first();
                        if ($ownVoucher) {
                            if ($ownVoucher->status_aktif == FALSE) {
                                throw new Exception('Voucher ' . $vc . ' Sudah Digunakan Sebelumnya');
                            } else {
                                $ownVoucher->update([
                                    'status_aktif' => false,
                                    'updated_who' => 'api-rajagadai',
                                    'used_for' => 'Perpanjang Gadai ' . $history->doc_number
                                ]);
                            }
                        } else {
                            throw new Exception('Code voucher salah');
                        }
                    }
                }
            } else {
                $history = HistoryExtend::where('no_transaksi', $data['transactionNumber'])->where('status', 'Pending')->first();
                if (!empty($history)) {
                    $history->update([
                        'no_member' => $data['memberNumber'],
                        'no_transaksi' => $data['transactionNumber'],
                        'tgl_jatuh_tempo' => $data['dueDate'],
                        'tgl_extend' => $data['extendDate'],
                        'nominal' => $payAmount,
                        'status' => 'Berhasil',
                        'point' => abs($usedPoint),
                        'code_voucher' => $voucherCode,
                        'from_outlet' => false,
                        'created_who' => 'api-rajagadai',
                        'calculate_reward_amount' => $data['calculateRewardAmount']
                    ]);
                    $extDocNumber = $history->doc_number;
                } else {
                    throw new Exception('Perpanjang Gadai Sudah Terbayar Sebelumnya', 400);
                }
            }

            $level = Level::where('point', '<=', $cust->level_point)
                ->orderBy('point', 'desc')->first();

            $point = $amount / $level->point_conversion;
            $xp = $amount / $level->xp_conversion;
            $history->update([
                'get_point' => abs((int)$point),
                'get_xp' => abs((int)$xp)
            ]);
            DB::table('customer')
                ->where('customer_id', $cust->customer_id)
                ->lockForUpdate()
                ->update([
                    'point' => DB::raw('point +' . abs((int)$point)),
                    'level_point' => DB::raw('level_point + ' . abs((int)$xp)),
                    'sumber_mutasi' => 'Bonus Perpanjangan Gadai ' . $data['transactionNumber'],
                ]);

            $jobReminder = JobLog::where('customer_id', $cust->customer_id)
                ->where('tipe_proses', 'Reminder')
                ->where('gadai_number', $data['transactionNumber'])->get();

            foreach ($jobReminder as $job) {
                $job->delete();
            }

            JobLog::create([
                'customer_id' => $cust->customer_id,
                'notification_id' => $tipe_notif->id,
                'status' => 0,
                'tipe_proses' => 'Perpanjang Gadai',
                'created_who' => 'cronjob',
                'tgl_proses' => $date_now,
                'gadai_number' => $data['transactionNumber'],
                'count_sending' => 0
            ]);

            $this->referalPaid($cust->customer_id, $data['memberNumber']);

            DB::commit();

            $responseData = [
                'message' => 'Data Perpanjang Gadai Berhasil Disimpan',
                'extendDocNumber' => $extDocNumber
            ];

            Log::channel('repair')->info('Response : ' . json_encode($responseData), $this->logKey);
            return response()->json($responseData, 200);
        } catch (Exception $e) {
            DB::rollBack();
            $errorMessage = $this->responseError($e, 'repair', $this->logKey);
            return response()->json($errorMessage, ($e->getCode() >= 100 && $e->getCode() < 600) ? $e->getCode() : Response::HTTP_INTERNAL_SERVER_ERROR);
        }
    }

    public function gadaiRepair(Request $request)
    {
        $data = $request->json()->all();
        Log::channel('repair')->info('url: ' . $request->url(), $this->logKey);
        Log::channel('repair')->info('Request: ' . json_encode($data), $this->logKey);

        try {
            DB::beginTransaction();
            $cust = Customer::where('nomor_member', $data['memberNumber'])->first();
            $tipe_notif = Notification::where('type_id', 2)->first();
            $now = Carbon::now();
            $date_now = $now->format('Y-m-d H:i:s');
            $tanggal_sekarang = Carbon::now()->format('Y-m-d');
            $promo_point =  PromoPoint::where('tgl_mulai_pengumpulan_point', '<=', $data['pawnDate'])
                ->where('tgl_selesai_pengumpulan_point', '>=', $data['pawnDate'])
                ->where('status', 'Aktif')
                ->where('minimum_transaksi', '<', $data['amount'])
                ->first();
            $data['status'] = ucwords(strtolower($data['status']));
            $validator = Validator::make($data, [
                'pawnDate' => 'required|date',
                'dueDate' => 'required|date|after_or_equal:pawnDate',
                'auctionDate' => 'required|date|after_or_equal:dueDate',
                'transactionNumber' => 'required',
                'memberNumber' => 'required',
                'status' => 'required|in:Gadai,Close,Lelang',
                'item' => 'required|array'
            ]);
            if ($validator->fails()) {
                throw new Exception($validator->errors(), 400);
            }
            if ($cust == null) {
                throw new Exception('Tidak ada customer dengan nomor member tersebut', 400);
            }
            if ($cust->ext_member_id == null) {
                $ctrl_rg_out = new RajaGadaiOutController();
                $getExtMemberID = $ctrl_rg_out->register($cust->nomor_member, $cust->no_hp);
                $responseArray = json_decode($getExtMemberID, true);
                if ($responseArray['status'] == true) {
                    $responseMessage = $responseArray['data'];
                    $extMemberID = $responseMessage['externalMemberID'];
                    $cust->update([
                        'ext_member_id' => $extMemberID,
                        'updated_who' => 'api-rajagadai'
                    ]);
                }
            }

            $transaksi = DataGadai::where('nomor_transaksi', $data['transactionNumber'])->whereNull('deleted_at')->count();
            if ($transaksi > 0) {
                throw new Exception('Nomor Transaksi Sudah Terdaftar', 400);
            }
            $level = Level::where('point', '<=', $cust->level_point)
                ->orderBy('point', 'desc')->first();
            $point = $data['calculateRewardAmount'] / $level->point_conversion;
            $xp = $data['calculateRewardAmount'] / $level->xp_conversion;
            $gerai = Gerai::where('outletidrgapp', $data['outletIDRGApp'])->first();
            if ($gerai != null) {
                $gadai = DataGadai::create([
                    'customer_id' => $cust->customer_id,
                    'nomor_transaksi' => $data['transactionNumber'],
                    'tgl_gadai' => $data['pawnDate'],
                    'tgl_jatuh_tempo' => $data['dueDate'],
                    'tgl_lelang' => $data['auctionDate'],
                    'nominal' => $data['amount'],
                    'status' => ucwords(strtolower($data['status'])),
                    'poin' => (int)$point ?? 0,
                    'lokasi_gerai' => $gerai->nama_gerai,
                    'outletidrgapp' => $data['outletIDRGApp'],
                    'get_point' => abs((int)$point),
                    'get_xp' => abs((int)$xp),
                    'calculate_reward_amount' => $data['calculateRewardAmount']
                ]);
                foreach ($data['item'] as $item) {

                    DataGadaiDetail::create([
                        'data_gadai_id' => $gadai->id,
                        'jenis_barang' => $item['itemType'],
                        'merk_barang' => $item['itemBrand'],
                        'nama_barang' => $item['itemName'],
                        'attribut' => $item['itemAttribute'],
                        'created_who' => 'api_rajagadai'
                    ]);
                }
                $data_coin = $cust->coin;
                if ($cust->coin == null) {
                    $data_coin = 0;
                }
                if ($promo_point != null) {
                    if ($promo_point->kelipatan == "Y") {
                        $result_kelipatan = floor($data['amount'] / $promo_point->minimum_transaksi);
                        $result_coin =   $result_kelipatan * $promo_point->point;
                        $result_valid_coin = $result_coin + $data_coin;
                        Customer::where('customer_id', $cust->customer_id)
                            ->update([
                                'coin' => $result_valid_coin,
                                'promo_point_id' => $promo_point->id,
                                'sumber_mutasi' => 'Gadai Baru ' . $data['transactionNumber'],
                            ]);
                    } else {
                        $result_valid_coin = $promo_point->point + $data_coin;
                        Customer::where('customer_id', $cust->customer_id)
                            ->update([
                                'coin' => $result_valid_coin,
                                'promo_point_id' => $promo_point->id,
                                'sumber_mutasi' => 'Gadai Baru ' . $data['transactionNumber'],
                            ]);
                    }
                }
                if ($data['vouchers'] != null) {
                    foreach ($data['vouchers'] as $voucher) {
                        if ($voucher['externalCodeVoucher'] != null && $voucher['codeVoucher'] != null) {
                            $vouchers = Coupon::where('external_code', $voucher['externalCodeVoucher'])->first();
                            if ($vouchers == null) {
                                throw new Exception('Kode External Voucher ' . $voucher['externalCodeVoucher'] . ' Salah', 400);
                            }
                            $ownVoucher = CustomerCoupon::where('code_coupon', $voucher['codeVoucher'])
                                ->first();
                            if (!empty($ownVoucher)) {
                                throw new Exception('Voucher ' . $voucher['codeVoucher'] . ' sudah pernah diberikan', 400);
                            }

                            CustomerCoupon::create([
                                'customer_id' => $cust->customer_id,
                                'coupon_id' => $vouchers->coupon_id,
                                'code_coupon' => $voucher['codeVoucher'],
                                'tgl_redeem' => $voucher['startEffective'],
                                'masa_berlaku' => $voucher['expired'],
                                'nominal' => $voucher['amountVoucher'],
                                'status_aktif' => true
                            ]);
                        }
                    }
                }

                if ($data['usedVoucher'] != null) {
                    $usedVouchers = explode(',', $data['usedVoucher']);
                    foreach ($usedVouchers as $usedVoucher) {
                        $ownVoucher = CustomerCoupon::where('code_coupon', $usedVoucher)
                            ->where('customer_id', $cust->customer_id)->first();
                        if ($ownVoucher) {
                            if ($ownVoucher->status_aktif == FALSE) {
                                throw new Exception('Voucher ' . $usedVoucher . ' Sudah Digunakan Sebelumnya');
                            } else {
                                $ownVoucher->update([
                                    'status_aktif' => false,
                                    'updated_who' => 'api-rajagadai',
                                    'used_for' => 'Gadai Baru ' . $data['transactionNumber']
                                ]);
                            }
                        } else {
                            throw new Exception('Code voucher ' . $data['usedVoucher'] . ' tidak tersedia');
                        }
                    }
                }

                if ($data['usedPoint'] != null && $data['usedPoint'] > 0) {
                    if ($data['usedPoint'] > $cust->point) {
                        throw new Exception('Poin Tidak Mencukupi', 400);
                    }
                    $mutasi = 'Gadai Baru ' . $data['transactionNumber'];
                    Customer::where('customer_id', $cust->customer_id)
                        ->lockForUpdate()
                        ->update([
                            'point' => DB::raw('point - ' . abs($data['usedPoint'])),
                            'sumber_mutasi' => $mutasi,
                        ]);
                    $settledPoint = abs($data['usedPoint']);
                    $this->settledPoint($settledPoint, $cust->customer_id, $mutasi);
                }

                DB::table('customer')
                    ->where('customer_id', $cust->customer_id)
                    ->lockForUpdate()
                    ->update([
                        'point' => DB::raw('point +' . abs((int)$point)),
                        'level_point' => DB::raw('level_point + ' . abs((int)$xp)),
                        'sumber_mutasi' => 'Gadai Baru ' . $data['transactionNumber'],
                    ]);
                JobLog::create([
                    'customer_id' => $cust->customer_id,
                    'notification_id' => $tipe_notif->id,
                    'status' => 0,
                    'tipe_proses' => 'Penggadaian',
                    'created_who' => 'cronjob',
                    'tgl_proses' => $date_now,
                    'gadai_number' => $data['transactionNumber'],
                    'count_sending' => 0
                ]);
                Log::channel('repair')->info('Point : ' . $point . 'XP: ' . $xp);
            } else {
                throw new Exception('Location ID belum di set', 400);
            }
            $this->referalPaid($cust->customer_id, $data['memberNumber']);
            DB::commit();
            Log::channel('repair')->info('Response: Data berhasil dibuat', $this->logKey);
            return response()->json('Data berhasil dibuat', 200);
        } catch (Exception $e) {
            DB::rollBack();
            $errorMessage = $this->responseError($e, 'repair', $this->logKey);
            return response()->json($errorMessage, ($e->getCode() >= 100 && $e->getCode() < 600) ? $e->getCode() : Response::HTTP_INTERNAL_SERVER_ERROR);
        }
    }
}
