<?php

namespace App\Http\Controllers;

use App\Console\Commands\SpeedyPersoBulkSms;
use App\DataTables\TmpGroupSmsDataTable;
use App\Filters;
use App\Imports\BulkSmsImport;
use App\Imports\PersonalisedSmsImport;
use App\LogReceived;
use App\SavedMessage;
use App\SmsImage;
use App\TargetedCampaign;
use App\UserJob;
use App\Log;
use App\UserSenderId;
use Carbon\Carbon;
use GuzzleHttp\Client;
use Illuminate\Http\Request;
use Illuminate\Http\File;
use Illuminate\Support\Facades\Auth;
use App\Tools\SmsTools;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use Maatwebsite\Excel\Facades\Excel;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

class SmsController extends Controller
{
    public function send_single_sms(Request $request)
    {
        $step = 1;
        //reset current session data for sending single sms
        if ($request->session()->has('single_sms_data')) {
            $request->session()->forget('single_sms_data');
        }
        if ($request->session()->has('alert')) {
            $request->session()->forget('alert');
        }
        //show view :11xx
        return view('sms.send_single_sms', [
            'step' => $step,
            'sms_count' => null,
            'sender_ids' => UserSenderId::query()->where([['user_id', Auth::user()->id], ['status', 1]])->get()
        ]);
    }

    public function send_targeted_sms(Request $request)
    {
        $step = 1;
        //reset current session data for sending single sms
        if ($request->session()->has('single_sms_data')) {
            $request->session()->forget('single_sms_data');
        }
        if ($request->session()->has('alert')) {
            $request->session()->forget('alert');
        }
        //show view :11xx
        return view('sms.send_targeted_sms', [
            'step' => $step,
            'sms_count' => null,
            'sender_ids' => UserSenderId::query()->where([['user_id', Auth::user()->id], ['status', 1]])->get()
        ]);
    }

    public function post_send_single_sms(Request $request)
    {
        //get current user
        $user = Auth::user();
        $credit = $user->credit;

        $myUsername = $user->username;
        $myPassword = $request->session()->get('myPassword');


        //get current step
        $step = $request->get('step', 1);

        //process for step 1
        if ($step == 1) {
            //validate the request
            $tank = $this->validate($request, [
                'phone_numbers' => 'required',
                'sender_id' => 'required|max:11',
                'flash' => 'required|max:11',
                'schedule_date' => 'present',
                'message_content' => 'required',
                //                'image_upload' => 'image',
                'image_upload' => 'file|mimes:jpeg,jpg,png,gif'
            ]);
            $sd = $tank['schedule_date'];
            session(['s_date' => $sd]);

            $schedule_date = Carbon::parse($tank['schedule_date']);
            session(['tank_date' => $schedule_date]);

            $filters = Filters::query()->get();

            $banned = array();
            $flash = null;


            foreach ($filters as $filth)
                array_push($banned, strtolower($filth->keyword));


            $new_strings = explode(" ", strtolower($request->message_content));
            $result = array_intersect($banned, $new_strings);
            if (!empty($result)):
                foreach ($result as $value):
                    $flash .= $value . ', ';
                endforeach;
                return \redirect()->back()->withErrors("The words {$flash} are not permitted");
            endif;

            //get data for step 2
            $destination = explode(',', $request->get('phone_numbers'));


            $new_msg_text = preg_replace(array('/\r\n/'), array("\n"), trim($request->get('message_content', '')));
            $no_chars = mb_strlen($new_msg_text);
            $no_pages = SmsTools::no_pages($no_chars);


            $sms_count = $no_pages;

            $price = 0.0;
            foreach ($destination as $single_msisdn) {
                $network = SmsTools::get_msisdn_network($user, $single_msisdn);
                $price += (float)$network['sms_price'];
            }
            $cost = $no_pages * $price;
            // cost of sending one msg with this no_pages to one person
            $nummsisdn = count($destination);
            // no of recepients
            $tot_cost = $cost;

            $curr_bal = $credit->new_bal;
            $credit_used = $credit->credit_used;
            $this->loggingPushedSMS('', 'single-sms', "Abraham Log |$curr_bal| $cost");

            $rem_sms = floor($curr_bal / $cost);
            //remaining sms user can send

            $counter = floor($rem_sms / $no_pages);
            $some_cost = $cost * $counter;

            //            $price_per_sms = $cost;
            $recipients = $nummsisdn;
            $total_price = $tot_cost;
            $credit_available = $curr_bal;
            $imgId = null;

            //update image if image exist
            if (!empty($request['image_upload'])) {
                if ($request->file('image_upload')->isValid()) {
                    $current_filename = $request->file('image_upload')->getClientOriginalName();
                    $fileMimeType = $request->file('image_upload')->getMimeType();

                    $destinationPath = storage_path() . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR;
                    $fileName = $user->username . '_' . $current_filename;
                    $request->file('image_upload')->move($destinationPath, $fileName);
                    $full_path = $destinationPath . $fileName;
                    while (1) {
                        $imgId = uniqid();
                        if (empty(SmsImage::find($imgId))) {
                            break;
                        }
                    }
                    $user->sms_images()->create([
                        'path' => $full_path,
                        'file_name' => $current_filename,
                        'mime_type' => $fileMimeType,
                        'id' => $imgId
                    ]);
                } else {
                    return Redirect::back()->withInput()->withErrors(array('image_upload' => 'Sorry, The file upload failed!'));
                }
            }

            $msg = $new_msg_text;
            if (!empty($imgId)) {
                $sms_msg_url = route('sms_image', ['id' => $imgId]);
                $msg = $new_msg_text . "\n" . $sms_msg_url;
            }

            // clean message
            $msg = $this->cleanMessage($msg);

            //store user input in the new session data
            session(['single_sms_data' => [
                'phone_numbers' => $request->get('phone_numbers'),
                'sender_id' => $request->get('sender_id'),
                'message_type' => $request->get('message_type'),
                'flash' => $request->input('flash'),
                'message_content' => $msg,
                'recipients' => $recipients,
                'total_price' => $total_price,
                'credit_available' => number_format($credit_available, 3),
                'schedule_date' => Carbon::parse($request->get('schedule_date')),
            ]]);
            $step = 2;
        } elseif ($step == 2) {

            //check if next button was pressed
            if ($request->has('submit')) {
                session(['alert', []]);
                //send single sms now
                $destination = explode(',', session('single_sms_data')['phone_numbers']);
                $sender = session('single_sms_data')['sender_id'];
                $message_type = session('single_sms_data')['message_type'];
                $msgs = session('single_sms_data')['message_content'];
                $cost = session('single_sms_data')['total_price'];
                $flash = session('single_sms_data')['flash'];

                // cost of sending one msg with this no_pages to one person
                $nummsisdn = count($destination);
                $tot_cost = $cost;
                $curr_bal = $credit->new_bal;
                $rejected_arr = [];

                // Log submitted sms
                $this->loggingPushedSMS('', 'single-sms', $sender);

                if (isset(session('single_sms_data')['schedule_date']) && !empty(session('single_sms_data')['schedule_date'])) {
                    $sch_date = Carbon::parse(session('single_sms_data')['schedule_date']);
                    $now = Carbon::now();
                    $date = $now->lte($sch_date) ? $sch_date : $now;

                    $numbers = session('single_sms_data')['phone_numbers'];
                    $explodeNums = explode(',', $numbers);
                    $nummsisdn = count($explodeNums);
                    $numbers = str_replace(',', "\n", trim($numbers));

                    $destinationPath = storage_path() . DIRECTORY_SEPARATOR . 'bulk_sms' . DIRECTORY_SEPARATOR;
                    $fileNam = $user->username . '_' . date('YmdHis') . '.txt';
                    $myFilePath = storage_path('bulk_sms/' . $fileNam);
                    file_put_contents($myFilePath, $numbers);


                    if (Carbon::parse(session('s_date')) > Carbon::now()) {
                        $job = new UserJob([
                            'username' => $user->username,
                            'sender' => $sender,
                            'message' => $msgs,
                            'sms_count' => SmsTools::no_pages(strlen($msgs)),
                            'type' => 'bulk',
                            'message_type' => $message_type,
                            'sched_datetime' => session('s_date'),
                            'status' => 'pending',
                            'created_by' => $user->username,
                            'file_path' => $myFilePath,
                            'name' => $user->username . '_single_campaign',
                            'total_traffic' => $nummsisdn,
                            'remove_duplicate' => 0,
                            'flash' => 'text'
                        ]);

                        $user->jobs()->save($job);

                        $user->audit_trails()->create([
                            'username' => $user->username,
                            'date' => Carbon::now()->toDateTimeString(),
                            'activity' => $user->username . ' scheduled a single sms to ' . $nummsisdn . ' msisdns'
                        ]);
                        $request->session()->flash('success', $nummsisdn . ' message(s) successfully scheduled!');

                        return view('sms.send_single_sms', [
                            'step' => $step,
                            'sms_count' => $sms_count ?? null,
                            'sender_ids' => UserSenderId::query()->where([['user_id', Auth::user()->id], ['status', 1]])->get()
                        ]);
                    }

                } else {
                    $date = Carbon::now();
                }

                $oneMinuteLater = Carbon::now()->addMinutes(1);
                $sentItNow = $date->lte($oneMinuteLater);
                $data = [];

                if ($curr_bal >= $tot_cost) {
                    $count = 0;
                    $no_rej_msisdn = 0;
                    while ($count !== $nummsisdn) {
                        $number = self::format_phone_number($destination[$count]);
                        $msisdn = preg_replace('/\D/', '', $number);
                        $msisdn = SmsTools::msisdn_prep($msisdn);
                        $msisdn = trim($msisdn);
                        if (is_numeric($msisdn)) {
                            while (1) {
                                $id = uniqid('NS', true);
                                if (empty(Log::find($id)))
                                    break;
                            }
                            if ($sentItNow == false) {
                                $data[] = $msisdn;
                            } else {
//                                $user->pending_single_sms()->create([
//                                    'msisdn' => $msisdn,
//                                    'sender' => $sender,
//                                    'message_type' => $message_type,
//                                    'message' => $msgs,
//                                    'flash' => $flash,
//                                    'sched_datetime' => $date < now() ? now()->addMinutes(1) : $date,
//                                ]);
                                $msgs = $this->cleanMessage($msgs);
                                $myMessage = urlencode($msgs);
                                $sender = urlencode($sender);

                                if ($message_type == 'unicode') {
                                    $directSubmit = file_get_contents("https://deywuro.com/api/sms?username=$myUsername&password=$myPassword&source=$sender&destination=$msisdn&message=$myMessage&ol=true");
                                } else {
                                    $directSubmit = file_get_contents("https://deywuro.com/api/sms?username=$myUsername&password=$myPassword&source=$sender&destination=$msisdn&message=$myMessage");
                                }
                                $this->logging($now, 'Single SMS fired|', $directSubmit);
                            }
                        } else {
                            array_push($rejected_arr, $msisdn);
                            $request->session()->push('alert', $msisdn . ' not successful');
                        }
                        $no_rej_msisdn = count($rejected_arr);
                        //counts number of rejected contacts
                        $count++;
                    }

                    if ($sentItNow == false) {
                        foreach ($data as $dat) {
                            //                            $user->pending_single_sms()->create([
                            //                                'msisdn' => $dat,
                            //                                'sender' => $sender,
                            //                                'message_type' => $message_type,
                            //                                'message' => $msgs,
                            //                                'flash' => $flash,
                            //                                'sched_datetime' => $date < now() ? now()->addMinutes(1) : $date,
                            //                            ]);


                            $msgs = $this->cleanMessage($msgs);
                            $myMessage = urlencode($msgs);
                            $sender = urlencode($sender);
                            if ($message_type == 'unicode') {
                                $directSubmit = file_get_contents("https://deywuro.com/api/sms?username=$myUsername&password=$myPassword&source=$sender&destination=$msisdn&message=$myMessage&ol=true");
                            } else {
                                $directSubmit = file_get_contents("https://deywuro.com/api/sms?username=$myUsername&password=$myPassword&source=$sender&destination=$msisdn&message=$myMessage");
                            }
                            $this->logging($now, 'Single SMS fired|', $directSubmit);
                        }

                        //update audit trails
                        $user->audit_trails()->create([
                            'username' => $user->username,
                            'date' => Carbon::now()->toDateTimeString(),
                            'activity' => $user->username . ' sent a single sms to ' . count($data) . ' msisdn'
                        ]);

                        $logged = count($data);

                        if ($no_rej_msisdn == 0) {
                            $request->session()->flash('success', $logged . ' message(s) successfully scheduled!');
                        } else {
                            $request->session()->flash('success', $logged . ' messages successfully scheduled, ' . $no_rej_msisdn . ' rejected');
                        }
                    } else {
                        $logged = $nummsisdn - $no_rej_msisdn;
                        $logged = $nummsisdn - $no_rej_msisdn;

                        //update audit trails
                        $user->audit_trails()->create([
                            'username' => $user->username,
                            'date' => Carbon::now()->toDateTimeString(),
                            'activity' => $user->username . ' sent a single sms to ' . $logged . ' msisdn'
                        ]);

                        if ($no_rej_msisdn == 0) {
                            $request->session()->flash('success', $logged . ' message(s) successfully sent!');
                        } else {
                            $request->session()->flash('success', $logged . ' message(s) successfully sent!, ' . $no_rej_msisdn . ' rejected');
                        }
                    }
                } else {
                    return Redirect::back()->withInput()->withErrors(array('error' => 'Sorry, you don\'t have enough credit to proceed!'));
                }

                //reset session
                $step = 0;
                $request->session()->forget('single_sms_data');
                if (!$request->session()->has('success') || empty(session('success')))
                    $request->session()->flash('success', 'Your SMS Message has been successfully sent!');
            } //in case back button was pressed
            else {
                //go back to step 1
                $step = 1;
            }
        }
        return view('sms.send_single_sms', ['step' => $step, 'sms_count' => $sms_count ?? null, 'sender_ids' => UserSenderId::query()->where([['user_id', Auth::user()->id], ['status', 1]])->get()]);
    }


    public function post_send_targeted_sms(Request $request)
    {
        //get current user
        $user = Auth::user();
        $credit = $user->credit;

        $myUsername = $user->username;
        $myPassword = $request->session()->get('myPassword');


        //get current step
        $step = $request->get('step', 1);

        //process for step 1
        if ($step == 1) {
            //validate the request
            $tank = $this->validate($request, [
                'phone_numbers' => 'nullable',
                'sender_id' => 'required|max:11',
                'campaign_name' => 'required',
//                'flash' => 'required|max:11',
                'schedule_date' => 'present',
                'message_content' => 'required',
                'demographics' => 'required|array|min:1', // At least one demographic must be selected
                'total_reach' => 'nullable',
                //                'image_upload' => 'image',
//                'image_upload' => 'file|mimes:jpeg,jpg,png,gif'
            ]);
            $sd = $tank['schedule_date'];
            session(['s_date' => $sd]);

            $schedule_date = Carbon::parse($tank['schedule_date']);
            session(['tank_date' => $schedule_date]);

            $filters = Filters::query()->get();

            $banned = array();
            $flash = null;


            foreach ($filters as $filth)
                array_push($banned, strtolower($filth->keyword));


            $new_strings = explode(" ", strtolower($request->message_content));
            $result = array_intersect($banned, $new_strings);
            if (!empty($result)):
                foreach ($result as $value):
                    $flash .= $value . ', ';
                endforeach;
                return \redirect()->back()->withErrors("The words {$flash} are not permitted");
            endif;

            //get data for step 2
            $destination = explode(',', $request->get('phone_numbers'));


            $new_msg_text = preg_replace(array('/\r\n/'), array("\n"), trim($request->get('message_content', '')));
            $no_chars = mb_strlen($new_msg_text);
            $no_pages = SmsTools::no_pages($no_chars);


            $sms_count = $no_pages;

            $price = 0.0;
            foreach ($destination as $single_msisdn) {
                $network = SmsTools::get_msisdn_network($user, $single_msisdn);
                $price += (float)$network['sms_price'];
            }
            $cost = $no_pages * $price;
            // cost of sending one msg with this no_pages to one person
            $nummsisdn = count($destination);
            // no of recepients
            $tot_cost = $cost;

            $curr_bal = $credit->new_bal;
            $credit_used = $credit->credit_used;
            $this->loggingPushedSMS('', 'single-sms', "Abraham Log |$curr_bal| $cost");

            $rem_sms = floor($curr_bal / $cost);
            //remaining sms user can send

            $counter = floor($rem_sms / $no_pages);
            $some_cost = $cost * $counter;

            //            $price_per_sms = $cost;
            $recipients = $nummsisdn;
            $total_price = $tot_cost;
            $credit_available = $curr_bal;
            $imgId = null;

            $msg = $new_msg_text;

            //store user input in the new session data
            session(['targeted_sms_data' => [
                'phone_numbers' => $request->get('phone_numbers'),
                'sender_id' => $request->get('sender_id'),
                'message_type' => $request->get('message_type'),
                'flash' => $request->input('flash'),
                'message_content' => $msg,
                'demographics' => $request->input('demographics'),
                'total_reach' => $request->input('total_reach'),
                'recipients' => $recipients,
                'total_price' => $total_price,
                'campaign_name' => $request->input('campaign_name'),
                'credit_available' => number_format($credit_available, 3),
                'schedule_date' => Carbon::parse($request->get('schedule_date')),
            ]]);
            $step = 2;
        } elseif ($step == 2) {

            //check if next button was pressed
            if ($request->has('submit')) {
                session(['alert', []]);
                //send single sms now
                $destination = explode(',', session('targeted_sms_data')['phone_numbers']);
                $sender = session('targeted_sms_data')['sender_id'];
                $message_type = session('targeted_sms_data')['message_type'];
                $msgs = session('targeted_sms_data')['message_content'];
                $cost = session('targeted_sms_data')['total_price'];
                $campaign_name = session('targeted_sms_data')['campaign_name'];
                $total_reach = session('targeted_sms_data')['total_reach'];
                $demographics = session('targeted_sms_data')['demographics'];
                $flash = session('targeted_sms_data')['flash'];

                // cost of sending one msg with this no_pages to one person
                $nummsisdn = count($destination);
                $tot_cost = $cost;
                $curr_bal = $credit->new_bal;
                $rejected_arr = [];

                // Log submitted sms
                $this->loggingPushedSMS('', 'single-sms', $sender);

                if (isset(session('targeted_sms_data')['schedule_date']) && !empty(session('targeted_sms_data')['schedule_date'])) {
                    $sch_date = Carbon::parse(session('targeted_sms_data')['schedule_date']);
                    $now = Carbon::now();
                    $date = $now->lte($sch_date) ? $sch_date : $now;

                    $numbers = session('targeted_sms_data')['phone_numbers'];
                    $explodeNums = explode(',', $numbers);
                    $nummsisdn = count($explodeNums);
                    $numbers = str_replace(',', "\n", trim($numbers));

                    foreach ($demographics as $key => $demographic){
                        $campaign = TargetedCampaign::query()->create([
                            'username' => $user->username,
                            'sender' => $sender,
                            'message' => $msgs,
                            'sms_count' => SmsTools::no_pages(strlen($msgs)),
                            'type' => 'bulk',
                            'message_type' => $message_type,
                            'sched_datetime' => session('s_date'),
                            'status' => 'pending',
                            'created_by' => $user->username,
                            'file_path' => null,
                            'name' => $campaign_name . '_'.$key,
                            'total_traffic' => $total_reach,
                            'remove_duplicate' => 1,
                            'flash' => 'text',
                            'target_audience' => json_encode($demographics)
                        ]);

                    }
                        $user->audit_trails()->create([
                            'username' => $user->username,
                            'date' => Carbon::now()->toDateTimeString(),
                            'activity' => $user->username . ' scheduled targeted sms campaign ' . $campaign_name . ' for '.session('targeted_sms_data')['schedule_date']
                        ]);
                        $request->session()->flash('success', $nummsisdn . ' campaign successfully scheduled!');

                        return view('sms.send_targeted_sms', [
                            'step' => $step,
                            'sms_count' => $sms_count ?? null,
                            'sender_ids' => UserSenderId::query()->where([['user_id', Auth::user()->id], ['status', 1]])->get()
                        ]);

                } else {
                    return Redirect::back()->withInput()->withErrors(array('error' => 'Sorry, you don\'t have enough credit to proceed!'));
                }

                //reset session
                $step = 0;
                $request->session()->forget('targeted_sms_data');
                if (!$request->session()->has('success') || empty(session('success')))
                    $request->session()->flash('success', 'Your SMS Message has been successfully sent!');
            } //in case back button was pressed
            else {
                //go back to step 1
                $step = 1;
            }
        }
        return view('sms.send_targeted_sms', ['step' => $step, 'sms_count' => $sms_count ?? null, 'sender_ids' => UserSenderId::query()->where([['user_id', Auth::user()->id], ['status', 1]])->get()]);
    }


    public function send_bulk_sms(Request $request)
    {
        $step = 1;
        //reset current session data for sending single sms
        if ($request->session()->has('bulk_sms_data')) {
            $request->session()->forget('bulk_sms_data');
        }
        if ($request->session()->has('alert')) {
            $request->session()->forget('alert');
        }

        //get templates
        $templates = SavedMessage::where('user_id', auth()->user()->id)->get();

        //show view:1xx
        return view('sms.send_bulk_sms', [
            'step' => $step,
            'templates' => $templates,
            'sender_ids' => UserSenderId::query()->where([['user_id', Auth::user()->id], ['status', 1]])->get()
        ]);
    }

    public function post_send_bulk_sms(Request $request)
    {
        //get current user
        $user = Auth::user();
        $credit = $user->credit;

        //get current step
        $step = $request->get('step', 1);

        //process for step 1
        if ($step == 1) {
            //validate the request
            $tank = $this->validate($request, [
                'file_upload' => 'required|mimes:csv,txt,xlsx,xls',
                'sender_id' => 'required|max:11',
                'schedule_date' => 'present',
                'message_content' => 'required',
                'name' => 'required',
                'image_upload' => 'file|mimes:jpeg,jpg,png,gif'
            ]);

            $schedule_date = Carbon::parse($tank['schedule_date']);
            session(['tank_date' => $schedule_date]);

            /***  We get the filters from here ***/
            $filters = Filters::query()->get();
            /** @var  $banned @as an array for the newly filtered records */
            $banned = array();
            /** @var  $flash @for linear array */
            $flash = null;

            /** @var  $filth @foreach to loop through keywords  * */
            foreach ($filters as $filth)
                array_push($banned, strtolower($filth->keyword));

            /** @var  $new_strings @exploding occurs here  * */
            $new_strings = explode(" ", strtolower($request->message_content));
            $result = array_intersect($banned, $new_strings);
            if (!empty($result)):
                foreach ($result as $value):
                    $flash .= $value . ', ';
                endforeach;
                return \redirect()->back()->withErrors("The following words are not permitted:  {$flash}");
            endif;

            /** @var  @the rest @occurs here */
            $current_filename = $request->file('file_upload')->getClientOriginalName();
            $filename_splitted = explode(".", $current_filename);
            $extension = end($filename_splitted);

            $destinationPath = storage_path() . DIRECTORY_SEPARATOR . 'bulk_sms' . DIRECTORY_SEPARATOR;
            $fileName = $user->username . '_' . date('YmdHis') . '.' . $extension;
            $full_filename = $destinationPath . $fileName;

            if ($request->file('file_upload')->isValid()) {
                $request->file('file_upload')->move($destinationPath, $fileName);
                @chmod($full_filename, 0777);
            } else {
                return Redirect::back()->withInput()->withErrors(array('file_upload' => 'Sorry, The file upload failed!'));
            }

            // Initialize recipient count
            $highestRow = 0;

            try {
                // Efficiently count records without loading the entire file into memory
                switch (strtolower($extension)) {
                    case 'csv':
                        $highestRow = $this->countCsvLines($full_filename) - 1; // -1 for header (if exists)
                        break;

                    case 'txt':
                        $highestRow = $this->countTextFileLines($full_filename);
                        break;

                    case 'xlsx':
                        $highestRow = $this->countExcelRows($full_filename, 'xlsx');
                        break;

                    case 'xls':
                        $highestRow = $this->countExcelRows($full_filename, 'xls');
                        break;

                    default:
                        return Redirect::back()->withInput()->withErrors(array('file_upload' => 'Unsupported file format!'));
                }
            } catch (\Throwable $e) {
                return Redirect::back()->withInput()->withErrors(array('file_upload' => $e->getMessage() . ' Error! Your file is invalid!'));
            }

            // If no recipients found
            if ($highestRow <= 0) {
                return Redirect::back()->withInput()->withErrors(array('file_upload' => 'Error! No valid recipients found in file!'));
            }

            //get data for step 2
            $new_msg_text = preg_replace(array('/\r\n/'), array("\n"), trim($request->get('message_content', '')));
            $imgId = null;

            //update image if image exist
            if (!empty($request['image_upload'])) {
                if ($request->file('image_upload')->isValid()) {
                    $current_filename = $request->file('image_upload')->getClientOriginalName();
                    $fileMimeType = $request->file('image_upload')->getMimeType();

                    $destinationPath = storage_path() . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR;
                    $fileName = $user->username . '_' . $current_filename;
                    $request->file('image_upload')->move($destinationPath, $fileName);
                    $full_path = $destinationPath . $fileName;
                    while (1) {
                        $imgId = uniqid();
                        if (empty(SmsImage::find($imgId))) {
                            break;
                        }
                    }
                    $user->sms_images()->create([
                        'path' => $full_path,
                        'file_name' => $current_filename,
                        'mime_type' => $fileMimeType,
                        'id' => $imgId
                    ]);
                } else {
                    return Redirect::back()->withInput()->withErrors(array('image_upload' => 'Sorry, The file upload failed!'));
                }
            }

            $msg = $new_msg_text;
            if (!empty($imgId)) {
                $original_sms_msg_url = route('view_sms_image', ['id' => $imgId]);
                $sms_msg_url = $this->get_tiny_url($original_sms_msg_url);
                $msg = $new_msg_text . "\n" . $sms_msg_url;
            }

            $no_pages = SmsTools::no_pages(strlen($msg));
            $sms_cost = $highestRow * $no_pages * auth()->user()->credit->price;
            $user_balance = auth()->user()->credit->new_bal;

            if ($sms_cost > $user_balance)
                return redirect()->back()->withErrors("You do not have sufficient balance to do the blast.
            Total cost is $sms_cost and your current balance is $user_balance");

            // clean message
            $msg = $this->cleanMessage($msg);

            //store user input in the new session data
            session(['bulk_sms_data' => [
                'phone_numbers' => $current_filename,
                'no_pages' => $no_pages,
                'sender_id' => $request->get('sender_id'),
                'flash' => $request->get('flash'),
                'message_content' => $msg,
                'recipients' => $highestRow,
                'path' => $full_filename,
                'message_type' => $request->input('message_type'),
                'credit_available' => number_format($credit->new_bal, 2),
                'schedule_date' => $request->input('schedule_date'),
                'name' => $request->get('name'),
                'remove_duplicate' => $request->has('remove_duplicate'),
                'file_extension' => $extension
            ]]);

            $step = 2;
        } //process for step 2
        else if ($step == 2) {
            //check if next button was pressed
            if ($request->has('submit')) {
                $no_chars = strlen(session('bulk_sms_data')['message_content']);
                $sender = session('bulk_sms_data')['sender_id'];
                $flash = session('bulk_sms_data')['flash'];
                $nummsisdn = session('bulk_sms_data')['recipients'];
                $msgs = session('bulk_sms_data')['message_content'];
                $path = session('bulk_sms_data')['path'];
                $name = session('bulk_sms_data')['name'];
                $message_type = session('bulk_sms_data')['message_type'];
                $remove_duplicate = session('bulk_sms_data')['remove_duplicate'];
                $file_extension = session('bulk_sms_data')['file_extension'] ?? '';
                $no_pages = SmsTools::no_pages($no_chars);
                $curr_bal = $credit->new_bal;

                //remaining sms user can send
                // Log submitted sms
                $this->loggingPushedSMS($name, 'bulk-sms', $sender);

                if (isset(session('bulk_sms_data')['schedule_date']) && !empty(session('bulk_sms_data')['schedule_date'])) {
                    $sch_date = Carbon::parse(session('bulk_sms_data')['schedule_date']);
                    $now = Carbon::now()->addMinutes(1);
                    $date = $now->lte($sch_date) ? $sch_date : $now;
                } else {
                    $date = Carbon::now()->addMinutes(1);
                }

                if ($nummsisdn * $credit->price <= $curr_bal) {
                    //Create a job
                    $status = 'pending';
                    if (strtoupper($user->username) == 'SCBULK' || strtoupper($user->username) == 'GCBCARDS') {
                        $status = 'Awaiting approval';
                    }

                    $job = new UserJob([
                        'username' => $user->username,
                        'sender' => $sender,
                        'message' => $msgs,
                        'sms_count' => $no_pages,
                        'type' => 'bulk',
                        'message_type' => $message_type,
                        'sched_datetime' => $date < now() ? now()->addMinutes(1) : $date,
                        'status' => $status,
                        'created_by' => $user->username,
                        'file_path' => $path,
                        'name' => $name,
                        'total_traffic' => $nummsisdn,
                        'remove_duplicate' => $remove_duplicate,
                        'flash' => $flash,
                        'file_extension' => $file_extension, // Added this to help the job processor know how to handle the file
                        'use_chunk_processing' => true // Flag to indicate we want to use chunk processing
                    ]);

                    if (empty($sender)) {
                        return redirect()->route('app');
                    }

                    $user->jobs()->save($job);

                    //update audit trails
                    $user->audit_trails()->create([
                        'username' => $user->username,
                        'date' => Carbon::now()->toDateTimeString(),
                        'activity' => $user->username . ' sent a bulk sms to ' . $nummsisdn . ' msisdn'
                    ]);

                    // Send bulk blast alert to all
                    $send_schdule_time = $date < now() ? now()->addMinutes(1) : $date;
                    $send_alert_contacts = explode(',', env('BLAST_ALERT_CONTACT'));
                    $send_alert_message = "Bulk SMS for {$user->username} ({$job->id})
SenderID: $sender
Volume: $nummsisdn
Scheduled Time: $send_schdule_time";

                    foreach ($send_alert_contacts as $contact) {
                        $this->sendSmsNew($send_alert_message, $contact, 'Blast Alert');
                    }

                    try{
                        $url = 'https://ticketingtoolapi.snwolley.com/api/create/ticket';
                        $data = ['username' => 'talerts',
                            'password' => 'password',
                            'title' => 'Bulk Blast Alert',
                            'type' => 'REQUEST',
                            'priority' => 3,
                            'description' => $send_alert_message,
                        ];
                        $client = new \GuzzleHttp\Client();
                        $response = $client->request('POST', $url, ['form_params' => $data]);
                    } catch (\Exception $exception){
                        \Illuminate\Support\Facades\Log::error('ERROR CREATING TICKET '.$exception->getMessage());
                    }

                    //send blast alert
                    $alertThreshold = intval(env('BLAST_ALERT', 100));
                    if (intval($nummsisdn) >= $alertThreshold) {
                        SmsTools::sendBlastAlert($user, $nummsisdn);
                    }

                    $request->session()->flash('success', 'The contacts were successfully uploaded!');
                } else {
                    return Redirect::back()->withInput()->withErrors(array('error' => 'Sorry, you don\'t have enough credit to proceed!'));
                }

                //reset session
                $step = 0;
                $request->session()->forget('bulk_sms_data');
                if (!$request->session()->has('success') || empty(session('success')))
                    $request->session()->flash('success', 'Your contacts were successfully uploaded!');
            } //in case back button was pressed
            else {
                //go back to step 1
                $step = 1;
            }
        }

        $templates = SavedMessage::where('user_id', auth()->id())->get();
        return view('sms.send_bulk_sms', [
            'step' => $step,
            'templates' => $templates,
            'pages' => $no_pages ?? null,
            'sender_ids' => UserSenderId::query()->where([['user_id', Auth::user()->id], ['status', 1]])->get()
        ]);
    }

    /**
     * Count lines in a CSV file efficiently without loading the entire file
     *
     * @param string $filePath Path to the CSV file
     * @return int Number of non-empty lines in the file
     */
    private function countCsvLines($filePath)
    {
        $lineCount = 0;
        $handle = fopen($filePath, "r");

        if ($handle === false) {
            throw new \Exception("Unable to open file: $filePath");
        }

        while(!feof($handle)){
            $line = fgets($handle);
            if (!empty(trim($line))) {
                $lineCount++;
            }
        }

        fclose($handle);
        return $lineCount;
    }

    /**
     * Count lines in a text file efficiently
     *
     * @param string $filePath Path to the text file
     * @return int Number of non-empty lines in the file
     */
    private function countTextFileLines($filePath)
    {
        $lineCount = 0;
        $handle = fopen($filePath, "r");

        if ($handle === false) {
            throw new \Exception("Unable to open file: $filePath");
        }

        while(!feof($handle)){
            $line = fgets($handle);
            if (!empty(trim($line))) {
                $lineCount++;
            }
        }

        fclose($handle);
        return $lineCount;
    }

    /**
     * Count rows in an Excel file efficiently without loading all content
     *
     * @param string $filePath Path to the Excel file
     * @param string $type Excel file type (xlsx or xls)
     * @return int Number of rows with data
     */
    private function countExcelRows($filePath, $type)
    {
        if ($type == 'xlsx') {
            // For xlsx files, use a stream reader approach
            try {
                $reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();
                $reader->setReadDataOnly(true);
                // Just read cell count, not formatting or other data
                $reader->setReadEmptyCells(false);

                // Create a filter to count only
                $chunkFilter = new class implements \PhpOffice\PhpSpreadsheet\Reader\IReadFilter {
                    public $rowCount = 0;

                    public function readCell($columnAddress, $row, $worksheetName = '') {
                        $this->rowCount = max($this->rowCount, $row);
                        return false; // Don't actually load the cell
                    }
                };

                $reader->setReadFilter($chunkFilter);
                $reader->load($filePath);

                return $chunkFilter->rowCount;
            } catch (\Exception $e) {
                // Fallback method if the direct count method fails
                return $this->countExcelRowsFallback($filePath);
            }
        } else if ($type == 'xls') {
            // For xls files, use a different approach
            try {
                $reader = new \PhpOffice\PhpSpreadsheet\Reader\Xls();
                $reader->setReadDataOnly(true);
                $reader->setReadEmptyCells(false);

                // Same filter as xlsx
                $chunkFilter = new class implements \PhpOffice\PhpSpreadsheet\Reader\IReadFilter {
                    public $rowCount = 0;

                    public function readCell($columnAddress, $row, $worksheetName = '') {
                        $this->rowCount = max($this->rowCount, $row);
                        return false; // Don't actually load the cell
                    }
                };

                $reader->setReadFilter($chunkFilter);
                $reader->load($filePath);

                return $chunkFilter->rowCount;
            } catch (\Exception $e) {
                // Fallback
                return $this->countExcelRowsFallback($filePath);
            }
        }

        throw new \Exception("Unsupported Excel file type");
    }

    /**
     * Fallback method to count Excel rows when other methods fail
     * This uses a streaming approach to count lines
     *
     * @param string $filePath Path to the Excel file
     * @return int Estimated number of rows
     */
    private function countExcelRowsFallback($filePath)
    {
        // Use a different calculation method - convert to CSV in memory and count lines
        try {
            // Create a temporary file
            $tempFile = tempnam(sys_get_temp_dir(), 'excel_convert');

            // Convert first sheet only to CSV
            $command = "ssconvert --export-type=Gnumeric_stf:stf_csv {$filePath} {$tempFile} 2>/dev/null";
            shell_exec($command);

            if (file_exists($tempFile)) {
                // Count the lines
                $lineCount = $this->countCsvLines($tempFile);
                unlink($tempFile); // Remove temp file
                return $lineCount - 1; // Subtract header row
            }
        } catch (\Exception $e) {
            // If all else fails, use a reasonable estimate based on file size
            $fileSize = filesize($filePath);
            // Rough estimate: assume average 100 bytes per row
            return max(1, intval($fileSize / 100));
        }

        // Last resort fallback
        return 1000; // Return a default estimate
    }

    public function send_group_sms(Request $request, TmpGroupSmsDataTable $dataTable)
    {
        if ($request->has('draw')) {
            return $dataTable->render('sms.send_group_sms', ['step' => 2]);
        }

        $step = 1;
        //reset current session data for sending group sms
        if ($request->session()->has('group_sms_data')) {
            $request->session()->forget('group_sms_data');
        }
        if ($request->session()->has('alert')) {
            $request->session()->forget('alert');
        }

        //fetch user groups
        $groups = $request->user()->groups()->orderBy('name', 'asc')->get(['name', 'id']);

        //get templates
        $templates = SavedMessage::where('user_id', auth()->id())->get();

        //show view
        return view('sms.send_group_sms', [
            'step' => $step,
            'groups' => $groups,
            'templates' => $templates,
            'sender_ids' => UserSenderId::query()->where([['user_id', Auth::user()->id], ['status', 1]])->get()
        ]);
    }

    public function post_send_group_sms(Request $request, TmpGroupSmsDataTable $dataTable)
    {
        //get current user
        $user = Auth::user();
        $credit = $user->credit;

        //get current step
        $step = $request->get('step', 1);

        //process for step 1
        if ($step == 1) {
            //validate the request
            $tank = $this->validate($request, [
                'selected_group' => 'required',
                'sender_id' => 'required|max:11',
                'schedule_date' => 'present',
                'message_content' => 'required',
                'name' => 'required',
                //                'image_upload' => 'image',
                'image_upload' => 'file|mimes:jpeg,jpg,png,gif'
            ]);

            $schedule_date = Carbon::parse($tank['schedule_date']);

            session(['tank_date' => $schedule_date]);

            $filters = Filters::query()->get();

            $banned = array();
            $flash = null;


            foreach ($filters as $filth)
                array_push($banned, strtolower($filth->keyword));


            $new_strings = explode(" ", strtolower($request->message_content));
            $result = array_intersect($banned, $new_strings);

            if (!empty($result)):
                foreach ($result as $value):
                    $flash .= $value . ', ';
                endforeach;
                return redirect()->back()->withErrors("The following words are not permitted:  {$flash}");
            endif;


            $highestRow = 0;
            $selected_groups = $request->get('selected_group');
            $group_name = '';
            $data = [];

            DB::beginTransaction();
            $user->tmp_group_sms()->delete();

            if (!empty($selected_groups))
                $to_insert = [];
            foreach ($selected_groups as $group_id) {
                $group = $user->groups()->find($group_id);
                if (!empty($group)) {
                    $group_name .= ($group->name . ', ');
                    $highestRow += $group->contacts()->count();
                    $group->contacts()->chunk(5000, function ($contacts)
                    use (&$user, &$to_insert) {
                        foreach ($contacts as $contact) {

                            //                                $existing = DB::table('tmp_group_sms')->where([
                            //                                    ['user_id', '=', $user->id],
                            //                                    ['msisdn', '=', $contact->phone_number]
                            //                                ])->first();
                            //
                            //                                if (empty($existing)) {
                            //                                    DB::table('tmp_group_sms')->insert([
                            //                                        'user_id' => $user->id,
                            //                                        'name' => $contact->name,
                            //                                        'msisdn' => $contact->phone_number
                            //                                    ]);
                            //                                }

                            $var1 = $user->id;
                            $var2 = $contact->phone_number;

                            $existing = array_filter($to_insert, function ($val) use ($var1, $var2) {
                                return ($val['user_id'] == $var1 and $val['msisdn'] == $var2);
                            });


                            if (empty($existing)) {
                                array_push($to_insert, [
                                    'user_id' => $user->id,
                                    'name' => $contact->name,
                                    'msisdn' => $contact->phone_number
                                ]);
                            }
                        }
                    });
                }
            }
            DB::table('tmp_group_sms')->insert($to_insert);

            DB::commit();

            $imgId = null;

            //update image if image exist
            if (!empty($request['image_upload'])) {
                if ($request->file('image_upload')->isValid()) {
                    $current_filename = $request->file('image_upload')->getClientOriginalName();
                    $fileMimeType = $request->file('image_upload')->getMimeType();

                    $destinationPath = storage_path() . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR;
                    $fileName = $user->username . '_' . $current_filename;
                    $request->file('image_upload')->move($destinationPath, $fileName);
                    $full_path = $destinationPath . $fileName;
                    while (1) {
                        $imgId = uniqid();
                        if (empty(SmsImage::find($imgId))) {
                            break;
                        }
                    }
                    $user->sms_images()->create([
                        'path' => $full_path,
                        'file_name' => $current_filename,
                        'mime_type' => $fileMimeType,
                        'id' => $imgId
                    ]);
                } else {
                    return Redirect::back()->withInput()->withErrors(array('image_upload' => 'Sorry, The file upload failed!'));
                }
            }

            $new_msg_text = preg_replace(array('/\r\n/'), array("\n"), trim($request->get('message_content', '')));
            $msg = $new_msg_text;
            if (!empty($imgId)) {
                $sms_msg_url = route('sms_image', ['id' => $imgId]);
                $msg = $new_msg_text . "\n" . $sms_msg_url;
            }

            // clean message
            $msg = $this->cleanMessage($msg);

            //store user input in the new session data
            session(['group_sms_data' => [
                'group_name' => $group_name,
                'sender_id' => $request->get('sender_id'),
                'message_content' => $msg,
                'message_type' => $request->input('message_type'),
                'flash' => $request->input('flash'),
                'groups' => $selected_groups,
                'schedule_date' => Carbon::parse($request->get('schedule_date')),
                'name' => $request->get('name'),
                'selected_group' => $request->get('selected_group')
            ]]);
            $step = 2;
        } //process for step 2
        else if ($step == 2) {
            //check if next button was pressed
            if ($request->has('next')) {
                $highestRow = $user->tmp_group_sms()->count();
                //check if user can send sms
                if ($highestRow > 0) {
                    //do the calculation and move to step 3
                    //get data for step 2
                    $no_chars = strlen(session('group_sms_data')['message_content']);
                    $no_pages = SmsTools::no_pages($no_chars);

                    $price = 0.0;
                    foreach ($user->tmp_group_sms as $tempp) {
                        $network = SmsTools::get_msisdn_network($user, $tempp->msisdn);
                        $price += (float)$network['sms_price'];
                    }
                    $cost = $no_pages * $price;
                    // cost of sending one msg with this no_pages to one person
                    $nummsisdn = $highestRow;
                    $tot_cost = $cost;
                    $curr_bal = $credit->new_bal;


                    $recipients = $nummsisdn;
                    $total_price = $tot_cost;
                    $credit_available = $curr_bal;

                    session(['group_sms_data' => [
                        'group_name' => session('group_sms_data')['group_name'],
                        'sender_id' => session('group_sms_data')['sender_id'],
                        'message_content' => session('group_sms_data')['message_content'],
                        'groups' => session('group_sms_data')['groups'],
                        'flash' => session('group_sms_data')['flash'],
                        'message_type' => session('group_sms_data')['message_type'],
                        'recipients' => $recipients,
                        'total_price' => $total_price,
                        'credit_available' => number_format($credit_available, 3),
                        'schedule_date' => session('group_sms_data')['schedule_date'],
                        'name' => session('group_sms_data')['name'],
                        'selected_group' => session('group_sms_data')['selected_group'],
                    ]]);

                    //move to step 3
                    $step = 3;
                } else {
                    //prevent user from access step3
                    $request->session()->flash('error_msg', 'Kindly add some phone number(s)');
                    $step = 2;
                }
            } else if ($request->has('add_msisdn_btn')) {
                $input = $request->get('add_msisdn_input');
                if (empty(trim($input))) {
                    $request->session()->flash('error_msg', 'Kindly enter the msisdn to be added');
                }

                $tmp_msisdn_list = explode(',', $input);
                $added = 0;
                if (!empty($tmp_msisdn_list))
                    foreach ($tmp_msisdn_list as $temp) {
                        $temp = trim($temp);
                        if (!empty($temp)) {
                            if (!empty($user->tmp_group_sms()->where('msisdn', $temp)->first())) {
                                $request->session()->flash('error_msg', $temp . ' already exists in the list!');
                                break;
                            }
                            $user->tmp_group_sms()->create(['msisdn' => $temp]);
                            $added++;
                        }
                    }
                if ($added > 0)
                    $request->session()->flash('success_msg', $added . ' msisdn added to the list!');
                $step = 2;
            } else if ($request->has('delete_item')) {
                $input = $request->get('delete_item');
                $contact = $user->tmp_group_sms()->where('msisdn', $input)->first();
                if (!empty($contact)) {
                    $contact->delete();
                    $request->session()->flash('success_msg', $input . ' was deleted from the list!');
                } else {
                    $request->session()->flash('error_msg', $input . ' not found in the list!');
                }
                $step = 2;
            } else if ($request->has('delete_selection')) {
                $selection = $request->get('selection');
                $deleted = 0;
                if (!empty($selection))
                    foreach ($selection as $msisdn) {
                        $contact = $user->tmp_group_sms()->where('msisdn', $msisdn)->first();
                        if (!empty($contact)) {
                            $contact->delete();
                            $deleted++;
                        } else {
                            $request->session()->flash('error_msg', $msisdn . ' not found in the list!');
                        }
                    }
                if ($deleted > 0)
                    $request->session()->flash('success_msg', $deleted . ' msisdn deleted from the list!');
                $step = 2;
            } //in case back button was pressed
            else if ($request->has('back')) {
                //go back to step 1
                $step = 1;
            }
        } else if ($step == 3) {
            //check if next button was pressed
            if ($request->has('submit')) {
                $no_chars = strlen(session('group_sms_data')['message_content']);
                $sender = session('group_sms_data')['sender_id'];
                $message_type = session('group_sms_data')['message_type'];
                $nummsisdn = session('group_sms_data')['recipients'];
                $msgs = session('group_sms_data')['message_content'];
                $flash = session('group_sms_data')['flash'];
                $name = session('group_sms_data')['name'];
                if (!empty(session('group_sms_data')) && !empty(session('group_sms_data')['selected_group']))
                    $group_ids = implode(",", session('group_sms_data')['selected_group']);
                else
                    return back()->withInput(request()->all())->withErrors(['error' => 'The contact group is required!']);
                $cost = session('group_sms_data')['total_price'];

                $no_pages = SmsTools::no_pages($no_chars);

                $price = $credit->price;
                $tot_cost = $cost;

                $curr_bal = $credit->new_bal;

                //remaining sms user can send
                // Log submitted sms
                $this->loggingPushedSMS($name, 'bulk-group-sms', $sender);

                if (isset(session('group_sms_data')['schedule_date']) && !empty(session('group_sms_data')['schedule_date'])) {
                    $sch_date = Carbon::parse(session('group_sms_data')['schedule_date']);
                    $now = Carbon::now()->addMinutes(1);
                    $date = $now->lte($sch_date) ? $sch_date : $now;
                } else {
                    $date = Carbon::now()->addMinutes(1);
                }

                if ($curr_bal >= $tot_cost) {
                    //copy msisdn to excel file and add it to the pending job list
                    $destinationPath = storage_path('bulk_sms');
                    $fileName = $user->username . '_' . date('YmdHis');

                    try {

                        $spreadsheet = new Spreadsheet();
                        $sheet = $spreadsheet->getActiveSheet();
                        $sheet->setTitle('GROUP SMS Details');

                        $i = 1;
                        $data = $user->tmp_group_sms()->get();
                        foreach ($data as $dat) {
                            $sheet->setCellValue("A$i", $dat->msisdn);
                            $i++;
                        }

                        $writer = new Xlsx($spreadsheet);
                        $file_name = $fileName . '.xlsx';
                        $writer->save(storage_path("bulk_sms/$file_name"));

                        $user->tmp_group_sms()->delete();


                        //                        $res = Excel::create($fileName, function($excel) use (&$user) {
                        //                            // Set the title
                        //                            $excel->setTitle('GROUP SMS Details');
                        //                            // Chain the setters
                        //                            $excel->setCreator('Alphonse')->setCompany('Npontu');
                        //                            $excel->setDescription('Send Group SMS Details');
                        //
                        //                            $excel->sheet('Msisdn', function ($sheet) use (&$user) {
                        //                                $sheet->setOrientation('landscape');
                        //                                $i = 0;
                        //                                $data = $user->tmp_group_sms()->get();
                        //                                foreach ($data as $dat) {
                        //                                    $i++;
                        //                                    $sheet->appendRow($i, [$dat->msisdn]);
                        //                                }
                        //                                $user->tmp_group_sms()->delete();
                        //                            });
                        //                        })->store('xls', $destinationPath, true);


                    } catch (\Exception $e) {
                        $request->session()->flash('error_msg', 'Sorry, an error occurred while scheduling the blast!');
                        Log::error($e->getMessage());
                        $step = 3;
                        $templates = SavedMessage::where('user_id', auth()->id())->get();
                        return view('sms.send_group_sms', ['step' => $step, 'templates' => $templates]);
                    }
                    //Create a job
                    if (empty($sender)) {
                        return redirect()->route('app');
                    }

                    $res['full'] = "/var/www/html/deywuro_messenger/storage/bulk_sms/$file_name";
                    //Create a job
                    $status = 'pending';
                    if (strtoupper($user->username) == 'SCBULK' || strtoupper($user->username) == 'GCBCARDS') {
                        $status = 'Awaiting approval';
                    }


                    // Send bulk blast alert to all
                    $send_schdule_time = $date < now() ? now()->addMinutes(1) : $date;
		    $send_alert_contacts = explode(',', env('BLAST_ALERT_CONTACT'));
                    //$send_alert_contacts = ['233200154778', '0552837882', '233249173335', '0242219890', '0576907722', '233205663677', '0243375520', '0244304528', '0249430715', '233548617798', '233540882909'];
                    $send_alert_message = "Bulk-Grouped Details
                    Username: $user->username
                    SenderID: $sender
                    Volume: $nummsisdn
                    Campaign: $name
                    Scheduled Time: $send_schdule_time";
                    if ($nummsisdn >= 1000) {
                        foreach ($send_alert_contacts as $contact) {
                            $this->sendSmsNew($send_alert_message, $contact, 'Blast Alert');
                        }
                    }


                    UserJob::create([
                        'username' => $user->username,
                        'user_id' => $user->id,
                        'sender' => $sender,
                        'message' => $msgs,
                        'sms_count' => $no_pages,
                        'flash' => $flash,
                        'sched_datetime' => $date < now() ? now()->addMinutes(1) : $date,
                        'type' => 'group',
                        'message_type' => $message_type,
                        'status' => $status,
                        'created_by' => $user->username,
                        'file_path' => $res['full'],
                        'name' => $name,
                        'total_traffic' => $nummsisdn,
                        'group_ids' => $group_ids
                    ]);
                    @chmod($res['full'], 0777);

                    //update audit trails
                    $user->audit_trails()->create([
                        'username' => $user->username,
                        'date' => Carbon::now()->toDateTimeString(),
                        'activity' => $user->username . ' sent a group sms to ' . $nummsisdn . ' msisdn'
                    ]);

                    //send blast alert
                    $alertThreshold = intval(env('BLAST_ALERT', 100));
                    if (intval($nummsisdn) >= $alertThreshold) {
                        SmsTools::sendBlastAlert($user, $nummsisdn);
                    }

                    $request->session()->flash('success', 'The contacts was successfully uploaded!');
                } else {
                    $request->session()->flash('error_msg', 'Sorry, you don\'t have enough credit to proceed!');
                }

                //reset session
                $step = 0;
                $request->session()->forget('group_sms_data');
                if (!$request->session()->has('success') || empty(session('success')))
                    $request->session()->flash('success', 'Your contacts was successfully uploaded!');
            } //in case back button was pressed
            else {
                //go back to step 1
                $step = 2;
            }
        }

        $templates = SavedMessage::where('user_id', auth()->id())->get();

        if ($step == 1) {
            //fetch user groups
            $groups = $request->user()->groups()->orderBy('name', 'asc')->get(['name', 'id']);
            return view('sms.send_group_sms', [
                'step' => $step,
                'groups' => $groups,
                'templates' => $templates,
                'pages' => $no_pages ?? null,
                'sender_ids' => UserSenderId::query()->where([['user_id', Auth::user()->id], ['status', 1]])->get()
            ]);
        } else if ($step == 2) {
            return $dataTable->render('sms.send_group_sms', ['step' => $step, 'templates' => $templates, 'pages' => $no_pages ?? null,]);
        } else {

            return view('sms.send_group_sms', [
                'step' => $step,
                'templates' => $templates,
                'pages' => $no_pages,
                'sender_ids' => UserSenderId::query()->where([['user_id', Auth::user()->id], ['status', 1]])->get()
            ]);
        }
    }

    public function send_sms_dlr(Request $request)
    {

        DB::beginTransaction();

        $error_msg = null;
        $msgid = $request->input('msgID');
        $msg = $request->input('msg');
        $myid = $request->input('mid');
        $now = date('Y-m-d h:i:s');


        sleep(0.5);
        $this->logging($now, 'checking on..', $myid);

        $error_msg = $request->input('errorDescr');


        $error_code = SmsTools::get_string($msg, 'err:', 'text:');
        $status_desc = SmsTools::get_string($msg, 'stat:', 'err:');
        $submit_date = SmsTools::get_string($msg, 'submit date:', 'done date:');
        $sent = SmsTools::string_date($submit_date);


        $log_received = LogReceived::query()->find($myid);

        $this->logging($now, json_encode($log_received), $myid);

        $l_delivery_date = Carbon::now()->toDateTimeString();
        $l_sent_date = $sent;

        $l_msgid = !empty($log_received) ? $log_received->msgid : '';
        if ($l_msgid == '') {
            if (substr($msg, 0, 3) == 'id:' || substr($msg, 1, 4) == 'id:') {
                $msg = 'ACK/';
            }
            $l_status = $msg;
            $l_msgid = $msgid;
            $this->logging($now, "status first if ..$l_status...", $myid);
        } else {
            if ($status_desc == 'ACCEPTD' || $status_desc == 'ENROUTE') {
                $status_desc = 'ACK/';
            }
            if ($status_desc == 'Delivered') {
                $status_desc = 'DELIVRD';
            }
            if ($status_desc == 'Undeliverable') {
                $status_desc = 'UNDELIV';
            }
            $error_code = trim($error_code);
            $status_desc = trim($status_desc);
            $l_status = $status_desc;
            $l_delivery_date = Carbon::now()->toDateTimeString();

            $this->logging($now, "status at else ..$l_status...", $myid);
        }

        //compute delivery time
        $diff = null;
        if (1) {
            $log = Log::find($myid);
            if (!empty($log)) {
                $submitDate = Carbon::parse($log->submit_date);
                $delivDate = Carbon::parse($l_delivery_date);
                $diff = $delivDate->diffInSeconds($submitDate);
            }
        }

        sleep(1);

        $data = [
            'msgid' => $l_msgid,
            'status' => $l_status,
            'delivery_date' => $l_delivery_date,
            'sent_date' => $l_sent_date,
            'delivery_time' => $diff,
            'error_code' => !empty($error_code) ? $error_code : null,
            'error_msg' => !empty($error_msg) ? $error_msg : null,
            'updated_at' => Carbon::now()->toDateTimeString()
        ];
        //update db

        try {

            if (empty($log_received)):

                $this->logging($now, 'inserting into db id..', $myid);
                $data['id'] = $myid;
                LogReceived::query()->create($data);

            else :

                $this->logging($now, 'updating', $myid);
                $log_received->update($data);

            endif;
        } catch (\Exception $ex) {
            $this->logging($now, "error  {$ex->getMessage()} on..", $myid);
        }


        DB::commit();

        return "Updated!";
    }

    public function send_personalised_group_sms(Request $request, TmpGroupSmsDataTable $dataTable)
    {
        if ($request->has('draw')) {
            return $dataTable->render('sms.send_personalised_group_sms', ['step' => 3]);
        }

        $step = 1;
        //reset current session data for sending group sms
        if ($request->session()->has('group_sms_personalised_data')) {
            $request->session()->forget('group_sms_personalised_data');
        }
        if ($request->session()->has('alert')) {
            $request->session()->forget('alert');
        }

        //fetch user groups
        $groups = $request->user()->groups()->orderBy('name', 'asc')->get(['name', 'id']);

        //show view
        return view('sms.send_personalised_group_sms', [
            'step' => $step,
            'groups' => $groups,
            'sender_ids' => UserSenderId::query()->where([['user_id', Auth::user()->id], ['status', 1]])->get()
        ]);
    }

    public function post_send_personalised_group_sms(Request $request, TmpGroupSmsDataTable $dataTable)
    {
        //get current user
        $user = Auth::user();
        $credit = $user->credit;

        //get current step
        $step = $request->get('step', 1);

        //process for step 1
        if ($step == 1) {
            //validate the request
            $tank = $this->validate($request, [
                'selected_group' => 'required',
                'sender_id' => 'required|max:11',
                'schedule_date' => 'present',
                'name' => 'required',
                //                'image_upload' => 'image',
                'image_upload' => 'file|mimes:jpeg,jpg,png,gif'
            ]);


            $schedule_date = Carbon::parse($tank['schedule_date']);
            session(['tank_date' => $schedule_date]);


            /** @var  $highestRow ** */


            $filters = Filters::query()->get();

            $banned = array();
            $flash = null;


            foreach ($filters as $filth)
                array_push($banned, strtolower($filth->keyword));


            $new_strings = explode(" ", strtolower($request->message_content));

            $result = array_intersect($banned, $new_strings);
            if (!empty($result)):
                foreach ($result as $value):
                    $flash .= $value . ', ';
                endforeach;
                return \redirect()->back()->withErrors("The following words are not permitted:  {$flash}");
            endif;

            $highestRow = 0;
            $selected_groups = $request->get('selected_group');
            $group_name = '';
            $counter = 0;

            DB::beginTransaction();
            $user->tmp_group_sms()->delete();

            if (!empty($selected_groups))
                $to_insert = [];
            foreach ($selected_groups as $group_id) {
                $group = $user->groups()->find($group_id);
                if (!empty($group)) {
                    $group_name .= ($group->name . ', ');
                    $highestRow += $group->contacts()->count();
                    $group->contacts()->chunk(5000, function ($contacts)
                    use (&$user, &$counter, &$to_insert) {
                        foreach ($contacts as $contact) {
//                                $existing = DB::table('tmp_group_sms')->where([
//                                    ['user_id', '=', $user->id],
//                                    ['msisdn', '=', $contact->phone_number]
//                                ])->first();
//
                            $existing = '';

                            //                                $existing = array_search($contact->phone_number, array_column($to_insert, 'msisdn'));
                            //                                $existing = in_array($contact->phone_number, $to_insert);
                            //                                array_push($check, $existing);
                            //                              dd($check);

                            $var1 = $user->id;
                            $var2 = $contact->phone_number;

                            $existing = array_filter($to_insert, function ($val) use ($var1, $var2) {
                                return ($val['user_id'] == $var1 and $val['msisdn'] == $var2);
                            });


                            if (empty($existing)) {
                                $counter++;
                                array_push($to_insert, [
                                    'user_id' => $user->id,
                                    'name' => $contact->name,
                                    'msisdn' => $contact->phone_number
                                ]);
                            }
                        }
                    });
                }
            }

            DB::table('tmp_group_sms')->insert($to_insert);

            DB::commit();


            $imgId = null;

            //update image if image exist
            if (!empty($request['image_upload'])) {
                if ($request->file('image_upload')->isValid()) {
                    $current_filename = $request->file('image_upload')->getClientOriginalName();
                    $fileMimeType = $request->file('image_upload')->getMimeType();

                    $destinationPath = storage_path() . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR;
                    $fileName = $user->username . '_' . $current_filename;
                    $request->file('image_upload')->move($destinationPath, $fileName);
                    $full_path = $destinationPath . $fileName;
                    while (1) {
                        $imgId = uniqid();
                        if (empty(SmsImage::find($imgId))) {
                            break;
                        }
                    }
                    $user->sms_images()->create([
                        'path' => $full_path,
                        'file_name' => $current_filename,
                        'mime_type' => $fileMimeType,
                        'id' => $imgId
                    ]);
                } else {
                    return Redirect::back()->withInput()->withErrors(array('image_upload' => 'Sorry, The file upload failed!'));
                }
            }

            $new_msg_text = preg_replace(array('/\r\n/'), array("\n"), trim($request->get('message_content', '')));
            $msg = $new_msg_text;
            if (!empty($imgId)) {
                $sms_msg_url = route('sms_image', ['id' => $imgId]);
                $msg = $new_msg_text . "\n" . $sms_msg_url;
            }

            // clean message
            $msg = $this->cleanMessage($msg);

            //store user input in the new session data
            session(['group_sms_personalised_data' => [
                'group_name' => $group_name,
                'sender_id' => $request->get('sender_id'),
                'message_type' => $request->input('message_type'),
                'flash' => $request->input('flash'),
                'groups' => $selected_groups,
                'schedule_date' => Carbon::parse($request->get('schedule_date')),
                'name' => $request->get('name'),
                'msg' => $msg,
                'recipients' => $counter,
                'selected_group' => $request->get('selected_group')
            ]]);
            $step = 2;
        } //process for step 2
        else if ($step == 2) {
            //check if next button was pressed
            if ($request->has('next')) {
                $new_msg_text = preg_replace(array('/\r\n/'), array("\n"), trim($request->get('message_content', '')));
                $message = $new_msg_text . session('group_sms_personalised_data')['msg'];
                if (empty($message)) {
                    $step = 2;
                    $request->session()->flash('error_msg', 'Kindly enter the text message!');
                } else {
                    //get data for step 2
                    $no_chars = strlen($message);
                    $no_pages = SmsTools::no_pages($no_chars);

                    // cost of sending one msg with this no_pages to one person
                    $nummsisdn = session('group_sms_personalised_data')['recipients'];
                    // no of recepients


                    $curr_bal = $credit->new_bal;

                    $recipients = $nummsisdn;

                    $credit_available = $curr_bal;


                    // clean message
                    $message = $this->cleanMessage($message);

                    //store user input in the new session data
                    session(['group_sms_personalised_data' => [
                        'group_name' => session('group_sms_personalised_data')['group_name'],
                        'sender_id' => session('group_sms_personalised_data')['sender_id'],
                        'message_content' => $message,
                        'message_type' => session('group_sms_personalised_data')['message_type'],
                        'flash' => session('group_sms_personalised_data')['flash'],
                        'recipients' => $recipients,
                        'total_price' => $no_pages,
                        'credit_available' => number_format($credit_available, 3),
                        'groups' => session('group_sms_personalised_data')['groups'],
                        'schedule_date' => session('group_sms_personalised_data')['schedule_date'],
                        'name' => session('group_sms_personalised_data')['name'],
                        'selected_group' => session('group_sms_personalised_data')['selected_group'],
                    ]]);
                    $step = 3;
                }
            } //in case back button was pressed
            else {
                //go back to step 1
                $step = 1;
            }
        } //process for step 2
        else if ($step == 3) {
            //check if next button was pressed
            if ($request->has('next')) {
                $highestRow = $user->tmp_group_sms()->count();
                //check if user can send sms
                if ($highestRow > 0) {
                    //do the calculation and move to step 3
                    //get data for step 2
                    $no_chars = strlen(session('group_sms_personalised_data')['message_content']);
                    $total_price = strlen(session('group_sms_personalised_data')['total_price']);
                    $price = 0.0;
                    foreach ($user->tmp_group_sms as $tempp) {
                        $network = SmsTools::get_msisdn_network($user, $tempp->msisdn);
                        $price += (float)$network['sms_price'];
                    }
                    $no_pages = SmsTools::no_pages($no_chars);

                    // cost of sending one msg with this no_pages to one person
                    $nummsisdn = $highestRow;
                    // no of recepients
                    $tot_cost = $total_price * $price;

                    $curr_bal = $credit->new_bal;
                    $credit_used = $credit->credit_used;

                    $recipients = $nummsisdn;
                    $credit_available = $curr_bal;

                    session(['group_sms_personalised_data' => [
                        'group_name' => session('group_sms_personalised_data')['group_name'],
                        'sender_id' => session('group_sms_personalised_data')['sender_id'],
                        'message_content' => session('group_sms_personalised_data')['message_content'],
                        'groups' => session('group_sms_personalised_data')['groups'],
                        'message_type' => session('group_sms_personalised_data')['message_type'],
                        'flash' => session('group_sms_personalised_data')['flash'],
                        'recipients' => $recipients,
                        'total_price' => $tot_cost,
                        'credit_available' => number_format($credit_available, 3),
                        'schedule_date' => session('group_sms_personalised_data')['schedule_date'],
                        'name' => session('group_sms_personalised_data')['name'],
                        'selected_group' => session('group_sms_personalised_data')['selected_group'],
                    ]]);

                    //move to step 3
                    $step = 4;
                } else {
                    //prevent user from access step3
                    $request->session()->flash('error_msg', 'Kindly add some phone number(s)');
                    $step = 3;
                }
            } else if ($request->has('add_msisdn_btn')) {
                $input = $request->get('add_msisdn_input');
                if (empty(trim($input))) {
                    $request->session()->flash('error_msg', 'Kindly enter the msisdn to be added');
                }

                $tmp_msisdn_list = explode(',', $input);
                $added = 0;
                if (!empty($tmp_msisdn_list))
                    foreach ($tmp_msisdn_list as $temp) {
                        $temp = trim($temp);
                        if (!empty($temp)) {
                            if (!empty($user->tmp_group_sms()->where('msisdn', $temp)->first())) {
                                $request->session()->flash('error_msg', $temp . ' already exists in the list!');
                                break;
                            }
                            $user->tmp_group_sms()->create(['msisdn' => $temp]);
                            $added++;
                        }
                    }
                if ($added > 0)
                    $request->session()->flash('success_msg', $added . ' msisdn added to the list!');
                $step = 3;
            } else if ($request->has('delete_item')) {
                $input = $request->get('delete_item');
                $contact = $user->tmp_group_sms()->where('msisdn', $input)->first();
                if (!empty($contact)) {
                    $contact->delete();
                    $request->session()->flash('success_msg', $input . ' was deleted from the list!');
                } else {
                    $request->session()->flash('error_msg', $input . ' not found in the list!');
                }
                $step = 3;
            } else if ($request->has('delete_selection')) {
                $selection = $request->get('selection');
                $deleted = 0;
                if (!empty($selection))
                    foreach ($selection as $msisdn) {
                        $contact = $user->tmp_group_sms()->where('msisdn', $msisdn)->first();
                        if (!empty($contact)) {
                            $contact->delete();
                            $deleted++;
                        } else {
                            $request->session()->flash('error_msg', $msisdn . ' not found in the list!');
                        }
                    }
                if ($deleted > 0)
                    $request->session()->flash('success_msg', $deleted . ' msisdn deleted from the list!');
                $step = 3;
            } //in case back button was pressed
            else if ($request->has('back')) {
                //go back to step 1
                $step = 2;
            }
        } else if ($step == 4) {
            //check if next button was pressed
            if ($request->has('submit')) {
                $no_chars = strlen(session('group_sms_personalised_data')['message_content']);
                $sender = session('group_sms_personalised_data')['sender_id'];
                $message_type = session('group_sms_personalised_data')['message_type'];
                $nummsisdn = session('group_sms_personalised_data')['recipients'];
                $msgs = session('group_sms_personalised_data')['message_content'];
                $total_price = session('group_sms_personalised_data')['total_price'];
                $name = session('group_sms_personalised_data')['name'];
                $group_ids = implode(",", session('group_sms_personalised_data')['selected_group']);
                $flash = session('group_sms_personalised_data')['flash'];

                $no_pages = SmsTools::no_pages($no_chars);

                $tot_cost = $total_price;

                $curr_bal = $credit->new_bal;

                //remaining sms user can send
                // Log submitted sms
                $this->loggingPushedSMS($name, 'personalised-group-sms', $sender);

                if (isset(session('group_sms_personalised_data')['schedule_date']) && !empty(session('group_sms_personalised_data')['schedule_date'])) {
                    $sch_date = Carbon::parse(session('group_sms_personalised_data')['schedule_date']);
                    $now = Carbon::now()->addMinutes(1);
                    $date = $now->lte($sch_date) ? $sch_date : $now;
                } else {
                    $date = Carbon::now()->addMinutes(1);
                }

                if ($curr_bal >= $tot_cost) {
                    //copy msisdn to excel file and add it to the pending job list
                    $destinationPath = storage_path('bulk_sms');
                    $fileName = $user->username . '_' . date('YmdHis');

                    try {


                        $spreadsheet = new Spreadsheet();
                        $sheet = $spreadsheet->getActiveSheet();
                        $sheet->setTitle('GROUP SMS Details');

                        $i = 2;
                        $data = $user->tmp_group_sms()->get();

                        $sheet->setCellValue('A1', 'Number');
                        $sheet->setCellValue('B1', 'Name');
                        foreach ($data as $dat) {
                            $sheet->setCellValue("A$i", $dat->msisdn);
                            $sheet->setCellValue("B$i", empty($dat->name) ? '' : $dat->name);
                            $i++;
                        }

                        $writer = new Xlsx($spreadsheet);
                        $file_name = $fileName . '.xlsx';
                        $writer->save(storage_path("bulk_sms/$file_name"));

                        $user->tmp_group_sms()->delete();


                        //                        $res = Excel::create($fileName, function($excel) use (&$user) {
                        //                            // Set the title
                        //                            $excel->setTitle('GROUP SMS Details');
                        //                            // Chain the setters
                        //                            $excel->setCreator('Alphonse')->setCompany('Npontu');
                        //                            $excel->setDescription('Send Group SMS Details');
                        //
                        //                            $excel->sheet('Msisdn', function ($sheet) use (&$user) {
                        //                                $sheet->setOrientation('landscape');
                        //                                $i = 1;
                        //                                $data = $user->tmp_group_sms()->get();
                        //                                $sheet->appendRow($i, ['Number', 'Name']);
                        //                                foreach ($data as $dat) {
                        //                                    $i++;
                        //                                    $sheet->appendRow($i, [$dat->msisdn, empty($dat->name) ? '': $dat->name]);
                        //                                }
                        //                                $user->tmp_group_sms()->delete();
                        //                            });
                        //                        })->store('xls', $destinationPath, true);

                    } catch (\Exception $e) {
                        $request->session()->flash('error_msg', 'Sorry, an error occurred while scheduling the blast!');
                        Log::error($e->getMessage());
                        $step = 4;
                        return view('sms.send_personalised_group_sms', ['step' => $step]);
                    }
                    //Create a job
                    if (empty($sender)) {
                        return redirect()->route('app');
                    }

                    $res['full'] = "/var/www/html/deywuro_messenger/storage/bulk_sms/$file_name";

                    // Create a job
                    $status = 'pending';
                    if (strtoupper($user->username) == 'SCBULK' || strtoupper($user->username) == 'GCBCARDS') {
                        $status = 'Awaiting approval';
                    }


                    // Send bulk blast alert to all
                    $send_schdule_time = $date < now() ? now()->addMinutes(1) : $date;
                    $send_alert_contacts = explode(',', env('BLAST_ALERT_CONTACT'));
                    //$send_alert_contacts = ['233200154778', '0552837882', '233249173335', '0242219890', '0576907722', '233205663677', '0243375520', '0244304528', '0249430715', '233548617798'];
                    $send_alert_message = "Personalised Group Details
Username: $user->username
SenderID: $sender
Volume: $nummsisdn
Campaign: $name
Scheduled Time: $send_schdule_time";
                    if ($nummsisdn >= 1000) {
                        foreach ($send_alert_contacts as $contact) {
                            $this->sendSmsNew($send_alert_message, $contact, 'Blast Alert');
                        }
                    }


                    UserJob::create([
                        'username' => $user->username,
                        'sender' => $sender,
                        'message_type' => $message_type,
                        'message' => $msgs,
                        'sms_count' => $no_pages,
                        'sched_datetime' => $date < now() ? now()->addMinutes(1) : $date,
                        'type' => 'p_group',
                        'status' => $status,
                        'created_by' => $user->username,
                        'flash' => $flash,
                        'file_path' => $res['full'],
                        'name' => $name,
                        'user_id' => $user->id,
                        'total_traffic' => $nummsisdn,
                        'group_ids' => $group_ids

                    ]);

                    @chmod($res['full'], 0777);

                    //update audit trails
                    $user->audit_trails()->create([
                        'username' => $user->username,
                        'date' => Carbon::now()->toDateTimeString(),
                        'activity' => $user->username . ' sent a personalised group sms to ' . $nummsisdn . ' msisdn'
                    ]);

                    //send blast alert
                    $alertThreshold = intval(env('BLAST_ALERT', 100));
                    if (intval($nummsisdn) >= $alertThreshold) {
                        SmsTools::sendBlastAlert($user, $nummsisdn);
                    }

                    $request->session()->flash('success', 'The contacts was successfully uploaded!');
                } else {
                    $request->session()->flash('error_msg', 'Sorry, you don\'t have enough credit to proceed!');
                }

                //reset session
                $step = 0;
                $request->session()->forget('group_sms_personalised_data');
                if (!$request->session()->has('success') || empty(session('success')))
                    $request->session()->flash('success', 'Your contacts was successfully uploaded!');
            } //in case back button was pressed
            else {
                //go back to step 2
                $step = 3;
            }
        }

        if ($step == 1) {
            //fetch user groups
            $groups = $request->user()->groups()->orderBy('name', 'asc')->get(['name', 'id']);
            return view('sms.send_personalised_group_sms', ['step' => $step, 'groups' => $groups]);
        } else if ($step == 3) {
            return $dataTable->render('sms.send_personalised_group_sms', ['step' => $step, 'pages' => $no_pages ?? null]);
        } else {
            return view('sms.send_personalised_group_sms', ['step' => $step, 'pages' => $no_pages ?? null]);
        }
    }

    public function send_personalised_bulk_sms()
    {
        $step = 1;
        //reset current session data for sending single sms
        if (session()->has('bulk_sms_personalised_data')) {
            session()->forget('bulk_sms_personalised_data');
        }
        if (session()->has('alert')) {
            session()->forget('alert');
        }
        //show view
        return view('sms.send_bulk_personalised_sms', [
            'step' => $step,
            'sender_ids' => UserSenderId::query()->where([['user_id', Auth::user()->id], ['status', 1]])->get()
        ]);
    }

    public function post_send_personalised_bulk_sms(Request $request)
    {
        $user = Auth::user();
        $credit = $user->credit;

        $step = $request->get('step', 1);


        if ($step == 1) {
            //validate the request
            $tank = $this->validate($request, [
                'file_upload' => 'required|mimes:csv,txt,xlsx,xls',
                'sender_id' => 'required|max:11',
                'schedule_date' => 'present',
                'name' => 'required',
                //                'image_upload' => 'image',
                'image_upload' => 'file|mimes:jpeg,jpg,png,gif'
            ]);

            $schedule_date = Carbon::parse($tank['schedule_date']);
            session(['tank_date' => $schedule_date]);


            /*************************************************/

            $filters = Filters::query()->get();

            $banned = array();
            $flash = null;


            foreach ($filters as $filth)
                array_push($banned, strtolower($filth->keyword));


            $new_strings = explode(" ", strtolower($request->message_content));
            $result = array_intersect($banned, $new_strings);
            if (!empty($result)):
                foreach ($result as $value):
                    $flash .= $value . ', ';
                endforeach;
                return \redirect()->back()->withErrors("The following words are not permitted:  {$flash}");
            endif;

            /** @var  $current_filename */


            $current_filename = $request->file('file_upload')->getClientOriginalName();
            $filename_splitted = explode(".", $current_filename);
            $extension = end($filename_splitted);

            $destinationPath = storage_path() . DIRECTORY_SEPARATOR . 'bulk_sms' . DIRECTORY_SEPARATOR;
            $fileName = $user->username . '_' . date('YmdHis') . '.' . $extension;
            $full_filename = $destinationPath . $fileName;

            if ($request->file('file_upload')->isValid()) {
                $request->file('file_upload')->move($destinationPath, $fileName);
                @chmod($full_filename, 0777);
            } else {
                return Redirect::back()->withInput()->withErrors(array('file_upload' => 'Sorry, The file upload failed!'));
            }

            $highestRow = 0;
            $headers = [];
            $first_record = [];

            try {
                // Efficiently count records without loading the entire file into memory
                switch (strtolower($extension)) {
                    case 'csv':
                        $highestRow = $this->countCsvLines($full_filename) - 1; // -1 for header (if exists)

                        // Get headers and first record
                        $file = fopen($full_filename, 'r');
                        if ($file) {
                            $head = fgetcsv($file);
                            $head2 = fgetcsv($file);
                            fclose($file);

                            foreach ($head as $header) {
                                $headers[] = $header;
                            }

                            if ($head2) {
                                foreach ($head2 as $header2) {
                                    $first_record[] = $header2;
                                }
                            }
                        }
                        break;

                    case 'txt':
                        $highestRow = $this->countTextFileLines($full_filename);

                        // Get headers and first record
                        $file = fopen($full_filename, 'r');
                        if ($file) {
                            $head = explode("\t", trim(fgets($file)));
                            $head2 = explode("\t", trim(fgets($file)));
                            fclose($file);

                            foreach ($head as $header) {
                                $headers[] = $header;
                            }

                            if ($head2) {
                                foreach ($head2 as $header2) {
                                    $first_record[] = $header2;
                                }
                            }
                        }
                        break;

                    case 'xlsx':
                    case 'xls':
                        // Handle both Excel formats the same way
                        $readerType = strtolower($extension) === 'xlsx' ? 'Xlsx' : 'Xls';
                        $highestRow = $this->countExcelRows($full_filename, strtolower($extension));

                        // Read just the first two rows like the original code
                        $reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($readerType);
                        $reader->setReadDataOnly(true);
                        $reader->setReadFilter(new class implements \PhpOffice\PhpSpreadsheet\Reader\IReadFilter {
                            public function readCell($columnAddress, $row, $worksheetName = '') {
                                // Only read rows 1 and 2
                                return ($row <= 2);
                            }
                        });

                        $spreadsheet = $reader->load($full_filename);
                        $worksheet = $spreadsheet->getActiveSheet();
                        $rawValue = [];

                        // Get first row (headers)
                        $rawValue[0][0] = [];
                        foreach ($worksheet->getRowIterator(1, 1) as $row) {
                            $cellIterator = $row->getCellIterator();
                            $cellIterator->setIterateOnlyExistingCells(false);
                            foreach ($cellIterator as $cell) {
                                $rawValue[0][0][] = $cell->getValue();
                            }
                        }

                        // Get second row (first data row)
                        $rawValue[0][1] = [];
                        foreach ($worksheet->getRowIterator(2, 2) as $row) {
                            $cellIterator = $row->getCellIterator();
                            $cellIterator->setIterateOnlyExistingCells(false);
                            foreach ($cellIterator as $cell) {
                                $rawValue[0][1][] = $cell->getValue();
                            }
                        }

                        // Get headers and first record exactly like the original code
                        $head = $rawValue[0][0];
                        $head2 = $rawValue[0][1];

                        foreach ($head as $header) {
                            $headers[] = $header;
                        }

                        foreach ($head2 as $header2) {
                            $first_record[] = $header2;
                        }
                        break;

                    default:
                        return Redirect::back()->withInput()->withErrors(array('file_upload' => 'Unsupported file format!'));
                }
            } catch (\Throwable $e) {
                return Redirect::back()->withInput()->withErrors(array('file_upload' => $e->getMessage() . ' Error! Your file is invalid!'));
            }

            if ($highestRow <= 0) {
                return Redirect::back()->withInput()->withErrors(array('file_upload' => 'Error! No valid recipients found in file!'));
            }
            
            $imgId = null;


            //update image if image exist
            if (!empty($request['image_upload'])) {
                if ($request->file('image_upload')->isValid()) {
                    $current_filename = $request->file('image_upload')->getClientOriginalName();
                    $fileMimeType = $request->file('image_upload')->getMimeType();

                    $destinationPath = storage_path() . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR;
                    $fileName = $user->username . '_' . $current_filename;
                    $request->file('image_upload')->move($destinationPath, $fileName);
                    $full_path = $destinationPath . $fileName;
                    while (1) {
                        $imgId = uniqid();
                        if (empty(SmsImage::find($imgId))) {
                            break;
                        }
                    }
                    $user->sms_images()->create([
                        'path' => $full_path,
                        'file_name' => $current_filename,
                        'mime_type' => $fileMimeType,
                        'id' => $imgId
                    ]);
                } else {
                    return Redirect::back()->withInput()->withErrors(array('image_upload' => 'Sorry, The file upload failed!'));
                }
            }

            $msg = $request->get('message_content', '');
            $msg = preg_replace(array('/\r\n/'), array("\n"), trim($msg));
            if (!empty($imgId)) {
                $sms_msg_url = route('sms_image', ['id' => $imgId]);
                $msg = $msg . "\n" . $sms_msg_url;
            }


            $msg = $this->cleanMessage($msg);

            //store user input in the new session data
            session([
                'bulk_sms_personalised_data' =>
                    [

                        'phone_numbers' => $current_filename,
                        'sender_id' => $request->get('sender_id'),
                        'recipients' => $highestRow,
                        'path' => $full_filename,
                        'message_type' => $request->input('message_type'),
                        'flash' => $request->input('flash'),
                        'schedule_date' => Carbon::parse($request->get('schedule_date')),
                        'headers' => $headers,
                        'first_record' => $first_record,
                        'name' => $request->get('name'),
                        'msg' => $msg,
                        'remove_duplicate' => request()->has('remove_duplicate')
                    ]
            ]);
            $step = 2;

        } else if ($step == 2) {
            if ($request->has('next')) {

                $new_msg_text = preg_replace(array('/\r\n/'), array("\n"), trim($request->get('message_content', '')));
                $imgUrl = isset(session('bulk_sms_personalised_data')['msg']) ? session('bulk_sms_personalised_data')['msg'] : '';
                $message = $new_msg_text . $imgUrl;

                if (empty($message)) {
                    $step = 2;
                    $request->session()->flash('error_msg', 'Kindly enter the text message!');
                } else {

                    if (session()->has('bulk_sms_personalised_data')) {
                        //get data for step 2
                        $nummsisdn = session('bulk_sms_personalised_data')['recipients'];

                        $curr_bal = $credit->new_bal;
                        $recipients = $nummsisdn;

                        $headers = session('bulk_sms_personalised_data')['headers'];
                        $first_record = session('bulk_sms_personalised_data')['first_record'];
                        $no_pages = SmsTools::no_pages(strlen(session('bulk_sms_personalised_data')['msg']));


                        $message = $this->cleanMessage($message);

                        //store user input in the new session data
                        session(['bulk_sms_personalised_data' => [

                            'phone_numbers' => session('bulk_sms_personalised_data')['phone_numbers'],
                            'sender_id' => session('bulk_sms_personalised_data')['sender_id'],
                            'message_content' => $message,
                            'temp_msg' => SpeedyPersoBulkSms::update_msg($headers, $first_record, $message),
                            'recipients' => $recipients,
                            'credit_available' => $curr_bal,
                            'message_type' => session('bulk_sms_personalised_data')['message_type'],
                            'msg' => $imgUrl,
                            'flash' => session('bulk_sms_personalised_data')['flash'],
                            'path' => session('bulk_sms_personalised_data')['path'],
                            'schedule_date' => session('bulk_sms_personalised_data')['schedule_date'],
                            'headers' => session('bulk_sms_personalised_data')['headers'],
                            'first_record' => session('bulk_sms_personalised_data')['first_record'],
                            'name' => session('bulk_sms_personalised_data')['name'],
                            'remove_duplicate' => session('bulk_sms_personalised_data')['remove_duplicate'],
                        ]]);
                        $step = 3;
                    } else {
                        $step = 2;
//                        $request->session()->flash('error_msg', 'A network error has occurred. Kindly try again soon!');
                        return Redirect::back()->withInput()->withErrors(array('error' => 'A network error has occurred. Kindly try again soon!'));

                    }

                }
            } else {
                $step = 1;
            }
        } else if ($step == 3) {
            //check if next button was pressed
            if ($request->has('submit')) {
                $no_chars = strlen(session('bulk_sms_personalised_data')['message_content']);
                $sender = session('bulk_sms_personalised_data')['sender_id'];
                $message_type = session('bulk_sms_personalised_data')['message_type'];
                $nummsisdn = session('bulk_sms_personalised_data')['recipients'];
                $msgs = session('bulk_sms_personalised_data')['message_content'];
                $path = session('bulk_sms_personalised_data')['path'];
                $name = session('bulk_sms_personalised_data')['name'];
                $remove_duplicate = session('bulk_sms_personalised_data')['remove_duplicate'];
                $flash = session('bulk_sms_personalised_data')['flash'];

                $no_pages = SmsTools::no_pages($no_chars);
                $curr_bal = $credit->new_bal;

                // Log submitted sms
                $this->loggingPushedSMS($name, 'personalised-bulk-sms', $sender);

                if (isset(session('bulk_sms_personalised_data')['schedule_date']) && !empty(session('bulk_sms_personalised_data')['schedule_date'])) {
                    $sch_date = Carbon::parse(session('bulk_sms_personalised_data')['schedule_date']);
                    $now = Carbon::now()->addMinutes(1);
                    $date = $now->lte($sch_date) ? $sch_date : $now;
                } else {
                    $date = Carbon::now()->addMinutes(1);
                }

                if ($nummsisdn * $credit->price <= $curr_bal) {
                    //Create a job
                    $status = 'pending';
                    if (strtoupper($user->username) == 'SCBULK' || strtoupper($user->username) == 'GCBCARDS') {
                        $status = 'Awaiting approval';
                    }


                    $job = new UserJob([
                        'username' => $user->username,
                        'sender' => $sender,
                        'message' => $msgs,
                        'sms_count' => $no_pages,
                        'type' => 'p_bulk',
                        'message_type' => $message_type,
                        'sched_datetime' => $date < now() ? now()->addMinutes(1) : $date,
                        'status' => $status,
                        'created_by' => $user->username,
                        'file_path' => $path,
                        'flash' => $flash,
                        'name' => $name,
                        'total_traffic' => $nummsisdn,
                        'remove_duplicate' => $remove_duplicate
                    ]);

                    if (empty($sender)) {
                        return redirect()->route('app');
                    }

                    $user->jobs()->save($job);

                    //update audit trails
                    $user->audit_trails()->create([
                        'username' => $user->username,
                        'date' => Carbon::now()->toDateTimeString(),
                        'activity' => $user->username . ' sent a personalised bulk sms to ' . $nummsisdn . ' msisdn'
                    ]);


                    // Send bulk blast alert to all
                    $send_schdule_time = $date < now() ? now()->addMinutes(1) : $date;
                    $send_alert_contacts = explode(',', env('BLAST_ALERT_CONTACT'));
//                    $send_alert_contacts = ['233200154778', '0552837882', '233249173335', '0576907722', '233205663677', '0243375520', '0244304528', '0249430715', '233548617798', '233540882909', '233209366367', '0544289513', '0554749206', '0543149941', '0555055445'];
                    $send_alert_message = "PBulk SMS for {$user->username} ({$job->id})
SenderID: $sender
Volume: $nummsisdn
Scheduled Time: $send_schdule_time";


                    if ($nummsisdn >= 1000) {
                        foreach ($send_alert_contacts as $contact) {
                            $this->sendSmsNew($send_alert_message, $contact, 'Blast Alert');
                        }
                        try{
                            $url = 'https://ticketingtoolapi.snwolley.com/api/create/ticket';
                            $data = ['username' => 'talerts',
                                'password' => 'password',
                                'title' => 'PBulk SMS Alert',
                                'type' => 'REQUEST',
                                'priority' => 3,
                                'description' => $send_alert_message,
                            ];
                            $client = new \GuzzleHttp\Client();
                            $response = $client->request('POST', $url, ['form_params' => $data]);
                        } catch (\Exception $exception){
                            \Illuminate\Support\Facades\Log::error('ERROR CREATING TICKET '.$exception->getMessage());
                        }
                    }

                    //send blast alert
                    $alertThreshold = intval(env('BLAST_ALERT', 100));
                    if (intval($nummsisdn) >= $alertThreshold) {
                        SmsTools::sendBlastAlert($user, $nummsisdn);
                    }

                    $request->session()->flash('success', 'The contacts was successfully uploaded!');
                } else {
                    return Redirect::back()->withInput()->withErrors(array('error' => 'Sorry, you don\'t have enough credit to proceed!'));
                }

                //reset session
                $step = 0;
                $request->session()->forget('bulk_sms_personalised_data');
                if (!$request->session()->has('success') || empty(session('success')))
                    $request->session()->flash('success', 'Your contacts was successfully uploaded!');
            } //in case back button was pressed
            else {
                //go back to step 1
                $step = 2;
            }
        }


        return view('sms.send_bulk_personalised_sms', [
            'step' => $step,
            'pages' => $no_pages ?? null,
            'sender_ids' => UserSenderId::query()->where([['user_id', Auth::user()->id], ['status', 1]])->get()
        ]);
    }

    private function logging($now, $log_msg, $myid)
    {
        try {
            file_put_contents(storage_path('logs/incoming.log'), "$now ||  $log_msg $myid ........... \n", FILE_APPEND);
        } catch (\Exception $ex) {
        }
    }


    public function loggingPushedSMS($campaign_name, $sms_type, $sender_id)
    {
        if (auth()->user()) {
            $url = url()->current();
            $ip = request()->ip();

            // log to all page
            $auth = auth()->id();
            $username = auth()->user()->username ?? '';
            $company_name = auth()->user()->organisation ?? '';

            \Illuminate\Support\Facades\Log::channel('deywuro_pushed_sms')->info("[user_id:$auth] [username:$username] [company_name:$company_name] [message: $sms_type has been submitted by $username with senderID $sender_id] [sms_campaign_name:$campaign_name] [current_url:$url] [ip:$ip]");


        } else {
            $url = url()->current();
            $ip = \request()->ip();

            \Illuminate\Support\Facades\Log::channel('deywuro_pushed_sms')->info("[current_url:$url] [ip:$ip] [message: $sms_type has been submitted with senderID $sender_id] [sms_campaign_name:$campaign_name]");
        }
    }

    public function send_email_api(Request $request)
    {
        $username = $request['username'];
        $password = $request['password'];
        $from = $request['from'];
        $to = trim($request['to']);
        $cc = trim($request['cc']);
        $bcc = trim($request['bcc']);
        $subject = $request['subject'];
        $text = $request['text'];
        $html = $request['html'];
        $attachment = $request['attachment'];

        if (empty($username)) {
            return [
                'code' => 402,
                'message' => 'The username is required'
            ];
        }
        if (empty($password)) {
            return [
                'code' => 402,
                'message' => 'The password is required'
            ];
        }
        if (empty($from)) {
            return [
                'code' => 402,
                'message' => 'The source is required'
            ];
        }
        if (empty($to)) {
            return [
                'code' => 402,
                'message' => 'The destination is required'
            ];
        }
        if (empty($subject)) {
            return [
                'code' => 402,
                'message' => 'The subject is required'
            ];
        }
        if (empty($html) && empty($text)) {
            return [
                'code' => 402,
                'message' => 'The message is required'
            ];
        }

        if (!Auth::once([
            'username' => $username,
            'password' => $password
        ])) {
            return [
                'code' => 401,
                'message' => 'Invalid Credential'
            ];
        }
        $curlString = "curl -s --user 'api:key-c2db007fa3f8bb651ad1ffd4bde9d914'  https://api.mailgun.net/v3/mail.deywuro.com/messages -F from=$from -F to=$to -F subject=$subject -F text=$text";
        $result = shell_exec($curlString);

        $json = json_decode($result, true);
        $resultMsgPrep = $json['message'];

        $resultMsg = str_replace('"', '', $resultMsgPrep);


        if ($resultMsg == 'Queued. Thank you.') {
            return [
                'code' => 0,
                'message' => 'email successfully sent'
            ];
        } else {
            return [
                'code' => 500,
                'message' => 'email request failed'
            ];
        }
    }

    public function get_saved_sms()
    {
        $inputs = request()->all();
        $saved = SavedMessage::findOrFail($inputs['id']);
        return $saved;
    }

    public function post_save_sms(Request $request)
    {

        $this->validate($request, [
            'message' => 'required',
            'type' => 'required',
            'name' => 'required'
        ]);
        $inputs = $request->all();
        SavedMessage::firstOrCreate([
            'message' => $inputs['message'],
            'type' => $inputs['type'],
            'name' => $inputs['name'],
            'user_id' => auth()->id()
        ]);
        return 'success';
    }

    public function delete_contact_from_sms_group($msisdn) {}

    public function get_image_for_image($id)
    {
        $img = SmsImage::findOrFail($id);
        $mime_type = $img->mime_type;
        return Response::download($img->path, $img->file_name, ['Content-Type: ' . $mime_type]);
    }

    public function view_sms_for_image($id)
    {
        $image_url = route('sms_image', $id);
        return view('sms.sms_image', ['image_url' => $image_url]);
    }

    public static function send_sms($msisdn, $msgs)
    {
        $should_send_sms = true; // bug-fix

        if ($should_send_sms && !empty(trim($msisdn))) {
            $msisdn = self::format_phone_number($msisdn);
            $senderId = 'Deywuro';
            $username = 'aamalan';
            $password = '123456';

            try {
                $client = new Client();
                $response = $client->request('GET', 'http://api.deywuro.com/bulksms', [
                    'query' => [
                        'username' => $username,
                        'password' => $password,
                        'type' => '0',
                        'dlr' => '1',
                        'destination' => $msisdn,
                        'source' => $senderId,
                        'message' => $msgs
                    ]
                ]);
                //$body = $response->getBody();
            } catch (\Exception $e) {
            }
        }
    }

    public static function format_phone_number($phoneNumber)
    {
        $phoneNumber = trim($phoneNumber);
        if (strlen($phoneNumber) == 9 && !starts_with($phoneNumber, '0')) {
            return '233' . $phoneNumber;
        }
        if (strlen($phoneNumber) == 10 && starts_with($phoneNumber, '0')) {
            return '233' . substr($phoneNumber, 1);
        }
        return $phoneNumber;
    }
}
