<?php

namespace App\Http\Controllers\Customer;

use App\Http\Controllers\Controller;
use App\Jobs\CampaignCreateJob;
use App\Models\Campaign;
use App\Models\Contact;
use App\Models\ContactGroup;
use App\Models\Exception;
use App\Models\Group;
use App\Models\Customer;
use App\Models\Message;
use App\Models\Number;
use App\Models\SmsQueue;
use App\Models\SmsTemplate;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Log;
use Maatwebsite\Excel\Facades\Excel;
use App\Imports\DuplicateChecks;
use App\Export\DuplicateInvalidExport;
use App\Imports\CampaignContactsImport;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
class CampaignController extends Controller
{
    public function index()
    {

        return view('customer.campaign.index');
    }

    public function report(Request $request)
    {
        $customer = auth('customer')->user();
        if ($customer->type == 'staff') {
            $customer = $customer->staff;
        }

        if ($request->campaign_id)
            $campaign = $customer->campaings()->where('id', $request->campaign_id)->firstOrFail();
        $messageLogs = $customer->message_logs()->select(['from', 'to', 'body', 'response_code', 'updated_at']);

        if ($request->campaign_id) {
            $messageLogs = $messageLogs->where('campaign_id', $campaign->id);
        }
        if ($request->response_code) {
            $messageLogs = $messageLogs->where('response_code', $request->response_code);
        }
        if ($request->campaign_id) {
            $data['reports'] = $messageLogs->simplePaginate(20);
        } else {
            $data['reports'] = '';
        }
        $data['campaigns'] = $customer->campaings;
        $data['requestData'] = $request->only('campaign_id', 'response_code');
        return view('customer.campaign.report', $data);
    }

    public function getAll()
    {
        $customer = auth('customer')->user();
        if ($customer->type == 'staff') {
            $customer = $customer->staff;
        }

        $campaings = $customer->campaings()->orderByDesc('id')->select(['id', 'title', 'start_date', 'end_date', 'start_time', 'end_time', 'status', 'import_fail_message']);
        return datatables()->of($campaings)
            ->addColumn('title', function ($q) {
                $sent_sms = $q->sms_queue()->where('schedule_completed', 'yes')->count();
                return $q->title . '(' . $sent_sms . '/' . count($q->sms_queue) . ')';
            })
            ->addColumn('start_date', function ($q) {
                return $q->start_date;
            })
            ->addColumn('end_date', function ($q) {
                return $q->end_date;
            })
            ->addColumn('status', function ($q) {
                $endDate = Carbon::parse($q->end_date->toDateString() . ' ' . $q->end_time);
                $timeDiff = $endDate->diffInMinutes(now(), false);
                if ($timeDiff > 0) {
                    $complete_smsqueue = $q->sms_queue()->where('schedule_completed', 'yes')->count();
                    $smsqueue = $q->sms_queue()->count();
                    if ($complete_smsqueue == $smsqueue) {
                        return ' <button type="button"  class="btn light btn-sm btn-primary">Completed</button>';
                    } else {
                        return ' <button type="button" class="btn light btn-sm btn-warning">Incompleted</button>';
                    }
                }

                if ($q->import_fail_message) {
                    return ' <button type="button" class="btn light btn-sm btn-danger">Import Failed</button> <br>' . $q->import_fail_message;
                }

                if ($q->status == 'running') {
                    return '  <button type="button" class="btn light btn-sm btn-success dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
                                                Running
                               </button>
                                <div class="dropdown-menu" x-placement="bottom-start" style="position: absolute; will-change: transform; top: 0px; left: 0px; transform: translate3d(0px, 38px, 0px);">
                                     <button data-message="Are you sure, you want to change this campaign status?" data-action=' . route('customer.campaign.status', ['id' => $q->id, 'status' => 'paused']) . '
                                        data-input={"_method":"post"} data-toggle="modal" data-target="#modal-confirm" class="dropdown-item">
                                                    Pause
                                     </button>
                                </div>';
                } elseif ($q->status == 'failed') {
                    return '  <button type="button" class="btn light btn-sm btn-danger">Failed</button> <br>' . $q->import_fail_message;
                } elseif ($q->status == 'importing') {
                    return "<span> <i class=\"fas fa-spinner fa-pulse\"></i> importing</span>";
                } else {
                    return '<button type="button" class="btn light btn-sm btn-warning dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
                                                Pause
                               </button>
                                <div class="dropdown-menu" x-placement="bottom-start" style="position: absolute; will-change: transform; top: 0px; left: 0px; transform: translate3d(0px, 38px, 0px);">
                                     <button data-message="Are you sure, you want to change this campaign status?" data-action=' . route('customer.campaign.status', ['id' => $q->id, 'status' => 'running']) . '
                                        data-input={"_method":"post"} data-toggle="modal" data-target="#modal-confirm" class="dropdown-item">
                                                    Running
                                     </button>
                                </div>';
                }
            })->addColumn('action', function ($q) {
                return '<a href="' . route('customer.campaign.statistic', [$q->id]) . '" target="_blank" class="btn light btn-sm btn-info mr-2">Statistic </a>' . '<button class="btn btn-sm btn-danger" data-message="Are you sure, you want to delete this campaign? <br> <br> <small>N.B: This will delete all messages including sent and queue related to this campaign.</small>"
                                        data-action=' . route('customer.campaign.destroy', [$q]) . '
                                        data-input={"_method":"delete"}
                                        data-toggle="modal" data-target="#modal-confirm" data-toggle="tooltip" data-placement="top" title="Delete"><i class="fas fa-trash"></i></button>';
            })->rawColumns(['title', 'action', 'status'])->toJson();
    }


    public function create()
    {
        $customer = auth('customer')->user();
        if ($customer->type == 'staff') {
            $customer = $customer->staff;
        }
        $current_plan = $customer->currentPlan();
        if (!$current_plan){
            return back()->withErrors(['failed'=>'Agency doesn\'t have any plan right now']);
        }
        $data['templates'] = SmsTemplate::where('customer_id', $customer->id)->where('status', 'active')->get();
        $data['groups'] = $customer->groups()->withCount('contacts')->get();
        // $groups =$customer->groups()->withCount('contacts')->get();
        // foreach ($groups as $key => $group) {
        // dd($group->contact);
        // }
        $data['users_from_devices'] = $customer->activeDevices()->where('device_type','device')->get();
        $data['users_from_wadevices'] = $customer->activeDevices()->where('device_type','whatsapp')->get();
        $data['plain_sms']=$current_plan->plain_sms?intval($current_plan->plain_sms, '0'):1;;
        return view('customer.campaign.create', $data);
    }

    public function getTemplate(Request $request)
    {

        $customer = auth('customer')->user();
        if ($customer->type == 'staff') {
            $customer = $customer->staff;
        }

        $template = SmsTemplate::where('id', $request->template_id)->where('customer_id', $customer->id)->first();

        return response()->json(['status' => 'success', 'data' => $template->body]);
    }

    public function store(Request $request)
    {
        // if($request->schedule == 'on'){
            if($request->start_date){
            $schedule = explode("T",$request->start_date);
            $start_date = $schedule[0];
            $start_time = $schedule[1];
            $end_date = $schedule[0];
            $endadd_time = $start_time;
            $end_time = date('H:i:s', strtotime($endadd_time) + 5);
          }else{
            $start_date = now()->format('Y-m-d');
            $start_time = now()->format('H:i:s');
            $end_date = now()->format('Y-m-d');
            $end_time = now()->addSeconds(5)->format('H:i:s');
          }
        if (!isset($request->regenerate)) {
            $request->validate([
                'title' => 'required',
                'template_body' => 'required',
                'from_devices' => 'required|array', // a|x:y:z => a=DeviceID, x=SimSlotIndex, y=SubscriberId, z=SimDisplayName
            ]);
        }
        $all_number = '';
        $numbers = [];
        $totalTo = [];
        $totalSmsAmount = 0;
        if(!$request->regenerate) {
            $to=[];
        }
        if (isset($request->regenerate) && $request->customer_id) {
            $customer = Customer::findOrFail($request->customer_id);
        } else {
            $customer = auth('customer')->user();
        }
        if ($request->recipient_type === 'group') {
            $contact_groups = ContactGroup::whereIn('group_id', $request->group_id)->with('contact')->get();
            if ($contact_groups) {
                foreach ($contact_groups as $contact) {
                    $numbers[] = $contact->contact->number;
                }
            }
            $all_number = implode(",", array_unique($numbers));
        }
         elseif ($request->recipient_type === 'paste_number') {
            $request_paste_number = preg_replace('/\s+/', ',', str_replace(array("\r\n", "\r", "\n"), ' ', trim($request->paste_numbers)));
            $recipient_numbers = explode(',', $request_paste_number);
            $recipient_numbers = array_unique($recipient_numbers);
            $insertContact = [];
            foreach ($recipient_numbers as $recipient_number) {
                if ($recipient_number) {
                    $number_code = $recipient_number;
                    $number_without_code = $recipient_number;
                    $preContact = Contact::where([
                        'customer_id' => auth('customer')->user()->id,
                        // 'contact_dial_code' => $number_code,
                        'number' => $number_without_code
                    ])->first();

                    if (!$preContact) {
                        $numbers[] = $number_without_code;
                        $totalSmsAmount = $totalSmsAmount  + 1;

                        $insertContact[] = [
                            'customer_id' => auth('customer')->user()->id,
                            'contact_dial_code' => $number_code,
                            'number' => $number_without_code
                        ];
                    } else {
                        $numbers[] = $number_without_code;
                    }
                }
            }
            if (count($numbers) <= 0) {
                return redirect()->back()->withErrors(['failed' => 'Enter at last one contact number with reference format']);
            }

            if ($insertContact) {
                $customer->contacts()->createMany($insertContact);
            }
            $all_number = implode(",", array_unique($numbers));
        }
        $totalNumber = $all_number;

        $selectedDeviceIds = [];
        foreach ($request->from_devices as $item) {
            $deviceInfo = explode("|", $item);
            $selectedDeviceIds[] = $deviceInfo[0];
        }
        if ($customer->type == 'staff') {
            $customer = $customer->staff;
        }

        $devices = $customer->activeDevices($selectedDeviceIds)->get();
        if ($devices->isEmpty()) {
            return back()->with('fail', 'Device has been removed or inactive');
        }
        $deviceUniqueIds = $devices->pluck('device_unique_id', 'id');
        if($request->recipient_type !='import_xls') {
            $totalTo = array_map('trim', array_unique(preg_split('/,/', $totalNumber, -1, PREG_SPLIT_NO_EMPTY)));
            $onException = Exception::where('customer_id', auth('customer')->id())->whereIn('number', $totalTo)->pluck('number')->toArray();
            $to = array_diff($totalTo, $onException);
        }
        $current_plan = $customer->currentPlan();
        if (!$current_plan)
            return back()->with('fail', 'Customer doesn\'t have any plan right now');

        $deviceIds = $devices->pluck('id')->toArray();
        if (!$request->campaign_id) {
            $campaign = new Campaign();
            $campaign->title = $request->title;
            $campaign->device_ids = json_encode($deviceIds);
            $campaign->customer_id = $customer->id;
            $campaign->from_devices = json_encode($devices->pluck('device_unique_id')->toArray());
            $campaign->to_number = json_encode($to);
            $campaign->start_date = $start_date ?? '';
            $campaign->end_date = $end_date ?? '';
            $campaign->start_time = $start_time ?? '';
            $campaign->end_time = $end_time ?? '';
            $campaign->template_id = $request->template_id;
            $campaign->message_body = json_encode($request->template_body);
            $campaign->message_send_rate = $request->send_speed;
            $campaign->status = 'importing';
            $campaign->sim_info = json_encode($request->from_devices); // a|x:y:z
            $campaign->save();
        }else{
            $campaign = Campaign::findOrFail($request->campaign_id);
            $campaign->to_number = json_encode($to);
            $campaign->status = 'running';
            $campaign->save();

            $request['start_date'] = $campaign->start_date;
            $request['end_date'] = $campaign->end_date;
            $request['start_time'] = $campaign->start_time;
            $request['end_time'] = $campaign->end_time;
        }
        $from = $deviceIds;

        // randomly assigning a from device to a TO number
        $totalToNumbersCount = 0;
        $totalFromNumbersCount = count($request->from_devices);
        $generatedToNumbers = [];
        $array = (array)$request->from_devices;
        $lastKey = end($array);
        for ($i = 0; $i < count($to); $i += count($request->from_devices)) {
            for ($j = 0; $j < count($request->from_devices); $j++) {
                if (isset($to[$i + $j])) {
                    $generatedToNumbers[$request->from_devices[$j]][] = trim($to[$i + $j]);
                    $totalToNumbersCount++;
                }
            }
        }
        if ($request->recipient_type && $request->recipient_type == 'import_xls') {
            $importContact = new Group();
            $importContact->customer_id = $customer->id;
            $importContact->name = $request->title;
            $importContact->save();
            if ($request->hasFile('import_xls')) {
                $data = $request->file('import_xls');
                $fileName = $importContact->id . '.' . $data->getClientOriginalExtension();
                $data->move(public_path() . '/uploads', $fileName);
                $file_url = public_path() . '/uploads/' . $fileName;
                try {

                    /*Start*/
                    $startDate = (new Carbon($request->start_date))->subDay();
                    $endDate = new Carbon($request->end_date);
                    $startTime = new Carbon($request->start_time);
                    $endTime = new Carbon($request->end_time);
                    $difference_time = $startTime->diffInSeconds($endTime);
                    $difference_date = $startDate->diffInDays($endDate);
                    $total_minute = $difference_time * $difference_date;
                    $send_speed = floor($total_minute / 2);
                    //      $send_speed = floor($total_minute / $totalToNumbersCount);
                    /*End*/
                    Excel::import(new CampaignContactsImport($customer, $campaign->id, $importContact->id, $from, $request->template_body, $request->start_date, $request->end_date, $request->start_time, $request->end_time), $file_url);
                } catch (\Exception $ex) {
                    if (isset($ex->validator)) {
                        return redirect()->back()->withErrors($ex->validator->errors());
                    } else {
                        return redirect()->back()->withErrors(['msg' => $ex->getMessage()]);
                    }
                }
            }
        } else {
            foreach ($generatedToNumbers as $key => $toNumbers) {

                $deviceInfo = explode("|", $key);
                if (!empty($deviceInfo[1]) && is_string($deviceInfo[1])) {
                    $subscriberParts = explode(":", $deviceInfo[1]);
                    $subscriberId = isset($subscriberParts[1]) ? $subscriberParts[1] : '';
                } else {
                    $subscriberId = '';
                }
                /*Start*/
                $startDate = (new Carbon($request->start_date))->subDay();
                $endDate = new Carbon($request->end_date);
                $startTime = new Carbon($request->start_time);
                $endTime = new Carbon($request->end_time);
                $difference_time = $startTime->diffInSeconds($endTime);
                $difference_date = $startDate->diffInDays($endDate);
                $total_minute = $difference_time * $difference_date;
                $send_speed = floor($total_minute / $totalToNumbersCount);
                /*End*/

                //create new message
                $newMessage = new Message();
                $newMessage->customer_id = $customer->id;
                $newMessage->body =  json_encode($request->template_body);
                $newMessage->numbers = json_encode(['from' => $deviceInfo[0], 'to' => $toNumbers, 'device_unique_id' => $deviceUniqueIds[$deviceInfo[0]], 'subscriber_id' => $subscriberId]);
                $newMessage->campaign_id = $campaign->id;
                $newMessage->type = 'sent';
                $newMessage->read = 'no';
                $newMessage->save();
                CampaignCreateJob::dispatch($key, $toNumbers, $campaign, $newMessage, $totalToNumbersCount, $totalFromNumbersCount, $difference_date, $startDate, $startTime, $send_speed, $customer, $lastKey);
            }
        }

        return redirect()->route('customer.campaign.index')->with('success', trans('Campaign created successfully'));
    }


    public function destroy(Campaign $campaign)
    {
        if ($campaign->sms_queue) {
            $campaign->sms_queue()->delete();
        }
        if ($campaign->messages) {
            $campaign->messages()->delete();
        }
        $campaign->delete();

        return redirect()->route('customer.campaign.index')->with('success', 'Congratulations ! Campaign successfully deleted');
    }

    public function status(Request $request)
    {
        $request->validate([
            'status' => 'required|in:running,paused',
        ]);
        $customer = auth('customer')->user();
        if ($customer->type == 'staff') {
            $customer = $customer->staff;
        }

        $campaign = Campaign::where('customer_id', $customer->id)->where('id', $request->id)->firstOrFail();
        $campaign->status = $request->status;
        $campaign->save();

        SmsQueue::where('campaign_id', $campaign->id)->where('schedule_completed', 'no')->where('status', $request->status == 'paused' ? 'running' : 'paused')->update(['status' => $request->status]);

        return redirect()->route('customer.campaign.index')->with('success', 'Congratulations ! Campaign status updated');
    }
    public function statistic($id)
    {
        $customer = auth('customer')->user();
        if ($customer->type == 'staff') {
            $customer = $customer->staff;
        }
        $campaign = $customer->campaings()->where('id', $id)->firstOrFail();
        $data['messageRunningLogs'] = $customer->sms_queues()->where('campaign_id', $campaign->id)->orderBy('schedule_datetime')->where('schedule_completed', 'no')->where('status', 'running')->paginate(20, ['*'], 'running');
        $data['messagePausedLogs'] = $customer->sms_queues()->where('campaign_id', $campaign->id)->orderBy('schedule_datetime')->where('status', 'paused')->paginate(20, ['*'], 'paused');
        $data['messageFailedLogs'] = $customer->sms_queues()->where('campaign_id', $campaign->id)->orderBy('schedule_datetime')->where('schedule_completed', 'yes')->where('status', 'failed')->paginate(20, ['*'], 'failed');
        $data['messageDeliveredLogs'] = $customer->sms_queues()->where('campaign_id', $campaign->id)->orderBy('schedule_datetime')->where('status', '!=', 'failed')->where('schedule_completed', 'yes')->whereColumn('created_at', '<', 'updated_at')->whereNull('response_code')->paginate(20, ['*'], 'delivered');
        $data['total_contact']= $customer->sms_queues()->where('campaign_id', $campaign->id)->orderBy('schedule_datetime')->where('schedule_completed', 'no')->where('status', 'running')->count();
        $data['totald_delivered'] = $customer->sms_queues()->where('campaign_id', $campaign->id)->orderBy('schedule_datetime')->where('status', '!=', 'failed')->where('schedule_completed', 'yes')->whereColumn('created_at', '<', 'updated_at')->whereNull('response_code')->count();
        $data['total_falied'] = $customer->sms_queues()->where('campaign_id', $campaign->id)->orderBy('schedule_datetime')->where('schedule_completed', 'yes')->where('status', 'failed')->count();
        return view('customer.campaign.statistic', $data);
    }
    public function checkDuplicates(Request $request){
        $result=[];
        if($request->isMethod('post') && $request->hasFile('import_xls')){
            $randomId=Str::random(16);
            $import=new DuplicateChecks();
            $datas = Excel::toCollection($import, $request->file('import_xls'))[0];
            $invalidNumbers=$datas->filter(function ($value,$key) {
                return strlen($value['number']) < 10 || strlen($value['number'])>12;
            });

            $invalidNumbers=$invalidNumbers->pluck('number')->all();
            $duplicates=$datas->duplicates('number');
            $duplicatesArray=$duplicates->merge($invalidNumbers);
            $total_validNumbers = $datas->count() - $duplicatesArray->count();
            $result['count']=$duplicatesArray->count();
            $result['file']=$randomId;
            $result['total_validNumbers'] = $total_validNumbers;
            $result['total_Numbers'] = $datas->count();
            Storage::put("duplicates/".$randomId.".dp",json_encode($duplicatesArray));
        }else if($request->id && strlen($request->id)==16){
            if(Storage::exists("duplicates/".$request->id.".dp")){
                return new DuplicateInvalidExport($request->id);
            }else{
                return redirect()->back()->withErrors(['msg'=>'File does not exist. Please reupload.']);
            }

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