name : ContactsController.php
<?php

namespace App\Http\Controllers\Customer;

use App\Exceptions\GeneralException;
use App\Http\Requests\Contacts\ImportContact;
use App\Http\Requests\Contacts\NewContactGroup;
use App\Http\Requests\Contacts\StoreContact;
use App\Http\Requests\Contacts\UpdateContact;
use App\Http\Requests\Contacts\UpdateContactGroup;
use App\Http\Requests\Contacts\UpdateContactGroupMessage;
use App\Jobs\ImportContacts;
use App\Jobs\ReplicateContacts;
use App\Library\Tool;
use App\Models\ContactGroups;
use App\Models\ContactGroupsOptinKeywords;
use App\Models\ContactGroupsOptoutKeywords;
use App\Models\Contacts;
use App\Models\ContactsCustomField;
use App\Models\CsvData;
use App\Models\ImportJobHistory;
use App\Models\Keywords;
use App\Models\PhoneNumbers;
use App\Models\PlansCoverageCountries;
use App\Models\PlansSendingServer;
use App\Models\Senderid;
use App\Models\SendingServer;
use App\Models\TemplateTags;
use App\Models\User;
use App\Repositories\Contracts\ContactsRepository;
use App\Rules\Phone;
use Arcanedev\NoCaptcha\Rules\CaptchaRule;
use Box\Spout\Common\Exception\InvalidArgumentException;
use Box\Spout\Common\Exception\IOException;
use Box\Spout\Common\Exception\UnsupportedTypeException;
use Box\Spout\Writer\Exception\WriterNotOpenedException;
use Generator;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Bus\Batch;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\Validator;
use JetBrains\PhpStorm\NoReturn;
use Maatwebsite\Excel\Facades\Excel;
use Rap2hpoutre\FastExcel\FastExcel;
use stdClass;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Throwable;

class ContactsController extends CustomerBaseController
{
    /**
     * @var ContactsRepository $contactGroups
     */
    protected ContactsRepository $contactGroups;


    public function __construct(ContactsRepository $contactGroups)
    {
        $this->contactGroups = $contactGroups;
    }


    /**
     * view all contact list
     *
     * @return Application|Factory|View
     * @throws AuthorizationException
     */
    public function index(): View|Factory|Application
    {

        $this->authorize('view_contact_group');

        $breadcrumbs = [
                ['link' => url('dashboard'), 'name' => __('locale.menu.Dashboard')],
                ['link' => url('dashboard'), 'name' => __('locale.menu.Contacts')],
                ['name' => __('locale.contacts.contact_groups')],
        ];


        return view('customer.contactGroups.index', compact('breadcrumbs'));
    }


    /**
     * search contact groups with given data
     *
     * @param  Request  $request
     *
     * @throws AuthorizationException
     */

    #[NoReturn] public function search(Request $request): void
    {

        $this->authorize('view_contact_group');

        $columns = [
                0 => 'responsive_id',
                1 => 'uid',
                2 => 'uid',
                3 => 'name',
                4 => 'contacts',
                5 => 'created_at',
                6 => 'status',
                7 => 'action',
        ];

        $totalData = ContactGroups::where('customer_id', auth()->user()->id)->count();

        $totalFiltered = $totalData;

        $limit = $request->input('length');
        $start = $request->input('start');
        $order = $columns[$request->input('order.0.column')];
        $dir   = $request->input('order.0.dir');

        if (empty($request->input('search.value'))) {
            $contact_groups = ContactGroups::where('customer_id', auth()->user()->id)->offset($start)
                    ->limit($limit)
                    ->orderBy($order, $dir)
                    ->get();
        } else {
            $search = $request->input('search.value');

            $contact_groups = ContactGroups::where('customer_id', auth()->user()->id)->whereLike(['uid', 'name', 'status', 'created_at'], $search)
                    ->offset($start)
                    ->limit($limit)
                    ->orderBy($order, $dir)
                    ->get();

            $totalFiltered = ContactGroups::where('customer_id', auth()->user()->id)->whereLike(['uid', 'name', 'status', 'created_at'], $search)->count();
        }

        $data = [];
        if ( ! empty($contact_groups)) {
            foreach ($contact_groups as $group) {

                if ($group->status === true) {
                    $status = 'checked';
                } else {
                    $status = '';
                }

                $nestedData['responsive_id'] = '';
                $nestedData['uid']           = $group->uid;
                $nestedData['name']          = $group->name;
                $nestedData['contacts']      = Tool::number_with_delimiter($group->subscribersCount($group->cache));
                $nestedData['created_at']    = Tool::formatHumanTime($group->created_at);
                $nestedData['status']        = "<div class='form-check form-switch form-check-primary'>
                <input type='checkbox' class='form-check-input get_status' id='status_$group->uid' data-id='$group->uid' name='status' $status>
                <label class='form-check-label' for='status_$group->uid'>
                  <span class='switch-icon-left'><i data-feather='check'></i> </span>
                  <span class='switch-icon-right'><i data-feather='x'></i> </span>
                </label>
              </div>";

                $nestedData['show']              = route('customer.contacts.show', $group->uid);
                $nestedData['show_label']        = __('locale.buttons.edit');
                $nestedData['new_contact']       = route('customer.contact.create', $group->uid);
                $nestedData['new_contact_label'] = __('locale.contacts.new_contact');
                $nestedData['copy']              = __('locale.buttons.copy');
                $nestedData['delete']            = __('locale.buttons.delete');
                $nestedData['can_create']        = Auth::user()->can('create_contact');
                $nestedData['can_update']        = Auth::user()->can('update_contact_group');
                $nestedData['can_delete']        = Auth::user()->can('delete_contact_group');

                $data[] = $nestedData;

            }
        }

        $json_data = [
                "draw"            => intval($request->input('draw')),
                "recordsTotal"    => intval($totalData),
                "recordsFiltered" => intval($totalFiltered),
                "data"            => $data,
        ];

        echo json_encode($json_data);
        exit();

    }


    /**
     * create new contact group
     *
     * @return Application|Factory|View|RedirectResponse
     * @throws AuthorizationException
     */

    public function create(): View|Factory|RedirectResponse|Application
    {
        if (! Auth::user()->customer->activeSubscription() ){
            return redirect()->route('customer.subscriptions.index')->with([
                    'status'  => 'error',
                    'message' => __('locale.customer.no_active_subscription'),
            ]);
        }

        $this->authorize('create_contact_group');
        $totalData = ContactGroups::where('customer_id', auth()->user()->id)->count();
        $list_max  = Auth::user()->customer->getOption('list_max');

        if ($list_max != '-1' && $list_max < $totalData) {
            return redirect()->route('customer.contacts.index')->with([
                    'status'  => 'error',
                    'message' => __('locale.contacts.max_list_quota', ['max_list' => $list_max]),
            ]);
        }

        $breadcrumbs = [
                ['link' => url('dashboard'), 'name' => __('locale.menu.Dashboard')],
                ['link' => url('contacts'), 'name' => __('locale.menu.Contacts')],
                ['name' => __('locale.contacts.new_contact_group')],
        ];

        return view('customer.contactGroups.create', compact('breadcrumbs'));
    }

    /**
     * store contact group
     *
     * @param  NewContactGroup  $request
     *
     * @return RedirectResponse
     */

    public function store(NewContactGroup $request): RedirectResponse
    {

        if (config('app.stage') == 'demo') {
            return redirect()->route('customer.contacts.index')->with([
                    'status'  => 'error',
                    'message' => 'Sorry! This option is not available in demo mode',
            ]);
        }

        $group = $this->contactGroups->store($request->input());

        return redirect()->route('customer.contacts.show', $group->uid)->with([
                'status'  => 'success',
                'message' => __('locale.contacts.contact_group_successfully_added'),
        ]);
    }


    /**
     * View contact group for edit
     *
     * @param  ContactGroups  $contact
     *
     * @return Application|Factory|View
     *
     * @throws AuthorizationException
     */

    public function show(ContactGroups $contact): View|Factory|Application
    {
        $this->authorize('view_contact_group');

        $breadcrumbs = [
                ['link' => url('dashboard'), 'name' => __('locale.menu.Dashboard')],
                ['link' => url('contacts'), 'name' => __('locale.menu.Contacts')],
                ['name' => $contact->name],
        ];

        if (Auth::user()->customer->getOption('sender_id_verification') == 'yes') {
            $sender_ids    = Senderid::where('user_id', auth()->user()->id)->cursor();
            $phone_numbers = PhoneNumbers::where('user_id', auth()->user()->id)->cursor();
        } else {
            $sender_ids    = null;
            $phone_numbers = null;
        }
        $template_tags          = TemplateTags::cursor();
        $contact_groups         = ContactGroups::where('status', 1)->where('uid', '!=', $contact->uid)->select('uid', 'name')->cursor();
        $opt_in_keywords        = ContactGroupsOptinKeywords::where('contact_group', $contact->id)->cursor();
        $existing_opt_in        = array_column($opt_in_keywords->toArray(), 'keyword');
        $remain_opt_in_keywords = Keywords::where('user_id', $contact->customer_id)->where('status', 'assigned')->whereNotIn('keyword_name', $existing_opt_in)->select('keyword_name')->cursor();

        $opt_out_keywords        = ContactGroupsOptoutKeywords::where('contact_group', $contact->id)->cursor();
        $existing_opt_out        = array_column($opt_out_keywords->toArray(), 'keyword');
        $remain_opt_out_keywords = Keywords::where('user_id', $contact->customer_id)->where('status', 'assigned')->whereNotIn('keyword_name', $existing_opt_out)->select('keyword_name')->cursor();

        $import_history = ImportJobHistory::where('import_id', $contact->uid)->where('type', 'import_contact')->cursor();

        $plan_id = Auth::user()->customer->activeSubscription()->plan_id;

        // Check the customer has permissions using sending servers and has his own sending servers
        if (Auth::user()->customer->getOption('create_sending_server') == 'yes') {
            if (PlansSendingServer::where('plan_id', $plan_id)->count()) {

                $sending_server = SendingServer::where('user_id', Auth::user()->id)->where('plain', 1)->where('status', true)->get();

                if ($sending_server->count() == 0) {
                    $sending_server_ids = PlansSendingServer::where('plan_id', $plan_id)->pluck('sending_server_id')->toArray();
                    $sending_server     = SendingServer::where('plain', 1)->where('status', true)->whereIn('id', $sending_server_ids)->get();
                }
            } else {
                $sending_server_ids = PlansSendingServer::where('plan_id', $plan_id)->pluck('sending_server_id')->toArray();
                $sending_server     = SendingServer::where('plain', 1)->where('status', true)->whereIn('id', $sending_server_ids)->get();
            }
        } else {
            // If customer don't have permission creating sending servers
            $sending_server_ids = PlansSendingServer::where('plan_id', $plan_id)->pluck('sending_server_id')->toArray();
            $sending_server     = SendingServer::where('plain', 1)->where('status', true)->whereIn('id', $sending_server_ids)->get();
        }

        return view('customer.contactGroups.show', compact('breadcrumbs', 'contact', 'sender_ids', 'phone_numbers', 'contact_groups', 'template_tags', 'opt_in_keywords', 'opt_out_keywords', 'remain_opt_in_keywords', 'remain_opt_out_keywords', 'import_history', 'sending_server'));
    }


    /**
     * change contact group status
     *
     * @param  ContactGroups  $contact
     *
     * @return JsonResponse
     *
     * @throws AuthorizationException
     * @throws GeneralException
     */
    public function activeToggle(ContactGroups $contact): JsonResponse
    {
        if (config('app.stage') == 'demo') {
            return response()->json([
                    'status'  => 'error',
                    'message' => 'Sorry! This option is not available in demo mode',
            ]);
        }

        try {
            $this->authorize('update_contact_group');

            if ($contact->update(['status' => ! $contact->status])) {
                return response()->json([
                        'status'  => 'success',
                        'message' => __('locale.contacts.contact_group_successfully_change'),
                ]);
            }

            throw new GeneralException(__('locale.exceptions.something_went_wrong'));
        } catch (ModelNotFoundException $exception) {
            return response()->json([
                    'status'  => 'error',
                    'message' => $exception->getMessage(),
            ]);
        }

    }


    /**
     * copy contact groups
     *
     * @param  ContactGroups  $contact
     * @param  Request  $request
     *
     * @return JsonResponse
     * @throws AuthorizationException
     */
    public function copy(ContactGroups $contact, Request $request): JsonResponse
    {

        if (config('app.stage') == 'demo') {
            return response()->json([
                    'status'  => 'error',
                    'message' => 'Sorry! This option is not available in demo mode',
            ]);
        }

        $this->authorize('create_contact_group');

        $totalData = ContactGroups::where('customer_id', auth()->user()->id)->count();
        $list_max  = Auth::user()->customer->getOption('list_max');

        if ($list_max != '-1' && $list_max < $totalData) {
            return response()->json([
                    'status'  => 'error',
                    'message' => __('locale.contacts.max_list_quota', ['max_list' => $list_max]),
            ]);
        }

        $subscriber_per_list_max = Contacts::where('group_id', $contact->id)->count();

        if (Auth::user()->customer->getOption('subscriber_per_list_max') != '-1' && $subscriber_per_list_max > Auth::user()->customer->getOption('subscriber_per_list_max')) {
            $subscriber_max = Contacts::where('customer_id', Auth::user()->id)->count();
            if (Auth::user()->customer->getOption('subscriber_max') != '-1' && $subscriber_max > Auth::user()->customer->getOption('subscriber_max')) {
                return response()->json([
                        'status'  => 'error',
                        'message' => __('locale.contacts.subscriber_max_quota', ['subscriber_max' => Auth::user()->customer->getOption('subscriber_max')]),
                ]);
            }

            return response()->json([
                    'status'  => 'error',
                    'message' => __('locale.contacts.subscriber_per_list_max_quota', ['subscriber_per_list_max' => Auth::user()->customer->getOption('subscriber_per_list_max')]),
            ]);
        }

        $new_group       = $contact->replicate();
        $new_group->name = $request->group_name;
        $new_group->save();
        $new_group_id = $new_group->id;

        $opt_in_keyword = ContactGroupsOptinKeywords::where('contact_group', $contact->id)->get();
        foreach ($opt_in_keyword as $keyword) {
            $new_keyword                = $keyword->replicate();
            $new_keyword->uid           = uniqid();
            $new_keyword->contact_group = $new_group_id;
            $new_keyword->save();
        }

        $opt_out_keyword = ContactGroupsOptoutKeywords::where('contact_group', $contact->id)->get();
        foreach ($opt_out_keyword as $keyword) {
            $new_keyword                = $keyword->replicate();
            $new_keyword->uid           = uniqid();
            $new_keyword->contact_group = $new_group_id;
            $new_keyword->save();
        }

        $count = Contacts::where('group_id', $contact->id)->count();

        if ($count > 2000) {
            $batch_list = [];
            Tool::resetMaxExecutionTime();
            Contacts::where('group_id', $contact->id)->cursor()
                    ->chunk(5000)
                    ->each(function ($lines) use ($new_group_id, &$batch_list) {
                        $batch_list[] = new ReplicateContacts($new_group_id, $lines);
                    });

            try {
                $import_name = 'CopyContacts_'.date('Ymdhms');

                $import_job = ImportJobHistory::create([
                        'name'      => $import_name,
                        'import_id' => $new_group->uid,
                        'type'      => 'import_contact',
                        'status'    => 'processing',
                        'options'   => json_encode(['status' => 'processing', 'message' => 'Import contacts are running']),
                        'batch_id'  => null,
                ]);

                $batch = Bus::batch($batch_list)
                        ->then(function (Batch $batch) use ($new_group, $import_name, $import_job) {
                            $new_group->update(['batch_id' => $batch->id]);
                            $import_job->update(['batch_id' => $batch->id]);
                        })
                        ->catch(function (Batch $batch, Throwable $e) {
                            $import_history = ImportJobHistory::where('batch_id', $batch->id)->first();
                            if ($import_history) {
                                $import_history->status  = 'failed';
                                $import_history->options = json_encode(['status' => 'failed', 'message' => $e->getMessage()]);
                                $import_history->save();
                            }

                        })
                        ->finally(function (Batch $batch) {
                            $import_history = ImportJobHistory::where('batch_id', $batch->id)->first();
                            if ($import_history) {
                                $import_history->status  = 'finished';
                                $import_history->options = json_encode(['status' => 'finished', 'message' => 'Import contacts was successfully imported.']);
                                $import_history->save();
                            }
                        })
                        ->name($import_name)
                        ->dispatch();

                $new_group->update(['batch_id' => $batch->id]);

                return response()->json([
                        'status'  => 'success',
                        'message' => __('locale.contacts.contact_successfully_imported_in_background'),
                ]);

            } catch (Throwable $e) {
                return response()->json([
                        'status'  => 'error',
                        'message' => $e->getMessage(),
                ]);
            }
        } else {
            Contacts::where('group_id', $contact->id)->cursor()->chunk('250')->each(function ($lines) use ($new_group_id) {

                foreach ($lines as $line) {
                    $new_contact             = $line->replicate();
                    $new_contact->uid        = uniqid();
                    $new_contact->group_id   = $new_group_id;
                    $new_contact->created_at = now()->toDateTimeString();
                    $new_contact->updated_at = now()->toDateTimeString();

                    $new_contact->save();
                }
            });

            return response()->json([
                    'status'  => 'success',
                    'message' => __('locale.contacts.contact_group_successfully_copied'),
            ]);
        }
    }

    /**
     * update contact group settings
     *
     * @param  ContactGroups  $contact
     * @param  UpdateContactGroup  $request
     *
     * @return RedirectResponse
     */

    public function update(ContactGroups $contact, UpdateContactGroup $request): RedirectResponse
    {

        if (config('app.stage') == 'demo') {
            return redirect()->route('customer.contacts.index')->with([
                    'status'  => 'error',
                    'message' => 'Sorry! This option is not available in demo mode',
            ]);
        }

        $group = $this->contactGroups->update($contact, $request->except('_method', '_token'));

        return redirect()->route('customer.contacts.show', $group->uid)->withInput(['tab' => 'settings'])->with([
                'status'  => 'success',
                'message' => __('locale.contacts.contact_group_successfully_updated'),
        ]);
    }

    /**
     * delete contact group
     *
     * @param  ContactGroups  $contact
     *
     * @return JsonResponse
     * @throws AuthorizationException
     */
    public function destroy(ContactGroups $contact): JsonResponse
    {
        if (config('app.stage') == 'demo') {
            return response()->json([
                    'status'  => 'error',
                    'message' => 'Sorry! This option is not available in demo mode',
            ]);
        }

        $this->authorize('delete_contact_group');

        $this->contactGroups->destroy($contact);

        return response()->json([
                'status'  => 'success',
                'message' => __('locale.contacts.contact_group_successfully_deleted'),
        ]);
    }

    /**
     * Bulk Action with Enable, Disable and Delete
     *
     * @param  Request  $request
     *
     * @return JsonResponse
     * @throws AuthorizationException
     */

    public function batchAction(Request $request): JsonResponse
    {

        if (config('app.stage') == 'demo') {
            return response()->json([
                    'status'  => 'error',
                    'message' => 'Sorry! This option is not available in demo mode',
            ]);
        }

        $action = $request->get('action');
        $ids    = $request->get('ids');

        switch ($action) {
            case 'destroy':
                $this->authorize('delete_contact_group');

                $this->contactGroups->batchDestroy($ids);

                return response()->json([
                        'status'  => 'success',
                        'message' => __('locale.contacts.contact_groups_deleted'),
                ]);

            case 'enable':
                $this->authorize('update_contact_group');

                $this->contactGroups->batchActive($ids);

                return response()->json([
                        'status'  => 'success',
                        'message' => __('locale.contacts.contact_groups_enabled'),
                ]);

            case 'disable':

                $this->authorize('update_contact_group');

                $this->contactGroups->batchDisable($ids);

                return response()->json([
                        'status'  => 'success',
                        'message' => __('locale.contacts.contact_groups_disabled'),
                ]);
        }

        return response()->json([
                'status'  => 'error',
                'message' => __('locale.exceptions.invalid_action'),
        ]);

    }


    /**
     * search contact with given data
     *
     * @param  ContactGroups  $contact
     * @param  Request  $request
     *
     * @throws AuthorizationException
     */

    #[NoReturn] public function searchContact(ContactGroups $contact, Request $request): void
    {

        $this->authorize('view_contact');

        $columns = [
                0 => 'responsive_id',
                1 => 'uid',
                2 => 'uid',
                3 => 'phone',
                4 => 'name',
                5 => 'created_at',
                6 => 'status',
                7 => 'action',
        ];

        $totalData = Contacts::where('customer_id', auth()->user()->id)->where('group_id', $contact->id)->count();

        $totalFiltered = $totalData;

        $limit = $request->input('length');
        $start = $request->input('start');
        $order = $columns[$request->input('order.0.column')];
        $dir   = $request->input('order.0.dir');

        if (empty($request->input('search.value'))) {
            $contacts = Contacts::where('customer_id', auth()->user()->id)->where('group_id', $contact->id)->offset($start)
                    ->limit($limit)
                    ->orderBy($order, $dir)
                    ->get();
        } else {
            $search = $request->input('search.value');

            $contacts = Contacts::where('customer_id', auth()->user()->id)->where('group_id', $contact->id)->whereLike(['uid', 'phone', 'first_name', 'last_name', 'status'], $search)
                    ->offset($start)
                    ->limit($limit)
                    ->orderBy($order, $dir)
                    ->get();

            $totalFiltered = Contacts::where('customer_id', auth()->user()->id)->where('group_id', $contact->id)->whereLike(['uid', 'phone', 'first_name', 'last_name', 'status'], $search)->count();
        }

        $data = [];
        if ( ! empty($contacts)) {
            foreach ($contacts as $singleContact) {

                if ($singleContact->status == 'subscribe') {
                    $status = 'checked';
                } else {
                    $status = '';
                }


                $display_name = $singleContact->display_name();
                if ($display_name == ' ') {
                    $display_name = __('locale.labels.no_name');
                }

                $nestedData['responsive_id'] = '';
                $nestedData['uid']           = $singleContact->uid;
                $nestedData['phone']         = $singleContact->phone;
                $nestedData['name']          = $display_name;
                $nestedData['created_at']    = Tool::formatHumanTime($singleContact->created_at);
                $nestedData['status']        = "<div class='form-check form-switch form-check-primary form-switch-xl'>
                <input type='checkbox' class='form-check-input get_status' id='status_$singleContact->uid' data-id='$singleContact->uid' name='status' $status>
                <label class='form-check-label' for='status_$singleContact->uid'>
                  <span class='switch-text-left'>".__('locale.labels.subscribe')."</span>
                  <span class='switch-text-right'>".__('locale.labels.unsubscribe')."</span>
                </label>
              </div>";


                $nestedData['show']             = route('customer.contact.edit', ['contact' => $contact->uid, 'contact_id' => $singleContact->uid]);
                $nestedData['show_label']       = __('locale.buttons.edit');
                $nestedData['conversion']       = route('customer.reports.all', ['recipient' => $singleContact->phone]);
                $nestedData['conversion_label'] = __('locale.contacts.view_conversion');
                $nestedData['send_sms']         = route('customer.sms.quick_send', ['recipient' => $singleContact->phone]);
                $nestedData['send_sms_label']   = __('locale.contacts.send_message');
                $nestedData['delete']           = __('locale.buttons.delete');
                $data[] = $nestedData;

            }
        }

        $json_data = [
                "draw"            => intval($request->input('draw')),
                "recordsTotal"    => intval($totalData),
                "recordsFiltered" => intval($totalFiltered),
                "data"            => $data,
        ];

        echo json_encode($json_data);
        exit();

    }

    /**
     * add new contact in a group
     *
     * @param  ContactGroups  $contact
     *
     * @return Application|Factory|View|RedirectResponse
     * @throws AuthorizationException
     */
    public function createContact(ContactGroups $contact): View|Factory|RedirectResponse|Application
    {
        $this->authorize('create_contact');

        $subscriber_per_list_max = Contacts::where('group_id', $contact->id)->count();

        if (Auth::user()->customer->getOption('subscriber_per_list_max') != '-1' && $subscriber_per_list_max > Auth::user()->customer->getOption('subscriber_per_list_max')) {
            $subscriber_max = Contacts::where('customer_id', Auth::user()->id)->count();
            if (Auth::user()->customer->getOption('subscriber_max') != '-1' && $subscriber_max > Auth::user()->customer->getOption('subscriber_max')) {
                return redirect()->route('customer.contacts.show', $contact->uid)->with([
                        'status'  => 'error',
                        'message' => __('locale.contacts.subscriber_max_quota', ['subscriber_max' => Auth::user()->customer->getOption('subscriber_max')]),
                ]);
            }

            return redirect()->route('customer.contacts.show', $contact->uid)->withInput(['tab' => 'contact'])->with([
                    'status'  => 'error',
                    'message' => __('locale.contacts.subscriber_per_list_max_quota', ['subscriber_per_list_max' => Auth::user()->customer->getOption('subscriber_per_list_max')]),
            ]);
        }

        $breadcrumbs = [
                ['link' => url('dashboard'), 'name' => __('locale.menu.Dashboard')],
                ['link' => route('customer.contacts.show', $contact->uid), 'name' => $contact->name],
                ['name' => __('locale.contacts.new_contact')],
        ];

        return view('customer.Contacts.create', compact('breadcrumbs', 'contact'));
    }

    /**
     * store new contact
     *
     * @param  ContactGroups  $contact
     * @param  StoreContact  $request
     *
     * @return RedirectResponse
     */
    public function storeContact(ContactGroups $contact, StoreContact $request): RedirectResponse
    {
        if (config('app.stage') == 'demo') {
            return redirect()->route('customer.contacts.show', $contact->uid)->withInput(['tab' => 'contact'])->with([
                    'status'  => 'error',
                    'message' => 'Sorry! This option is not available in demo mode',
            ]);
        }

        $phone = str_replace(['(', ')', '+', '-', ' '], '', $request->phone);

        $exist = Contacts::where('group_id', $contact->id)->where('customer_id', Auth::user()->id)->where('phone', $phone)->first();
        if ($exist) {
            return redirect()->route('customer.contact.create', $contact->uid)->withInput(['tab' => 'contact', 'phone' => $request->phone])->with([
                    'status'  => 'error',
                    'message' => __('locale.contacts.you_have_already_subscribed', ['contact_group' => $contact->name]),
            ]);
        }

        $this->contactGroups->storeContact($contact, $request->only('phone', 'first_name', 'last_name'));

        return redirect()->route('customer.contacts.show', $contact->uid)->withInput(['tab' => 'contact'])->with([
                'status'  => 'success',
                'message' => __('locale.contacts.contact_successfully_added'),
        ]);
    }

    /**
     * update contact status
     *
     * @param  ContactGroups  $contact
     * @param  Request  $request
     *
     * @return JsonResponse
     * @throws AuthorizationException
     */
    public function updateContactStatus(ContactGroups $contact, Request $request): JsonResponse
    {

        if (config('app.stage') == 'demo') {
            return response()->json([
                    'status'  => 'error',
                    'message' => 'Sorry! This option is not available in demo mode',
            ]);
        }


        $this->authorize('update_contact');
        $status = $this->contactGroups->updateContactStatus($contact, $request->only('id'));
        if ($status) {
            return response()->json([
                    'status'  => 'success',
                    'message' => __('locale.contacts.contact_successfully_change'),
            ]);
        }

        return response()->json([
                'status'  => 'error',
                'message' => __('locale.exceptions.something_went_wrong'),
        ]);
    }

    /**
     * delete single contact from group
     *
     * @param  ContactGroups  $contact
     * @param  Request  $request
     *
     * @return JsonResponse
     * @throws AuthorizationException
     */
    public function deleteContact(ContactGroups $contact, Request $request): JsonResponse
    {

        if (config('app.stage') == 'demo') {
            return response()->json([
                    'status'  => 'error',
                    'message' => 'Sorry! This option is not available in demo mode',
            ]);
        }

        $this->authorize('delete_contact');

        $status = $this->contactGroups->contactDestroy($contact, $request->only('id'));

        if ($status) {
            return response()->json([
                    'status'  => 'success',
                    'message' => __('locale.contacts.contact_successfully_deleted'),
            ]);
        }

        return response()->json([
                'status'  => 'error',
                'message' => __('locale.exceptions.something_went_wrong'),
        ]);

    }

    /**
     * view single contact for edit
     *
     * @param  ContactGroups  $contact
     * @param  Request  $request
     *
     * @return Application|Factory|View|RedirectResponse
     * @throws AuthorizationException
     */
    public function editContact(ContactGroups $contact, Request $request): View|Factory|RedirectResponse|Application
    {

        $this->authorize('update_contact');

        $data = Contacts::where('group_id', $contact->id)->where('customer_id', Auth::user()->id)->where('uid', $request->contact_id)->first();
        if ($data) {

            $breadcrumbs = [
                    ['link' => url('dashboard'), 'name' => __('locale.menu.Dashboard')],
                    ['link' => route('customer.contacts.show', $contact->uid), 'name' => $contact->name],
                    ['name' => __('locale.contacts.update_contact')],
            ];

            $template_tags = null;
            $custom_fields = ContactsCustomField::where('contact_id', $data->id)->cursor();
            if ($custom_fields->count() == 0) {
                $custom_fields = null;
                $template_tags = TemplateTags::cursor();
            }

            return view('customer.Contacts.show', compact('breadcrumbs', 'contact', 'data', 'custom_fields', 'template_tags'));
        }

        return redirect()->route('customer.contacts.show', $contact->uid)->with([
                'status'  => 'error',
                'message' => __('locale.contacts.contact_not_found'),
        ]);
    }

    /**
     * update single contact information
     *
     * @param  ContactGroups  $contact
     * @param  UpdateContact  $request
     *
     * @return RedirectResponse
     */
    public function updateContact(ContactGroups $contact, UpdateContact $request): RedirectResponse
    {
        if (config('app.stage') == 'demo') {
            return redirect()->route('customer.contacts.show', $contact->uid)->with([
                    'status'  => 'error',
                    'message' => 'Sorry! This option is not available in demo mode',
            ]);
        }

        $status = $this->contactGroups->updateContact($contact, $request->except('_token'));
        if ($status) {
            return redirect()->route('customer.contacts.show', $contact->uid)->withInput(['tab' => 'contact'])->with([
                    'status'  => 'success',
                    'message' => __('locale.contacts.contact_successfully_updated'),
            ]);
        }

        return redirect()->route('customer.contacts.show', $contact->uid)->withInput(['tab' => 'contact'])->with([
                'status'  => 'error',
                'message' => __('locale.exceptions.something_went_wrong'),
        ]);
    }

    /**
     * import contact using csv or excel
     *
     * @param  ContactGroups  $contact
     *
     * @return Application|Factory|View
     * @throws AuthorizationException
     */
    public function importContact(ContactGroups $contact): View|Factory|Application
    {

        $this->authorize('view_contact_group');

        $breadcrumbs = [
                ['link' => url('dashboard'), 'name' => __('locale.menu.Dashboard')],
                ['link' => url('contacts'), 'name' => __('locale.menu.Contacts')],
                ['name' => $contact->name],
        ];

        return view('customer.Contacts.import', compact('breadcrumbs', 'contact'));
    }

    /**
     * working with import contacts
     *
     * @param  ContactGroups  $contact
     * @param  ImportContact  $request
     *
     * @return Application|Factory|View|RedirectResponse
     */
    public function storeImportContact(ContactGroups $contact, ImportContact $request): View|Factory|RedirectResponse|Application
    {
        if (isset($request->option_toggle) && $request->option_toggle == 'on' && isset($request->import_file) && $request->hasFile('import_file')) {
            if ($request->file('import_file')->isValid()) {

                $breadcrumbs = [
                        ['link' => url('dashboard'), 'name' => __('locale.menu.Dashboard')],
                        ['link' => url('contacts'), 'name' => __('locale.menu.Contacts')],
                        ['name' => $contact->name],
                ];

                $data = Excel::toArray(new stdClass(), $request->file('import_file'))[0];

                $csv_data_file = CsvData::create([
                        'user_id'      => Auth::user()->id,
                        'ref_id'       => $contact->uid,
                        'ref_type'     => CsvData::TYPE_CONTACT,
                        'csv_filename' => $request->file('import_file')->getClientOriginalName(),
                        'csv_header'   => $request->has('header'),
                        'csv_data'     => json_encode($data),
                ]);

                $csv_data = array_slice($data, 0, 2);

                return view('customer.Contacts.import_fields', compact('csv_data', 'contact', 'csv_data_file', 'breadcrumbs'));
            }
        } elseif (isset($request->recipients) && $request->recipients != null) {

            if (config('app.stage') == 'demo') {
                return redirect()->route('customer.contacts.show', $contact->uid)->withInput(['tab' => 'contact'])->with([
                        'status'  => 'error',
                        'message' => 'Sorry! This option is not available in demo mode',
                ]);
            }

            if ($request->delimiter == ';') {
                $recipients = explode(';', $request->recipients);
            } elseif ($request->delimiter == ',') {
                $recipients = explode(',', $request->recipients);
            } elseif ($request->delimiter == '|') {
                $recipients = explode('|', $request->recipients);
            } elseif ($request->delimiter == 'tab') {
                $recipients = explode(' ', $request->recipients);
            } elseif ($request->delimiter == 'new_line') {
                $recipients = explode("\n", $request->recipients);
            } else {
                return redirect()->route('customer.contacts.show', $contact->uid)->withInput(['tab' => 'contact'])->with([
                        'status'  => 'error',
                        'message' => __('locale.labels.invalid_delimiter'),
                ]);
            }

            if (isset($recipients) && is_array($recipients) && count($recipients) > 1000) {
                return redirect()->route('customer.contacts.show', $contact->uid)->withInput(['tab' => 'contact'])->with([
                        'status'  => 'error',
                        'message' => __('locale.contacts.upload_maximum_1000_rows'),
                ]);
            }

            collect($recipients)->unique()->chunk('250')->each(function ($lines) use ($contact) {
                $list = [];
                foreach ($lines as $line) {

                    $exist = Contacts::where('group_id', $contact->id)->where('customer_id', Auth::user()->id)->where('phone', $line)->first();
                    if ( ! $exist){
                        $list[] = [
                                'uid'         => uniqid(),
                                'customer_id' => Auth::user()->id,
                                'group_id'    => $contact->id,
                                'status'      => 'subscribe',
                                'phone'       => $line,
                                'created_at'  => now()->toDateTimeString(),
                                'updated_at'  => now()->toDateTimeString(),
                        ];
                    }
                }

                Contacts::insert($list);
            });

            $contact->updateCache('SubscribersCount');

            return redirect()->route('customer.contacts.show', $contact->uid)->withInput(['tab' => 'contact'])->with([
                    'status'  => 'success',
                    'message' => __('locale.contacts.contact_successfully_imported'),
            ]);

        } else {
            return redirect()->route('customer.contacts.show', $contact->uid)->withInput(['tab' => 'contact'])->with([
                    'status'  => 'error',
                    'message' => __('locale.exceptions.invalid_action'),
            ]);
        }

        return redirect()->route('customer.contacts.show', $contact->uid)->withInput(['tab' => 'contact'])->with([
                'status'  => 'error',
                'message' => __('locale.exceptions.something_went_wrong'),
        ]);
    }


    /**
     * import process data
     *
     * @param  ContactGroups  $contact
     * @param  Request  $request
     *
     * @return RedirectResponse
     */
    public function importProcessData(ContactGroups $contact, Request $request): RedirectResponse
    {

        if (config('app.stage') == 'demo') {
            return redirect()->route('customer.contacts.show', $contact->uid)->with([
                    'status'  => 'error',
                    'message' => 'Sorry! This option is not available in demo mode',
            ]);
        }

        $data      = CsvData::find($request->csv_data_file_id);
        $csv_data  = json_decode($data->csv_data, true);
        $db_fields = $request->fields;

        if (is_array($db_fields) && ! in_array('phone', $db_fields)) {
            return redirect()->route('customer.contacts.show', $contact->uid)->with([
                    'status'  => 'error',
                    'message' => __('locale.filezone.phone_number_column_require'),
            ]);
        }

        $collection = collect($csv_data)->skip($data->csv_header);

        $batch_list = [];
        Tool::resetMaxExecutionTime();
        $collection->chunk(5000)
                ->each(function ($lines) use ($contact, &$batch_list, $db_fields) {
                    $batch_list[] = new ImportContacts(Auth::user()->id, $contact->id, $lines, $db_fields);
                });

        try {
            $import_name = 'ImportContacts_'.date('Ymdhms');

            $import_job = ImportJobHistory::create([
                    'name'      => $import_name,
                    'import_id' => $contact->uid,
                    'type'      => 'import_contact',
                    'status'    => 'processing',
                    'options'   => json_encode(['status' => 'processing', 'message' => 'Import contacts are running']),
                    'batch_id'  => null,
            ]);

            $batch = Bus::batch($batch_list)
                    ->then(function (Batch $batch) use ($contact, $import_name, $import_job) {
                        $contact->update(['batch_id' => $batch->id]);
                        $import_job->update(['batch_id' => $batch->id]);
                    })
                    ->catch(function (Batch $batch, Throwable $e) {
                        $import_history = ImportJobHistory::where('batch_id', $batch->id)->first();
                        if ($import_history) {
                            $import_history->status  = 'failed';
                            $import_history->options = json_encode(['status' => 'failed', 'message' => $e->getMessage()]);
                            $import_history->save();
                        }

                    })
                    ->finally(function (Batch $batch) use ($contact, $data) {
                        $import_history = ImportJobHistory::where('batch_id', $batch->id)->first();
                        if ($import_history) {
                            $import_history->status  = 'finished';
                            $import_history->options = json_encode(['status' => 'finished', 'message' => 'Import contacts was successfully imported.']);
                            $import_history->save();
                        }

                        $contact->updateCache('SubscribersCount');
                        $data->delete();
                        //send event notification remaining
                    })
                    ->name($import_name)
                    ->dispatch();

            $contact->update(['batch_id' => $batch->id]);

            return redirect()->route('customer.contacts.show', $contact->uid)->withInput(['tab' => 'import_history'])->with([
                    'status'  => 'success',
                    'message' => __('locale.contacts.contact_successfully_imported_in_background'),
            ]);

        } catch (Throwable $e) {
            return redirect()->route('customer.contacts.show', $contact->uid)->withInput(['tab' => 'import_history'])->with([
                    'status'  => 'error',
                    'message' => $e->getMessage(),
            ]);
        }
    }

    /**
     * Bulk Action with subscribe, unsubscribe and Delete contacts
     *
     * @param  ContactGroups  $contact
     * @param  Request  $request
     *
     * @return JsonResponse
     * @throws AuthorizationException
     */

    public function batchActionContact(ContactGroups $contact, Request $request): JsonResponse
    {

        if (config('app.stage') == 'demo') {
            return response()->json([
                    'status'  => 'error',
                    'message' => 'Sorry! This option is not available in demo mode',
            ]);
        }

        $action = $request->get('action');
        $ids    = $request->get('ids');

        switch ($action) {
            case 'destroy':

                $this->authorize('delete_contact');

                $this->contactGroups->batchContactDestroy($contact, $ids);

                return response()->json([
                        'status'  => 'success',
                        'message' => __('locale.contacts.contacts_deleted'),
                ]);

            case 'subscribe':

                $this->authorize('update_contact');

                $this->contactGroups->batchContactSubscribe($contact, $ids);

                return response()->json([
                        'status'  => 'success',
                        'message' => __('locale.contacts.contacts_subscribe'),
                ]);

            case 'unsubscribe':

                $this->authorize('update_contact');

                $this->contactGroups->batchContactUnsubscribe($contact, $ids);

                return response()->json([
                        'status'  => 'success',
                        'message' => __('locale.contacts.contacts_unsubscribe'),
                ]);

            case 'copy':

                $this->authorize('update_contact');

                $target_group = $request->get('target_group');
                $group        = ContactGroups::where('uid', $target_group)->first();

                if ( ! $group) {
                    return response()->json([
                            'status'  => 'error',
                            'message' => __('locale.contacts.contact_group_not_found'),
                    ]);
                }

                $input = [
                        'ids'          => $ids,
                        'target_group' => $group->id,
                ];

                $this->contactGroups->batchContactCopy($contact, $input);

                return response()->json([
                        'status'  => 'success',
                        'message' => __('locale.contacts.contacts_copy'),
                ]);

            case 'move':

                $this->authorize('update_contact');

                $target_group = $request->get('target_group');
                $group        = ContactGroups::where('uid', $target_group)->first();

                if ( ! $group) {
                    return response()->json([
                            'status'  => 'error',
                            'message' => __('locale.contacts.contact_group_not_found'),
                    ]);
                }

                $input = [
                        'ids'          => $ids,
                        'target_group' => $group->id,
                ];

                $this->contactGroups->batchContactMove($contact, $input);

                return response()->json([
                        'status'  => 'success',
                        'message' => __('locale.contacts.contacts_moved'),
                ]);
        }

        return response()->json([
                'status'  => 'error',
                'message' => __('locale.exceptions.invalid_action'),
        ]);

    }


    /**
     * @param $group_id
     *
     * @return Generator
     */

    public function contactsGenerator($group_id): Generator
    {
        foreach (Contacts::where('group_id', $group_id)->cursor() as $contact) {
            yield $contact;
        }
    }


    /**
     * @param  ContactGroups  $contact
     *
     * @return RedirectResponse|BinaryFileResponse
     * @throws AuthorizationException
     * @throws IOException
     * @throws InvalidArgumentException
     * @throws UnsupportedTypeException
     * @throws WriterNotOpenedException
     */
    public function exportContact(ContactGroups $contact): BinaryFileResponse|RedirectResponse
    {
        if (config('app.stage') == 'demo') {
            return redirect()->route('customer.contacts.show', $contact->uid)->with([
                    'status'  => 'error',
                    'message' => 'Sorry! This option is not available in demo mode',
            ]);
        }


        $this->authorize('view_contact');

        $file_name = (new FastExcel($this->contactsGenerator($contact->id)))->export(storage_path('Contacts_'.time().'.xlsx'));

        return response()->download($file_name);
    }


    /**
     * @param  ContactGroups  $contact
     *
     * @return Application|Factory|View
     */
    public function subscribeURL(ContactGroups $contact): View|Factory|Application
    {
        $pageConfigs = [
                'bodyClass' => "bg-full-screen-image",
                'blankPage' => true,
        ];

        $user     = User::find($contact->customer_id);
        $coverage = null;
        if ($user) {
            $plan_id  = $user->customer->activeSubscription()->plan_id;
            $coverage = PlansCoverageCountries::where('plan_id', $plan_id)->where('status', true)->cursor();

            return view('customer.Contacts.subscribe_form', compact('contact', 'pageConfigs', 'coverage'));
        }


        return view('customer.Contacts.subscribe_form', compact('contact', 'pageConfigs', 'coverage'));
    }

    /**
     * insert contact by subscription form
     *
     * @param  ContactGroups  $contact
     * @param  Request  $request
     *
     * @return RedirectResponse
     */
    public function insertContactBySubscriptionForm(ContactGroups $contact, Request $request): RedirectResponse
    {
        if (config('app.stage') == 'demo') {
            return redirect()->route('customer.contacts.show', $contact->uid)->with([
                    'status'  => 'error',
                    'message' => 'Sorry! This option is not available in demo mode',
            ]);
        }

        $rules = [
                'phone' => ['required', new Phone($request->phone)],
        ];

        if (config('no-captcha.registration')) {
            $rules['g-recaptcha-response'] = ['required', new CaptchaRule()];
        }

        $messages = [
                'g-recaptcha-response.required' => __('locale.auth.recaptcha_required'),
                'g-recaptcha-response.captcha'  => __('locale.auth.recaptcha_required'),
        ];

        $validation = Validator::make($request->all(), $rules, $messages);

        if ($validation->fails()) {
            return redirect()->route('contacts.subscribe_url', $contact->uid)->withInput($request->all())->withErrors($validation->errors());
        }

        if ($request->country_code) {
            $phone = $request->country_code.ltrim($request->phone, 0);
        } else {
            $phone = $request->phone;
        }

        $exist = Contacts::where('group_id', $contact->id)->where('phone', $phone)->first();

        if ($exist) {
            return redirect()->route('contacts.subscribe_url', $contact->uid)->with([
                    'status'  => 'error',
                    'message' => __('locale.contacts.you_have_already_subscribed', ['contact_group' => $contact->name]),
            ]);
        }

        $this->contactGroups->storeContact($contact, ['phone' => $phone, 'first_name' => $request->first_name, 'last_name' => $request->last_name]);

        return redirect()->route('contacts.subscribe_url', $contact->uid)->with([
                'status'  => 'success',
                'message' => __('locale.contacts.you_have_successfully_subscribe', ['contact_group' => $contact->name]),
        ]);

    }

    /**
     * return sms form data
     *
     * @param  ContactGroups  $contact
     * @param  Request  $request
     *
     * @return JsonResponse
     */
    public function getMessageForm(ContactGroups $contact, Request $request): JsonResponse
    {
        return response()->json([
                'status'  => 'success',
                'message' => $contact->{$request->sms_form},
        ]);
    }

    /**
     * update contact groups message
     *
     * @param  ContactGroups  $contact
     * @param  UpdateContactGroupMessage  $request
     *
     * @return RedirectResponse
     */
    public function message(ContactGroups $contact, UpdateContactGroupMessage $request): RedirectResponse
    {
        if (config('app.stage') == 'demo') {
            return redirect()->route('customer.contacts.show', $contact->uid)->with([
                    'status'  => 'error',
                    'message' => 'Sorry! This option is not available in demo mode',
            ]);
        }

        $contact->{$request->message_form} = $request->message;
        $contact->save();

        return redirect()->route('customer.contacts.show', $contact->uid)->withInput(['tab' => 'message'])->with([
                'status'  => 'success',
                'message' => __('locale.contacts.contact_groups_message_information', ['message_from' => ucfirst(str_replace('_', ' ', $request->message_form))]),
        ]);
    }

    /**
     * add opt in keyword
     *
     * @param  ContactGroups  $contact
     * @param  Request  $request
     *
     * @return JsonResponse
     */
    public function optInKeyword(ContactGroups $contact, Request $request): JsonResponse
    {

        if (config('app.stage') == 'demo') {
            return response()->json([
                    'status'  => 'error',
                    'message' => 'Sorry! This option is not available in demo mode',
            ]);
        }
        $keyword_name = $request->keyword_name;
        if ($keyword_name) {
            $keyword = Keywords::where('user_id', Auth::user()->id)->where('keyword_name', $keyword_name)->first();
            if ($keyword) {
                $status = ContactGroupsOptinKeywords::create([
                        'contact_group' => $contact->id,
                        'keyword'       => $keyword_name,
                ]);

                if ($status) {
                    return response()->json([
                            'status'  => 'success',
                            'message' => __('locale.contacts.optin_keyword_successfully_added'),
                    ]);
                }

                return response()->json([
                        'status'  => 'error',
                        'message' => __('locale.exceptions.something_went_wrong'),
                ]);

            }

            return response()->json([
                    'status'  => 'error',
                    'message' => __('locale.contacts.keyword_info_not_found'),
            ]);
        }

        return response()->json([
                'status'  => 'error',
                'message' => __('locale.labels.at_least_one_data'),
        ]);
    }

    /**
     * add opt in keyword
     *
     * @param  ContactGroups  $contact
     * @param  Request  $request
     *
     * @return JsonResponse
     */
    public function optOutKeyword(ContactGroups $contact, Request $request): JsonResponse
    {

        if (config('app.stage') == 'demo') {
            return response()->json([
                    'status'  => 'error',
                    'message' => 'Sorry! This option is not available in demo mode',
            ]);
        }

        $keyword_name = $request->keyword_name;
        if ($keyword_name) {
            $keyword = Keywords::where('user_id', Auth::user()->id)->where('keyword_name', $keyword_name)->first();
            if ($keyword) {

                $status = ContactGroupsOptoutKeywords::create([
                        'contact_group' => $contact->id,
                        'keyword'       => $keyword_name,
                ]);

                if ($status) {
                    return response()->json([
                            'status'  => 'success',
                            'message' => __('locale.contacts.optout_keyword_successfully_added'),
                    ]);
                }

                return response()->json([
                        'status'  => 'error',
                        'message' => __('locale.exceptions.something_went_wrong'),
                ]);

            }

            return response()->json([
                    'status'  => 'error',
                    'message' => __('locale.contacts.keyword_info_not_found'),
            ]);
        }

        return response()->json([
                'status'  => 'error',
                'message' => __('locale.labels.at_least_one_data'),
        ]);
    }


    /**
     * delete opt in keyword
     *
     * @param  ContactGroups  $contact
     * @param  Request  $request
     *
     * @return JsonResponse
     */
    public function deleteOptInKeyword(ContactGroups $contact, Request $request): JsonResponse
    {

        if (config('app.stage') == 'demo') {
            return response()->json([
                    'status'  => 'error',
                    'message' => 'Sorry! This option is not available in demo mode',
            ]);
        }
        $keyword_id    = $request->id;
        $optin_keyword = ContactGroupsOptinKeywords::where('contact_group', $contact->id)->where('uid', $keyword_id)->delete();
        if ($optin_keyword) {
            return response()->json([
                    'status'  => 'success',
                    'message' => __('locale.contacts.optin_keyword_successfully_deleted'),
            ]);
        }

        return response()->json([
                'status'  => 'error',
                'message' => __('locale.contacts.keyword_info_not_found'),
        ]);
    }

    /**
     * delete opt out keyword
     *
     * @param  ContactGroups  $contact
     * @param  Request  $request
     *
     * @return JsonResponse
     */
    public function deleteOptOutKeyword(ContactGroups $contact, Request $request): JsonResponse
    {

        if (config('app.stage') == 'demo') {
            return response()->json([
                    'status'  => 'error',
                    'message' => 'Sorry! This option is not available in demo mode',
            ]);
        }

        $keyword_id     = $request->id;
        $optout_keyword = ContactGroupsOptoutKeywords::where('contact_group', $contact->id)->where('uid', $keyword_id)->delete();
        if ($optout_keyword) {
            return response()->json([
                    'status'  => 'success',
                    'message' => __('locale.contacts.optout_keyword_successfully_deleted'),
            ]);
        }

        return response()->json([
                'status'  => 'error',
                'message' => __('locale.contacts.keyword_info_not_found'),
        ]);
    }

    /**
     * @return Generator
     */

    public function contactGroupsGenerator(): Generator
    {
        foreach (ContactGroups::where('customer_id', Auth::user()->id)->cursor() as $contactGroup) {
            yield $contactGroup;
        }
    }

    /**
     * @return RedirectResponse|BinaryFileResponse
     * @throws AuthorizationException
     * @throws IOException
     * @throws InvalidArgumentException
     * @throws UnsupportedTypeException
     * @throws WriterNotOpenedException
     */
    public function export(): BinaryFileResponse|RedirectResponse
    {

        if (config('app.stage') == 'demo') {
            return redirect()->route('customer.contacts.index')->with([
                    'status'  => 'error',
                    'message' => 'Sorry! This option is not available in demo mode',
            ]);
        }

        $this->authorize('view_contact');

        $file_name = (new FastExcel($this->contactGroupsGenerator()))->export(storage_path('ContactGroups_'.time().'.xlsx'));

        return response()->download($file_name);
    }

}

© 2025 UnknownSec
afwwrfwafr45458465
Password