<?php
/**
 * Created by PhpStorm.
 * User: Alphonse Malan
 * Date: 05/12/2017
 * Time: 11:53 AM
 */

namespace App\Tools;


use App\Console\Commands\SpeedyPersoBulkSms;
use App\Jobs\SendLowBalanceAlertToClient;
use App\Jobs\SendLowBalanceAlertToSupport;
use App\UserJob;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\Log;
use Maatwebsite\Excel\Facades\Excel;

class CheckCredit
{
    private static $instance = null;

    private function __contruct() {

    }

    public static function getInstance() {
        if(empty(self::$instance))
            self::$instance = new CheckCredit();
        return self::$instance;
    }

    public function can_send_sms(UserJob &$job) {
        $error_level = error_reporting();
        error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
        if($job->type==='bulk') {
            return $this->can_send_simple_bulksms($job);
        } else if($job->type==='p_bulk') {
            return $this->can_send_personalised_bulksms($job);
        } else {
            return true;
        }
    }

    private function can_send_simple_bulksms(UserJob &$job) {
        $error_level = error_reporting();
        error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);

        $processed_msisdn = [];
        $dupplicated_msisdn = [];
        $price = 0.0;
        $user = $job->user;
        $credit = $user->credit;
        $remove_duplicate = $job->remove_duplicate;
        Log::debug("Checking credit for job ".$job->name+"...");
        Excel::load($job->file_path, function ($reader)
        use (&$processed_msisdn, &$dupplicated_msisdn, &$price, &$user, $remove_duplicate) {
            $sheet = $reader->getExcel()->getSheet(0);
            $highestRow = $sheet->getHighestRow();
            $highestColumn = $sheet->getHighestColumn();
            for ($row = 1; $row <= $highestRow; $row++)
            {
                try {
                    $rowData = $sheet->rangeToArray('A' . $row . ':' . $highestColumn . $row, NULL, TRUE, FALSE);
                    $number = $rowData[0][0];
                    $msisdn = SmsTools::msisdn_prep(preg_replace('/\D/', '', $number));
                    $msisdn = trim($msisdn);
                    if(empty($msisdn)) continue;
                    if($remove_duplicate && in_array($msisdn, $processed_msisdn)) {
                        array_push($dupplicated_msisdn, $msisdn);
                        continue;
                    }
                    $network = SmsTools::get_msisdn_network($user, $msisdn);
                    $price += (float)$network['sms_price'];
                    array_push($processed_msisdn, $msisdn);
                } catch (\Exception $e) {
                    Log::error($e->getMessage());
                }
            }
        });

        $new_msg_text = preg_replace(array('/\r\n/'), array("\n"), $job->message);
        $no_pages = (int)SmsTools::no_pages(strlen($new_msg_text));
        $total_price = (double)($no_pages * $price);
        $recipients = count($processed_msisdn);
        $credit_available = (double)$credit->new_bal;
        $job->total_traffic = $recipients;
        $diff = $credit_available - $total_price;
        $low_credit = $diff<0.0;
        Log::debug("Total Msisdn: ".$recipients);
        Log::debug("Total Price: ".$total_price);
        Log::debug("Avail Bal: ".$credit_available);
        //check for low balance
        if($low_credit) {
            $this->send_low_credit_alert($user, $job, $diff);
        }
        $job->save();
        Log::debug("Done checking credit for job ".$job->name);
        return !$low_credit;
    }

    private function send_low_credit_alert(&$user, &$job, $diff) {
        $error_level = error_reporting();
        error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
        //change job status
        $job->status = 'low_balance';
        try {
            //send sms alert low credit
            $smsMsg = 'Hello ' . $user->username . ', your balance is low, you need an additional GHS ' . number_format(-1*$diff, 2) . ' to send your campaign "' . $job->name . '"';
            SmsTools::send_internal_sms($user->phone_number, $smsMsg);
            //send email alert low credit
            $job1 = new SendLowBalanceAlertToClient($user, -1 * $diff, $job);
            $job1->onConnection('redis');
            dispatch($job1);
            //alert support
            $job2 = new SendLowBalanceAlertToSupport($user, -1 * $diff, $job);
            $job2->onConnection('redis');
            dispatch($job2);
            //open ticket using Mel's api
            try {
                $client = new Client();
                $response = $client->request('GET', 'http://autoticketing.npontu.com/api/ticket', [
                    'query' => [
                        'app_id' => '2',
                        'description' => 'Client "' . $user->username . '" has low balance, the campaign "' . $job->name . '" requires topup before it can be send',
                        'subject' => 'Client has low balance on MTN MESSENGER',
                        'classification_id' => '2',
                        'severity_id' => '1'
                    ]
                ]);
                $body = $response->getBody();
                Log::debug((string)$body);
            } catch (\Exception $t) {
                Log::error($t->getMessage());
            }
        }catch (\Throwable $t) {
            Log::error($t->getMessage());
        }
    }

    private function can_send_personalised_bulksms(UserJob &$job) {
        $error_level = error_reporting();
        error_reporting(E_ALL & ~E_NOTICE & ~E_WARNING);
        $headers = [];
        $dupplicated_msisdn = [];
        $price = 0.0;
        $processed_msisdn = [];
        $user = $job->user;
        $credit = $user->credit;
        $msg = $job->message;
        $remove_duplicate = $job->remove_duplicate;
        Log::debug("Checking credit for job ".$job->name+"...");
            Excel::load($job->file_path, function ($reader)
            use (&$headers, &$processed_msisdn, &$dupplicated_msisdn, &$price, &$user, &$remove_duplicate, $msg) {
                $sheet = $reader->getExcel()->getSheet(0);
                $highestRow = $sheet->getHighestRow();
                $highestColumn = $sheet->getHighestColumn();
                $rowData = $sheet->rangeToArray('A' . 1 . ':' . $highestColumn . 1, NULL, TRUE, FALSE);
                $row = $rowData[0];
                foreach ($row as $header)
                    $headers[] = $header;

                //check for duplicated
                for ($row = 2; $row <= $highestRow; $row++)
                {
                    try {
                        //  Read a row of data into an array
                        $rowData = $sheet->rangeToArray('A' . $row . ':' . $highestColumn . $row,
                            NULL, TRUE, FALSE);
                        $number = $rowData[0][0];
                        $msisdn = SmsTools::msisdn_prep(preg_replace('/\D/', '', $number));
                        $msisdn = trim($msisdn);
                        if(empty($msisdn)) continue;
                        if($remove_duplicate && in_array($msisdn, $processed_msisdn)) {
                            array_push($dupplicated_msisdn, $msisdn);
                            continue;
                        }
                        $network = SmsTools::get_msisdn_network($user, $msisdn);

                        $tmpPrice = (float)$network['sms_price'];
                        $tmpMsg = SpeedyPersoBulkSms::update_msg($headers, $rowData[0], $msg);
                        $new_msg_text = preg_replace(array('/\r\n/'), array("\n"), $tmpMsg);
                        $no_chars = strlen($new_msg_text);
                        $no_pages = (int)SmsTools::no_pages($no_chars);
                        $price += ($tmpPrice * $no_pages);
                        array_push($processed_msisdn, $msisdn);
                    } catch (\Exception $e) {
                        Log::error($e->getMessage());
                    }
                }
            });

        $total_price = $price;
        $recipients = count($processed_msisdn);
        $credit_available = (double)$credit->new_bal;
        $job->total_traffic = $recipients;
        $diff = $credit_available - $total_price;
        $low_credit = $diff < 0.0;
        //check for low balance
        Log::debug("Total Msisdn: ".$recipients);
        Log::debug("Total Price: ".$total_price);
        Log::debug("Avail Bal: ".$credit_available);
        if($low_credit) {
            $this->send_low_credit_alert($user, $job, $diff);
        }
        $job->save();
        Log::debug("Done checking credit for job ".$job->name);
        return !$low_credit;
    }
}