<?php 
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Client;
use App\Models\User;
use App\Models\Renew;
use DB;
use Carbon\Carbon;
use App\Models\Package;
use App\Models\Wallet;
use App\Models\Payment;
use App\Models\Sms;
use App\Models\SmsHistory;


class ClientManagerController extends Controller
{

    public function send_sms($msg, $contact)
	{
        echo $msg;

		$sender = urlencode('NERVE TECH');

        //$sms = urlencode(mb_convert_encoding($msg, 'UTF-8','auto'));
        //echo $sms;
        // $msg = 'ME3 Café and Pastries Hello! "This" is a #test$ to %encode& special\' characters (like) *these+ , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~ é á í ó ú ñ';

        // $special_characters = [
        //     '!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/', 
        //     ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`', '{', '|', 
        //     '}', '~', 'é', 'á', 'í', 'ó', 'ú', 'ñ'
        // ];

        //replace special characters with the character in the array
        // foreach ($special_characters as $character) {
        //     $msg = str_replace($character, $character, $msg);
        // }
        
        $sms = rawurlencode($msg);
        
		$phone = $contact;
	
		$url = "http://powertxtgh.com/access.php?company=ALOT&ccode=ALT101&sender=Nerve-Tech&message=$sms&recipient=$contact";

		$ch = curl_init($url);
		curl_setopt($ch, CURLOPT_POST, false); //enable post
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //disable ssl
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); //enable response
		curl_setopt($ch, CURLOPT_ENCODING, '');
		// curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));//add parameters
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded; charset=UTF-8'));

        
		$server_output = curl_exec($ch); //execute request and get response

		return 1;
	}

    
    public function client($page_number)
    {
        $page_size = 30;
        $total_clients = DB::table('clients')->count();
        $total_pages = $this->calculateTotalPages($total_clients, $page_size);
        $offset = ($page_number - 1) * $page_size;

        $clients = Client::join('packages', 'clients.plan', '=', 'packages.id')
                    ->leftJoin('wallets', 'clients.id', '=', 'wallets.client_id') // Use leftJoin instead of join
                    ->select('clients.*', 'packages.data_package', 'packages.price', 'packages.package_type', 'wallets.balance') // Add other fields as needed
                    ->offset($offset)
                    ->limit($page_size)
                    ->get();


        $packages = DB::table('packages')->get();

        // Fetch the last renewal for each client
        $clientRenewals = DB::table('renews')
            ->whereIn('client_id', $clients->pluck('id')) // Select only relevant client IDs
            ->orderBy('id', 'asc')
            ->get();

        // return response()->json(['clients'=>$clientRenewals]);

        // Map renewals to clients
        $renewalsByClientId = $clientRenewals->keyBy('client_id');

        // Add renewal data to clients
        $clients->transform(function ($client) use ($renewalsByClientId) {
            $lastRenewal = $renewalsByClientId->get($client->id);

            if ($lastRenewal) {
                $client->last_renew_date = $lastRenewal->renew_date;
                $client->last_expiry_date = $lastRenewal->expiry_date;

                // Check if the client is renewed based on your logic
                $client->is_renewed = $this->isClientRenewed($lastRenewal->expiry_date);
            } else {
                $client->last_renew_date = null;
                $client->last_expiry_date = null;
                $client->is_renewed = false;
            }

            return $client;
        });

        $nodes = DB::table('stations')->get();

        $sms = Sms::all();

        $data = [
            'page_number' => $page_number,
            'total_pages' => $total_pages,
            'clients' => $clients,
            'nodes' => $nodes,
            'sms' => $sms,
            'packages' => $packages,
        ];

        // return response()->json(['clients'=>$clients]);
        return view('clientmanager', $data);
    }

    // Custom function to check if a client is renewed
    // Custom function to check if a client is renewed
    private function isClientRenewed($expiryDate)
    {
        // If expiry date is null or empty, return false
        if ($expiryDate === null || empty($expiryDate)) {
            return false;
        }

        // Convert the expiry date to a Carbon instance
        $expiryDate = \Carbon\Carbon::parse($expiryDate);

        $expiryDate->addDay();

        // Get the current date
        $currentDate = \Carbon\Carbon::now();

        // Compare the expiry date with the current date
        return $expiryDate->greaterThanOrEqualTo($currentDate);
    }


    public function calculateTotalPages($total_size, $pageSize) {
        return ceil($total_size / $pageSize);
    }

    public function importClients(Request $request)
    {
        try {
            $file = $request->file('file');
            $path = $file->getRealPath();
            $handle = fopen($path, 'r');

            $csvData = [];
            $header = null;

            if ($handle !== FALSE) {
                while (($row = fgetcsv($handle, 1000, ",")) !== FALSE) {
                    if (!$header) {
                        $header = array_map(function($label) {
                            return trim($label, "\xEF\xBB\xBF"); // Remove BOM
                        }, $row);
                    } else {
                        $csvData[] = array_combine($header, $row);
                    }
                }
                fclose($handle);
            }

            // Prepare data for plans batch insert
            $plans = [];
            foreach ($csvData as $row) {
                $plans[$row['Plan']] = [
                    'data_package' => $row['Plan'],
                ];
            }

            // Batch insert plans and retrieve plan IDs
            $planIds = [];
            foreach ($plans as $plan) {
                $existingPlan = Package::where('data_package', $plan['data_package'])->first();

                if (!$existingPlan) {
                    $newPlan = Package::create($plan);
                    $planIds[$plan['data_package']] = $newPlan->id;
                } else {
                    $planIds[$plan['data_package']] = $existingPlan->id;
                }
            }

            // Prepare data for clients batch insert or update
            $clients = [];
            foreach ($csvData as $row) {
                $existingClient = Client::where('client_id', $row['Client ID'])->first();

                $clients[] = [
                    'account_username' => $row['Name'],
                    'plan' => $planIds[$row['Plan']],
                    'client_id' => $row['Client ID'],
                    'username' => $row['Username'],
                    'phone_number' => $row['Phone Number'],
                    'email' => $row['Email Address'],
                    'gps' => $row['GPS Location (Ghana Post Number)'],
                    'expiry_date' => $row['Expiry Date'],
                    'node' => $row['Node'],
                    'referal_bonus' => $row['Referral Bonus'],
                    'installation_type' => $row['Installation Type'],
                    'status' => $row['STATUS'],
                    'cpe_outdoor' => $row['CPE-OUTOOR'],
                    'cpe_indoor' => $row['CPE-INDOOR']
                ];

                if ($existingClient) {
                    // Update the existing client
                    Client::where('client_id', $row['Client ID'])->update($clients[0]);
                    unset($clients[0]); // Remove the element to avoid duplicate insert
                    $clients = array_values($clients); // Re-index the array

                }else {

                    // Insert new client
                    $newClient = Client::create($clients[0]);
                    unset($clients[0]); // Remove the element to avoid duplicate insert
                    $clients = array_values($clients); // Re-index the array

                    $expiry_date = !empty($newClient->expiry_date) ? \Carbon\Carbon::parse($newClient->expiry_date) : NULL;

                    // Create default renew
                    $renew = new Renew([
                        'client_id' => $newClient->id,
                        'package_id' => $planIds[$row['Plan']], // Replace with actual default package ID
                        'renew_date' => \Carbon\Carbon::now(),
                        'expiry_date' => $expiry_date,
                    ]);

                    $renew->save();
                }
            }

            // Batch insert new clients
            if (!empty($clients)) {
                Client::insert($clients);
            }

            return response()->json([
                'message' => 'Clients imported successfully.',
                'data' => $clients
            ]);
        } catch (\Exception $e) {
            return response()->json(['error' => $e->getMessage()], 400);
        }
    }

    
    public function addClient(Request $request)
    {
        try {

            $plan = $request->input('plan');
            if (empty($plan)) {
                throw new \Exception('Plan cannot be empty');
            }
            // Capture the request data
            $data = [
                // 'account_balance' => $request->input('accountBalance'),
                // 'first_name' => $request->input('firstName'),
                // 'last_name' => $request->input('lastName'),
                'username' => $request->input('username'),
                'account_username' => $request->input('accountUsername'),
                'client_id' => $request->input('clientId'),
                'phone_number' => $request->input('phoneNumber'),
                'email' => $request->input('email'),
                'gps' => $request->input('gps'),
                'plan' => $request->input('plan'),
                'expiry_date' => date('d M Y', strtotime($request->input('expiryDate'))),
                'node' => $request->input('node'),
                'referal_bonus' => $request->input('referalBonus'),
                'installation_type' => $request->input('installationType'),
                'status' => $request->input('status'),
                'cpe_outdoor' => $request->input('cpeOutdoor'),
                'cpe_indoor' => $request->input('cpeIndoor')
            ];

            // return response()->json($data);

            // Check if the expiry date is greater than today's date
            $expiryDate = Carbon::parse($data['expiry_date']);
            $today = Carbon::now();

            if ($expiryDate->lte($today)) {
                throw new \Exception('Expiry date must be greater than today\'s date.');
            }

            // Check if the client already exists
            $existingClient = Client::where('email', $data['email'])->first();

            if ($existingClient) {
                // Client already exists, throw an exception or handle accordingly
                throw new \Exception('Client with this email already exists.');
            }

            // Begin a database transaction
            DB::beginTransaction();

            try {
                // Create a new client
                $client = Client::create($data);

                // Create a default renewal for the client
                $renew = new Renew([
                    'client_id' => $client->id,
                    'package_id' => $request->input('plan'), // Assuming the plan ID is used for the package_id
                    'renew_date' => Carbon::now(), // Use the current date as the renew date
                    'expiry_date' => \Carbon\Carbon::parse($request->input('expiryDate'))->format('d M Y'),                    
                ]);

                $renew->save();

                // Commit the transaction
                DB::commit();

                //send a welcome message to the client
                // $client_phone_number = $client->phone_number;
                // $client_phone_number = explode(',', $client_phone_number);

                // $sms = Sms::where('sms_type', 'Welcome Message')->get()[0];

                // $message = $sms->sms_content;                

                // foreach ($client_phone_number as $phoneNumber) {
                //     //get sms message 
                //     $this->send_sms($message, trim($phoneNumber));
                // }

                // Return the client data as a JSON response
                return response()->json($client);
            } catch (\Exception $e) {
                // Rollback the transaction in case of an exception
                DB::rollBack();

                // Re-throw the exception
                throw $e;
            }
        } catch (\Exception $e) {
            // Handle exceptions (e.g., client already exists)
            return response()->json(['error' => $e->getMessage()], 400);
        }
    }

    public function clientWallet(Request $request){
        //get the client wallet
        $wallet = Wallet::where('client_id', $request->client_id)->first();

        if (!$wallet) {
            return response()->json(['error' => 'Wallet does not exist for this client.'], 404);
        }

        return response()->json($wallet);
    }

    public function renewClient(Request $request)
    {
        // return response()->json($request->all());
        try {
            $client = Client::findOrFail($request->client_id);

            if (!$client->expiry_date) {
                throw new \Exception('Expiry date does not exist for this client.');
            }

            $renew_type = $request->renew_type;
            // // get the package amount
            $package = Package::find($request->package_id);

            // // get client wallet
            $wallet = Wallet::where('client_id', $client->id)->first();

            if($renew_type == 'renew_with_payment'){
                if (!$wallet || (doubleval($wallet->balance) < doubleval($package->price))) {
            
                $renew_date = \Carbon\Carbon::now()->format('d M Y');

                // Create a new Renew instance and save it
                $renew = new Renew([
                    'client_id' => $request->client_id,
                    'package_id' => $request->package_id,
                    'renew_type' => $request->renew_type,
                    'renew_date' => $renew_date,
                    'expiry_date' => \Carbon\Carbon::parse($renew_date)->addDays(29)->format('d M Y'),
                ]);

                $renew->save();

                $payment = new Payment([
                    'amount' => $package->price,
                    'client_id' => $request->client_id,
                    'payment_transaction_id' => $renew->id,
                    'payment_type' => 'on_time',
                    'payment_reason' => 'renewal',
                    'payment_date' => \Carbon\Carbon::now(),
                ]);

                $payment->save();

                $client->expiry_date = $renew->expiry_date;
                $client->plan = $request->package_id;
                $client->status = 'Active';

                $client->save();


                //Sending message to client
                $client_phone_number = $client->phone_number;
                $client_phone_number = explode(',', $client_phone_number);

                foreach ($client_phone_number as $phoneNumber) {
                    /*
                    Message should be like this:
                    Date: 15th March 2024
                    Received from: Client name
                    The sum of: Amount entered in payments
                    Being payment for internet subscription
                    Thank you
                    */
                    $message = "Date: " . date('jS F Y') . "\n";
                    $message .= "Received from: " . $client->account_username . "\n";
                    $message .= "The sum of: " . $package->price . "\n";
                    $message .= "Being the payment for: " .  $package->data_package . "\n"; 
                    $message .= "Expiry date: " . $renew->expiry_date . "\n";
                    $message .= "Thank you";

                    // Send the SMS
                    $this->send_sms($message, trim($phoneNumber));
                    $smsHistory = new SmsHistory;
                    $smsHistory->phone_number = $phoneNumber;
                    $smsHistory->message = $message;
                    $smsHistory->status = 'sent';
                    $smsHistory->save();

                }

                //Get the admin user details and send sms to his phone number
                $admin = User::where('user_role', 'admin')->first();
                $phoneNumbers = explode(',', $admin->phone_number);

                // Get SMS where sms feature is 1
                $sms = Sms::where('sms_feature', '1')->get()[0];

                foreach ($phoneNumbers as $phoneNumber) {
                    // Construct the message
                    $message = "Date: " . date('jS F Y') . "\n";
                    $message .= "Received from: " . $client->account_username . "\n";
                    $message .= "The sum of: " . $package->price . "\n";
                    $message .= "Being the payment for: " .  $package->data_package . "\n"; 
                    $message .= "Expiry date: " . $renew->expiry_date . "\n";
                    $message .= "Thank you";

                    // Send the SMS
                    $this->send_sms($message, trim($phoneNumber));
                    $smsHistory = new SmsHistory;
                    $smsHistory->phone_number = $phoneNumber;
                    $smsHistory->message = $message;
                    $smsHistory->status = 'sent';
                    $smsHistory->save();
                }
                // $this->send_sms('Your subscription has been renewed. Your new expiry date is ' . $renew->expiry_date, $client->phone_number);            

                // Return a success response
                return response()->json(['message' => 'Subscription renewed successfully']);
                }
            
                if((doubleval($wallet->balance) >= doubleval($package->price))){

                    $renew_date = \Carbon\Carbon::now()->format('d M Y');

                    // Create a new Renew instance and save it
                    $renew = new Renew([
                        'client_id' => $request->client_id,
                        'package_id' => $request->package_id,
                        'renew_type' => $request->renew_type, // 'renew_with_payment
                        'renew_date' => $renew_date,
                        'expiry_date' => \Carbon\Carbon::parse($renew_date)->addDays(29)->format('d M Y'),
                    ]);

                    $renew->save();

                    $wallet->balance -= $package->price;

                    $wallet->save();

                    $payment = new Payment([
                        'wallet_id' => $wallet->id,
                        'amount' => $package->price,
                        'client_id' => $request->client_id,
                        'payment_transaction_id' => $renew->id,
                        'payment_type' => 'early_payment',
                        'payment_reason' => 'renewal',
                        'payment_date' => \Carbon\Carbon::now(),
                    ]);

                    $payment->save();

                    $client->expiry_date = $renew->expiry_date;
                    $client->plan = $request->package_id;
                    $client->status = 'Active';

                    $client->save();

                    $client_phone_number = $client->phone_number;
                    $client_phone_number = explode(',', $client_phone_number);


                    foreach ($client_phone_number as $phoneNumber) {
                        /*
                        Message should be like this:
                        Date: 15th March 2024
                        Received from: Client name
                        The sum of: Amount entered in payments
                        Being payment for internet subscription
                        Thank you
                        */
                        $message = "Date: " . date('jS F Y') . "\n";
                        $message .= "Received from: " . $client->account_username . "\n";
                        $message .= "The sum of: " . $package->price . "\n";
                        $message .= "Being the payment for: " .  $package->data_package . "\n"; 
                        $message .= "Expiry date: " . $renew->expiry_date . "\n";
                        $message .= "Thank you";

                        // Send the SMS
                        $this->send_sms($message, trim($phoneNumber));
                        $smsHistory = new SmsHistory;
                        $smsHistory->phone_number = $phoneNumber;
                        $smsHistory->message = $message;
                        $smsHistory->status = 'sent';
                        $smsHistory->save();

                    }


                    //Get the admin user details and send sms to his phone number
                    $admin = User::where('user_role', 'admin')->first();
                    // $this->send_sms('The subscription for ' . $client->account_username . ' has been renewed. The new expiry date is ' . $renew->expiry_date, $admin->phone_number);
                    $phoneNumbers = explode(',', $admin->phone_number);

                    // foreach ($phoneNumbers as $phoneNumber) {
                    //     $this->send_sms('The subscription for ' . $client->account_username . ' has been renewed. The new expiry date is ' . $renew->expiry_date, trim($phoneNumber));
                    // }

                    // Get SMS where sms feature is 1
                    $sms = Sms::where('sms_feature', '4')->get()[0];

                    foreach ($phoneNumbers as $phoneNumber) {
                        // Construct the message
                        $message = "Date: " . date('jS F Y') . "\n";
                        $message .= "Received from: " . $client->account_username . "\n";
                        $message .= "The sum of: " . $package->price . "\n";
                        $message .= "Being the payment for: " . $package->data_package . "\n"; 
                        $message .= "Expiry date: " . $renew->expiry_date . "\n";
                        $message .= "Thank you";

                        // Send the SMS
                        $this->send_sms($message, trim($phoneNumber));
                        $smsHistory = new SmsHistory;
                        $smsHistory->phone_number = $phoneNumber;
                        $smsHistory->message = $message;
                        $smsHistory->status = 'sent';
                        $smsHistory->save();

                    }
                    // $this->send_sms('Your subscription has been renewed. Your new expiry date is ' . $renew->expiry_date, $client->phone_number);            

                    return response()->json(['message' => 'Subscription renewed successfully']);
                }
            }else{
                //implement the renew without payment
                $renew_date = \Carbon\Carbon::now()->format('d M Y');

                // Create a new Renew instance and save it
                $renew = new Renew([
                    'client_id' => $request->client_id,
                    'package_id' => $request->package_id,
                    'renew_type' => $request->renew_type, // 'renew_without_payment
                    'renew_date' => $renew_date,
                    'expiry_date' => \Carbon\Carbon::parse($renew_date)->addDays(29)->format('d M Y'),
                ]);

                $renew->save();

                $client->expiry_date = $renew->expiry_date;
                $client->plan = $request->package_id;
                $client->status = 'Active';

                $client->save();

                //Sending sms to client
                $client_phone_number = $client->phone_number;
                $client_phone_number = explode(',', $client_phone_number);

                 foreach ($client_phone_number as $phoneNumber) {
                    /*
                    Message should be like this:
                    Date: 15th March 2024
                    Received from: Client name
                    The sum of: Amount entered in payments
                    Being payment for internet subscription
                    Thank you
                    */
                    
                    $message = "Date: " . date('jS F Y') . "\n";
                    $message .= "Received from: " . $client->account_username . "\n";
                    $message .= "The package: " . $package->data_package . " has been renewed without payment.\n"; 
                    $message .= "Expiry date: " . $renew->expiry_date . "\n";
                    $message .= "Thank you";
                

                    // Send the SMS
                    $this->send_sms($message, trim($phoneNumber));
                    $smsHistory = new SmsHistory;
                    $smsHistory->phone_number = $phoneNumber;
                    $smsHistory->message = $message;
                    $smsHistory->status = 'sent';
                    $smsHistory->save();
                }

                //Get the admin user details and send sms to his phone number
                $admin = User::where('user_role', 'admin')->first();

                $adminPhoneNumbers = explode(',', $admin->phone_number);

                // foreach ($phoneNumbers as $phoneNumber) {
                //     $this->send_sms('The subscription for ' . $client->account_username . ' has been renewed. The new expiry date is ' . $renew->expiry_date, trim($phoneNumber));
                // }

                // Get SMS where sms feature is 1
                $sms = Sms::where('sms_feature', '4')->get()[0];

                foreach ($adminPhoneNumbers as $adminPhoneNumber) {
                    // Construct the message
                    $message = "Date: " . date('jS F Y') . "\n";
                    $message .= "Received from: " . $client->account_username . "\n";
                    $message .= "The package: " . $package->data_package . " has been renewed without payment.\n"; 
                    $message .= "Expiry date: " . $renew->expiry_date . "\n";
                    $message .= "Thank you";
                    
                    // Send the SMS
                    $this->send_sms($message, trim($adminPhoneNumber));
                    $smsHistory = new SmsHistory;
                    $smsHistory->phone_number = $adminPhoneNumber;
                    $smsHistory->message = $message;
                    $smsHistory->status = 'sent';
                    $smsHistory->save();
                }
                // $this->send_sms('Your subscription has been renewed. Your new expiry date is ' . $renew->expiry_date, $client->phone_number);

                return response()->json(['message' => 'Subscription renewed successfully']);
            }
            
        } catch (\Exception $e) {
            // Handle other exceptions
            return response()->json(['error' => $e->getMessage()], 500);
        }
    }

    public function edit($id)
    {
        $client = Client::leftJoin('wallets', 'clients.id', '=', 'wallets.client_id')
                        ->where('clients.id', $id)
                        ->select('clients.*', 'wallets.id as wallet_id', 'wallets.balance as wallet_balance')
                        ->first();

        $node = DB::table('stations')->where('node_uuid', $client->node)->get();

        if (!$client) {
            return response()->json(['message' => 'Client not found'], 404);
        }

        // // return response()->json(empty($nodes));

        // if (!empty($nodes)) {
        //     $client->node_name = $nodes[0]->node_name;
        // } else {
        //     $client->node_name = null; // or some default value
        // }
        
        return response()->json(["client"=>$client, "node"=>$node]);
    }

    public function update(Request $request)
    {
        $id = $request->input('id');
        try {
            // Validate the request data if needed
            $client = Client::findOrFail($id);

            $wallet = Wallet::where('id',  $request->wallet_id)->first();
    
            if ($wallet) {
                $wallet->balance = $request->input('wallet');
            } else {
                $wallet = new Wallet([
                    'client_id' => $client->id,
                    'balance' => $request->input('wallet')
                ]);
            }

            $wallet->save();

            $client->update([
                'username' => $request->input('username'),
                'account_username' => $request->input('accountUsername'),
                'client_id' => $request->input('clientId'),
                'phone_number' => $request->input('phoneNumber'),
                'email' => $request->input('email'),
                'gps' => $request->input('gps'),
                'plan' => $request->input('plan'),
                'expiry_date' => date('d M Y', strtotime($request->input('expiryDate'))),
                'node' => $request->input('edit-node'),
                'referal_bonus' => $request->input('referalBonus'),
                'installation_type' => $request->input('installationType'),
                'status' => $request->input('status'),
                'cpe_outdoor' => $request->input('cpeOutdoor'),
                'cpe_indoor' => $request->input('cpeIndoor')
            ]);

            // Get the last renew for the client
            $renew = Renew::where('client_id', $client->id)->orderBy('created_at', 'desc')->first();

            if ($renew) {
                if ($request->has('expiryDate') && !empty($request->input('expiryDate'))) {
                    $expiry_date = date('d M Y', strtotime($request->input('expiryDate')));
                    $renew->update(['expiry_date' => $expiry_date]);
                }

                if ($request->has('plan') && !empty($request->input('plan'))) {
                    $package_id = $request->input('plan');
                    $renew->update(['package_id' => $package_id]);
                }
            }

            // Optionally, you can return a response or redirect after the update
            return response()->json(['message' => 'Client updated successfully']);
        } catch (\Exception $e) {            
            // Return a response with the error message
            // return response()->json(['error' => 'An error occurred while updating the client.'], 500);
            return response()->json(['error' => $e->getMessage()], 500);        
        }
    }

    public function delete($id)
    {
        $client = Client::find($id);

        if (!$client) {
            return response()->json(['message' => 'Client not found'], 404);
        }

        $client->delete();

        return response()->json(['message' => 'Client deleted']);
    }

    public function receiptsById($id)
    {
        try {
            // Get the receipts for the client
            $receipts = Renew::where('client_id', $id)->get();

            $receipts = Renew::join('packages', 'renews.package_id', '=', 'packages.id')
            ->where('renews.client_id', $id)
            ->select('renews.*', 'packages.data_package', 'packages.price', 'packages.package_type') // Add other fields as needed
            ->get();

            // Return the receipts as a JSON response
            return response()->json(['receipts' => $receipts]);
        } catch (\Exception $e) {
            // Handle exceptions (e.g., client not found)
            return response()->json(['error' => $e->getMessage()], 404);
        }
    }

    public function deleteClients(Request $request)
    {
        try {
            // Get the array of client IDs from the request
            $clientIds = $request->input('clients');

            // Delete the renews that reference the clients
            Renew::whereIn('client_id', $clientIds)->delete();

            // Delete the clients
            Client::whereIn('id', $clientIds)->delete();

            // Return a success response
            return response()->json(['message' => 'Clients deleted successfully.']);
        } catch (\Exception $e) {
            // Handle exceptions (e.g., client not found)
            return response()->json(['error' => $e->getMessage()], 400);
        }
    }

    
    public function searchClients(Request $request)
    {
        try {
             $search = $request->input('search');

             $query = Client::query();

            if (!empty($search)) {
                $query->where('account_username', 'like', "%$search%")
                    ->orWhere('client_id', 'like', "%$search%")
                    ->orWhere('username', 'like', "%$search%")
                    ->orWhere('phone_number', 'like', "%$search%")
                    ->orWhere('email', 'like', "%$search%")
                    ->orWhere('gps', 'like', "%$search%")
                    ->orWhere('node', 'like', "%$search%")
                    ->orWhere('referal_bonus', 'like', "%$search%")
                    ->orWhere('installation_type', 'like', "%$search%")
                    ->orWhere('status', 'like', "%$search%")
                    ->orWhere('cpe_outdoor', 'like', "%$search%")
                    ->orWhere('expiry_date','like', "%$search%")
                    ->orWhere('cpe_indoor', 'like', "%$search%");
            }

            $clients = $query->join('packages', 'clients.plan', '=', 'packages.id')
                ->select('clients.*', 'packages.data_package', 'packages.price', 'packages.package_type')
                ->take(30)
                ->get();

            $packages = DB::table('packages')->get();

            $clientRenewals = DB::table('renews')
                ->whereIn('client_id', $clients->pluck('id'))
                ->orderBy('id', 'asc')
                ->get();

            $renewalsByClientId = $clientRenewals->keyBy('client_id');

            $clients->transform(function ($client) use ($renewalsByClientId) {
                $lastRenewal = $renewalsByClientId->get($client->id);

                if ($lastRenewal) {
                    $client->last_renew_date = $lastRenewal->renew_date;
                    $client->last_expiry_date = $lastRenewal->expiry_date;
                    $client->is_renewed = $this->isClientRenewed($lastRenewal->expiry_date);
                } else {
                    $client->last_renew_date = null;
                    $client->last_expiry_date = null;
                    $client->is_renewed = false;
                }

                return $client;
            });

            return response()->json(['clients' => $clients]);
        } catch (\Exception $e) {
            return response()->json(['error' => $e->getMessage()], 400);
        }
    }

    public function defaultRenewal(){
        $clients = Client::all();
        $renews = [];

        foreach ($clients as $client) {
            $expiry_date = isset($client->expiry_date) ? ($client->expiry_date) : null;
            // Prepare data for bulk insert
            $renews[] = [
                'client_id' => $client->id,
                'package_id' => $client->plan, // Replace with actual default package ID
                'renew_date' => \Carbon\Carbon::now()->format('d M Y'),
                'expiry_date' => $expiry_date,
            ];
        }

        // Bulk insert
        Renew::insert($renews);

        return response()->json(['message' => 'Default renewals created successfully']);
    }

    public function crontest()
    {
        try {
            // $this->send_sms('Cron job started', '0506596743');

            //Get client where id is 45
        //    $client = Client::find(45);

        //     //send sms to client
        //     $client_phone_number = $client->phone_number;

        //     $client_phone_number = explode(',', $client_phone_number);

        //     foreach ($client_phone_number as $phoneNumber) {
        //         echo $client->account_username;

        //         //check if account_username contains ME3 Café and Pastries and send a define a hard code message for them
        //         if(strpos($client->account_username, 'ME3 Café and Pastries') !== false){
        //             $message = 'Dear ME3 Cafe and Pastries, your subscription expires on ' . $client->expiry_date . '. Thank you';
        //         } else {
        //             $message = "Dear ".$client->account_username. ", your current subscription expires on ".$client->expiry_date.". Thank you";
        //         }

        //         // Convert the message to UTF-16
        //         $message = mb_convert_encoding($message, 'UTF-16', 'UTF-8');

        //         // Send the SMS
        //         $this->send_sms($message, trim($phoneNumber));
        //     }

        //     // return
        //     return response()->json(['message' => 'Cron job completed']);
            // Get the current date
            $now = \Carbon\Carbon::now();

            // Get all clients
            $clients = Client::all();

            $admin = User::where('user_role', 'admin')->first();
            $adminPhoneNumbers = explode(',', $admin->phone_number);

            // $this->send_sms(implode(", ", $adminPhoneNumbers), '0506596743');

            // Loop through each client
            foreach ($clients as $client) {
                // Convert the expiry_date to a date object
                $expiryDate = \DateTime::createFromFormat('d M Y', $client->expiry_date);
                // echo "<pre>";
                // print_r('Client: ' . $client->account_username . ', Expiry Date: ' . $expiryDate->format('Y-m-d H:i:s') . ', Now: ' . $now->format('Y-m-d H:i:s'));                
                // print_r($expiryDate > $now ? ' true' : 'false');
                // continue;

                //explode client phone_number
                $clientsPhoneNumbers = explode(',',$client->phone_number);

                // Check if $expiryDate is a valid DateTime object
                if ($expiryDate instanceof \DateTime && $expiryDate > $now) {
                    // Check if the expiry date is one day away
                    if ($expiryDate->diff($now)->days == 1) {
                        // Send an SMS to the client
                        foreach($clientsPhoneNumbers as $clientPhoneNumber){

                            if(strpos($client->account_username, 'ME3 Café and Pastries') !== false){
                                $smsMessage = 'Dear ME3 Cafe and Pastries, your subscription expires on ' . $client->expiry_date . '. Thank you';
                            } else {
                                $smsMessage = "Dear ".$client->account_username. ", your current subscription expires on ".$client->expiry_date.". Thank you";
                            }

                            // $smsMessage = 'Dear '.$client->account_username. ', your current subscription expires on '.$client->expiry_date.'. Thank you';
                            $this->send_sms($smsMessage, $clientPhoneNumber);
                            $smsHistory = new SmsHistory;
                            $smsHistory->phone_number = $clientPhoneNumber;
                            $smsHistory->message = $smsMessage;
                            $smsHistory->status = 'sent';
                            $smsHistory->save();
                        }

                        // Send an SMS to the admin
                        foreach($adminPhoneNumbers as $adminPhoneNumber){
                            if(strpos($client->account_username, 'ME3 Café and Pastries') !== false){
                                $smsMessage = 'Dear ME3 Cafe and Pastries, your subscription expires on ' . $client->expiry_date . '. Thank you';
                            } else {
                                $smsMessage = "Dear ".$client->account_username. ", your current subscription expires on ".$client->expiry_date.". Thank you";
                            }

                            //$smsMessage = 'Dear admin, '.$client->account_username. ' subscription expires on '.$client->expiry_date.'. Thank you';
                            $this->send_sms($smsMessage, $adminPhoneNumber);
                            $smsHistory = new SmsHistory;
                            $smsHistory->phone_number = $adminPhoneNumber;
                            $smsHistory->message = $smsMessage;
                            $smsHistory->status = 'sent';
                            $smsHistory->save();
                        } 
                    }

                    //send sms to client and admin exactly on the expiry date

                    if ($expiryDate->diff($now)->days == 0) {
                        // Send an SMS to the client
                        foreach($clientsPhoneNumbers as $clientsPhoneNumber){
                            $smsMessage = 'Dear '.$client->account_username. ', your current subscription expires on '.$client->expiry_date.'. Thank you';
                            $this->send_sms($smsMessage, $clientsPhoneNumber);
                            $smsHistory = new SmsHistory;
                            $smsHistory->phone_number = $clientsPhoneNumber;
                            $smsHistory->message = $smsMessage;
                            $smsHistory->status = 'sent';
                            $smsHistory->save();
                        }

                        // // Send an SMS to the admin
                        // $admin = User::where('user_role', 'admin')->first();

                        // $adminPhoneNumbers = explode(',', $admin->phone_number);

                        foreach($adminPhoneNumbers as $adminPhoneNumber){
                            $smsMessage = 'Dear admin, '.$client->account_username. ' subscription expires on '.$client->expiry_date.'. Thank you';
                            $this->send_sms($smsMessage, $adminPhoneNumber);
                            $smsHistory = new SmsHistory;
                            $smsHistory->phone_number = $adminPhoneNumber;
                            $smsHistory->message = $smsMessage;
                            $smsHistory->status = 'sent';
                            $smsHistory->save();
                        }
                    }
                    
                    // Check if the expiry date is one week away
                    if ($expiryDate->diff($now)->days == 7 && $expiryDate > $now) {
                        // Send an SMS to the client
                        foreach($clientsPhoneNumbers as $clientsPhoneNumber){
                            $smsMessage = 'Dear '.$client->account_username. ', your current subscription expires on '.$client->expiry_date.'. Thank you';
                            $this->send_sms($smsMessage, $clientsPhoneNumber);
                            $smsHistory = new SmsHistory;
                            $smsHistory->phone_number = $clientsPhoneNumber;
                            $smsHistory->message = $smsMessage;
                            $smsHistory->status = 'sent';
                            $smsHistory->save();


                        }

                        // Send an SMS to the admin
                        // $admin = User::where('user_role', 'admin')->first();

                        // $adminPhoneNumbers = explode(',', $admin->phone_number);

                        foreach($adminPhoneNumbers as $adminPhoneNumber){
                            $smsMessage = 'Dear admin, '.$client->account_username. ' subscription expires on '.$client->expiry_date.'. Thank you';
                            $this->send_sms($smsMessage, $adminPhoneNumber);
                            $smsHistory = new SmsHistory;
                            $smsHistory->phone_number = $adminPhoneNumber;
                            $smsHistory->message = $smsMessage;
                            $smsHistory->status = 'sent';
                            $smsHistory->save();
                        }
                    }
                    
                } else {
                    //save the error message.
                    continue;
                }
            }
            $this->send_sms('Cron job completed', '0506596743');
            return response()->json(['message' => 'Cron job executed successfully']);
        } catch (\Exception $e) {
            return response()->json(['error' => $e->getMessage()], 500);
        }
    }

    public function subscription_auto_renewal(){
        //if client subscription is due for renewal, renew the subscription
        // Get the current date
        $now = \Carbon\Carbon::now();

        // Get all clients
        $clients = Client::all();

        // Loop through each client
        foreach ($clients as $client) {
            // Convert the expiry_date to a date object
            $expiryDate = \DateTime::createFromFormat('d M Y', $client->expiry_date);

            // Check if $expiryDate is a valid DateTime object
            if ($expiryDate instanceof \DateTime && $expiryDate < $now) {
                //get the client wallet
                $wallet = Wallet::where('client_id', $client->id)->first();

                //get the client package
                $package = Package::find($client->plan);

                //get the client renew
                $renew = Renew::where('client_id', $client->id)->orderBy('created_at', 'desc')->first();

                //check if wallet is null return error message
                if(!$wallet){
                    continue;
                }

                //check if the client has enough balance in his wallet
                if($wallet->balance >= $package->price){
                    //renew the client subscription
                    $renew_date = \Carbon\Carbon::now()->format('d M Y');

                    // Create a new Renew instance and save it
                    $renew = new Renew([
                        'client_id' => $client->id,
                        'package_id' => $client->plan,
                        'renew_type' => 'auto_renewal',
                        'renew_date' => $renew_date,
                        'expiry_date' => \Carbon\Carbon::parse($renew_date)->addDays(29)->format('d M Y'),
                    ]);

                    $renew->save();

                    $wallet->balance -= $package->price;

                    $wallet->save();

                    $payment = new Payment([
                        'wallet_id' => $wallet->id,
                        'amount' => $package->price,
                        'client_id' => $client->id,
                        'payment_transaction_id' => $renew->id,
                        'payment_type' => 'auto_renewal',
                        'payment_reason' => 'renewal',
                        'payment_date' => \Carbon\Carbon::now(),
                    ]);

                    $payment->save();

                    $client->expiry_date = $renew->expiry_date;
                    $client->plan = $client->plan;
                    $client->status = 'Active';

                    $client->save();

                    //Sending sms to client
                    $client_phone_number = $client->phone_number;
                    $client_phone_number = explode(',', $client_phone_number);

                    foreach ($client_phone_number as $phoneNumber) {
                        /* Message should be like this: Date: 15th March 2024 Received from: Client name The sum of: Amount entered in payments Being payment for internet subscription Thank you */
                        $message = "Date: " . date('jS F Y') . "\n";
                        $message .= "Received from: " . $client->account_username . "\n";
                        $message .= "The sum of: " . $package->price . "\n";
                        $message .= "Being the payment for: " .  $package->data_package . "\n";
                        $message .= "Expiry date: " . $renew->expiry_date . "\n";
                        $message .= "Thank you";

                        // Send the SMS
                        $this->send_sms($message, trim($phoneNumber));
                        $smsHistory = new SmsHistory;
                        $smsHistory->phone_number = $phoneNumber;
                        $smsHistory->message = $message;
                        $smsHistory->status = 'sent';
                        $smsHistory->save();

                    }  

                    //Get the admin user details and send sms to his phone number
                    $admin = User::where('user_role', 'admin')->first();
                    $adminPhoneNumbers = explode(',', $admin->phone_number);

                    foreach ($adminPhoneNumbers as $adminPhoneNumber) {
                        $message = "Date: " . date('jS F Y') . "\n";
                        $message .= "Received from: " . $client->account_username . "\n";
                        $message .= "The sum of: " . $package->price . "\n";
                        $message .= "Being the payment for: " .  $package->data_package . "\n";
                        $message .= "Expiry date: " . $renew->expiry_date . "\n";
                        $message .= "Thank you";

                        // Send the SMS
                        $this->send_sms($message, trim($adminPhoneNumber));
                        $smsHistory = new SmsHistory;
                        $smsHistory->phone_number = $adminPhoneNumber;
                        $smsHistory->message = $message;
                        $smsHistory->status = 'sent';
                        $smsHistory->save();
                    }

                    // Return a success response
                    return response()->json(['message' => 'Subscription renewed successfully']);

                }

            }
        }             
    }
}
