<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Customer\CustomerFrontController;
use App\Jobs\ClientSyncJobForSingle;
use App\Models\BillGenerate;
use App\Models\Billpayment;
use App\Models\Client;
use App\Models\CustomerAccount;
use App\Models\Packages;
use Brian2694\Toastr\Facades\Toastr;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Http;


class SurjoPayController extends Controller
{
    private $username;
    private $password;
    private $baseUrl;
    private $generatedToken;
    private $return_url;
    private $cancelUrl;
    private $executelUrl;
    private $prefix;
    private $store_id;
    private $customer_name;
    private $customer_phone;
    private $amount_topay;
    private $orderId;
    private $currency;
    private $customer_email;
    private $customerAddress;
    private $customerRoadNo;
    private $customerCity;
    private $customerDistrict;
    private $customerThana;
    private $customer_ip;
    private $checkout_url;
    private $sp_order_id;
    private $callBackUrl;
    private $customer_id;


    public function __construct()
    {
        $this->username = env('SURJO_USER_NAME');
        $this->password = env('SURJO_PASSCODE');
        $this->baseUrl = env('SURJOPAY_BASE_URL');
        $this->prefix = env('SURJO_PREFIX');
        $this->return_url = env('SURJO_RETURN_URL');
        $this->cancelUrl = env('SURJO_CANCEL_URL');
        $this->callBackUrl = env('SURJO_CALLBACK_URL');
    }

    public function getClientInformation(Request $request)
    {
        $customerData = CustomerFrontController::getClientInfo($request);

        // Ensure we have a valid customer object from CustomerFrontController::getClientInfo
        if (!is_array($customerData) || empty($customerData['clientlist'])) {
            return;
        }

        $customer_info = $customerData['clientlist'];

        session(['customer_id' => $customer_info->id]);
        $customerBillingInfo = $customer_info->clientsinfo;



        if ($customerBillingInfo->clients_name !== null) {
            $this->customer_name = trim($customerBillingInfo->clients_name);
        } else {
            $this->customer_name = trim(env('SURJO_CUSTOMER_NAME'));
        }

        if ($customerBillingInfo->contact_no !== null) {
            $this->customer_phone = $customerBillingInfo->contact_no;
        } else {
            $this->customer_phone = env('SURJO_DEFAULT_PHONE');
        }

        if ($customerBillingInfo->email !== null) {
            $this->customer_email = $customerBillingInfo->email;
        } else {
            $this->customer_email = env('SURJO_DEFAULT_EMAIL');
        }




        if ($customerBillingInfo->road_no !== null) {
            $this->customerRoadNo = $customerBillingInfo->road_no;
        } else {
            $this->customerRoadNo = env('SURJO_ROADNO');
        }

        $this->currency = env('SURJO_CURRENCY');

        if ($customer_info != null) {
            $id                     = $customer_info->id;
            $details['userinfo']    =  $customer_info;
            $details['paymentinfo'] = Billpayment::whereClient_id($id)->get();
            $details['billinginfo'] = BillGenerate::whereClient_id($id)->get();
            $details['package']     = Packages::where('id', $customer_info->package_id)->first();
            $details['account']     = CustomerAccount::firstOrCreate(['client_id' => $id]);


            $bill_amount = 0;

            if ($details['account']->dueAmount > 0) {
                $bill_amount = $details['account']->dueAmount;
            } else {
                $bill_amount = $details['package']->package_rate + $details['account']->dueAmount;
            }

            $this->amount_topay = (float)$bill_amount;
        }


        $district = DB::table('districts')->where('id', $customerBillingInfo->district)->get();
        $thana = DB::table('upazilas')->where('id', $customerBillingInfo->thana)->get();
        $divison = DB::table('divisions')->where('id', $customerBillingInfo->division)->get();


        if ($divison != null && $divison != '') {
        }
        /*address*/


        if ($divison != null && count($divison) != 0) {
            $this->customerCity = trim($divison[0]->name);
        } else {
            $this->customerCity = trim(env('SURJO_CITY'));
        }


        if ($district != null && count($district) != 0) {
            $this->customerDistrict = trim($district[0]->name);
        } else {
            $this->customerDistrict = trim(env('SURJO_CITY'));
        }


        if ($thana != null && count($thana) != 0) {
            $this->customerThana = trim($thana[0]->name);
        } else {
            $this->customerThana = trim(env('SURJO_THANA'));
        }



        $this->customerAddress = trim($this->customerRoadNo . " " . $this->customerThana . " " . $this->customerDistrict . " " . $this->customerCity);
        $this->customer_ip = $request->ip();


        $this->orderId = trim($customer_info->id . $this->customer_ip . $this->prefix . substr($this->customer_name, 0, 4) . substr($this->customer_phone, 0, 5) . date("Y-m-d", time()) . "time" . date("h:i:s") . "u_name" . trim($customer_info->userid));
    }



    public function generateToken(Request $request)
    {

        $header = array(
            "Accept: application/json",
            'Content-Type:application/json',
        );


        $response = Http::withHeaders($header)->post("$this->baseUrl/get_token", [
            'username' => $this->username,
            'password' => $this->password
        ]);

        // Safely handle unexpected / failed API responses
        if (!$response->successful()) {
            // You may want to log the response body here for debugging
            throw new \RuntimeException('Unable to generate SurjoPay token. HTTP status: ' . $response->status());
        }

        $data = $response->json();

        if (!is_array($data) || empty($data['token']) || empty($data['store_id']) || empty($data['execute_url'])) {
            // If the API does not return the expected JSON structure, avoid array offset errors
            throw new \RuntimeException('Invalid response received from SurjoPay token API.');
        }

        $this->generatedToken = $data['token'];
        $this->store_id = $data['store_id'];
        $this->executelUrl = $data['execute_url'];


        $this->getClientInformation($request);
    }

    public function executePayment(Request $request)
    {

        $this->generateToken($request);


        $header = [
            "Authorization" => "Bearer $this->generatedToken",
            "Content-Type" => "application/json",
            "Accept" => "application/json"
        ];

        $body_json = [
            "token" => $this->generatedToken,
            "prefix" => $this->prefix,
            "return_url" => $this->callBackUrl . "/surjo-payment-callback",
            "cancel_url" => $this->cancelUrl,
            "store_id" => $this->store_id,
            "order_id" => $this->orderId,
            "amount" => $request->amount,
            "currency" => $this->currency,
            "customer_name" => $this->customer_name,
            "customer_address" => $this->customerAddress,
            "customer_email" => $this->customer_email,
            "customer_phone" => $this->customer_phone,
            "customer_city" => $this->customerCity,
            "client_ip" => $this->customer_ip,
        ];
        // $callBackUrl = "$this->callBackUrl";
        $response = Http::withHeaders($header)->post($this->executelUrl, $body_json);

        session(['surjo_recharge_amount' => $request->amount]);

        $this->checkout_url = $response['checkout_url'];
        $this->sp_order_id = $response['sp_order_id'];
        // dd($response->json());

        return $response['checkout_url'];
    }

    public function verifyPayment(Request $request)
    {
        $url = "$this->baseUrl/verification/$request->order_id";
    }




    public function surjoPaymenCallback(Request $request)
    {
        $this->generateToken($request);
        $header = [
            "Authorization" => "Bearer $this->generatedToken",
            "Content-Type" => "application/json",
            "Accept" => "application/json"
        ];

        $url = "$this->baseUrl/payment-status";
        $orderId = $request->order_id;
        $response_payment = Http::withHeaders($header)->post($url, ['order_id' => $orderId]);

        $resposnse = json_decode($response_payment->body(), true);

        if ($resposnse[0]['sp_message'] == "Success" && $resposnse[0]['amount'] == session('surjo_recharge_amount')) {
            DB::beginTransaction();
            try{
                (new PaymentController)->surjoPayClientCheckOutPaymentProcess(
                    $resposnse[0]['amount'],
                    session('customer_id'),
                    $resposnse[0]['bank_trx_id'],
                    $resposnse[0]['phone_no'],
                    $orderId,
                    $resposnse[0]['date_time'],
                );
                DB::commit();
            }catch(\Exception $e){
                DB::rollBack();
                Toastr::error('ShurjoPay Payment is not Successful');
                return redirect()->route('customerDashboard');
            }

            if (checkAPI()) {
                ClientSyncJobForSingle::dispatch(session('customer_id'));
            }

            Toastr::success('ShurjoPay Payment is Successful');
            return redirect()->route('customerDashboard');
        } else {
            Toastr::error('ShurjoPay Payment is not Successful');
            return redirect()->route('customerDashboard');
        }
        Toastr::error('ShurjoPay Payment is not Successful');
        return redirect()->route('customerDashboard');



    }
}
