<?php

namespace App\Tools;

use App\Jobs\SendBlastAlert;
use App\Jobs\SendBlastEmailAlert;
use App\Log;
use App\Network;
use App\User;
use App\UserNetwork;
use Carbon\Carbon;
use GuzzleHttp\Client;
use GuzzleHttp\Promise;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;

class SmsTools {


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

    public static function hash_currency_amount($message){
        $stanbicUser = session()->get('stanbic_user');
        $user = auth()->user();
        
        // Check if hashing should be applied for stanbicgh or npontuuser
        $shouldHash = false;
        
        if(!empty($stanbicUser) && $user->username=='stanbicgh' && $stanbicUser->username != 'stanbicgh' && $stanbicUser->username != 'NP01870') {
            $shouldHash = true;
        } elseif (in_array(strtolower($user->username), ['npontuuser', 'stanbicgh'])){
            $shouldHash = true;
        }
        
        if ($shouldHash) {
            $words = explode(' ', $message);
            $new_words = [];
            $helpline_numbers = ['233302815789', '23302815789', '233', '302', '815', '789'];

            for ($i = 0; $i < count($words); $i++) {
                $word = trim($words[$i]);

                // Hash OTP: numeric word in OTP/password context
                if (is_numeric($word) && self::is_otp_or_password_context($words, $i)) {
                    if (!in_array($word, $helpline_numbers)) {
                        $new_words[] = str_repeat('#', strlen($word));
                    } else {
                        $new_words[] = $word;
                    }
                }
                // Hash password: word after "Password is" (can be alphanumeric like rs20061590)
                elseif (self::is_password_value_context($words, $i) && $word !== '' && !in_array($word, $helpline_numbers)) {
                    $new_words[] = preg_replace('/[a-zA-Z0-9]/', '#', $word);
                }
                else {
                    $new_words[] = $word;
                }
            }

            return implode(' ', $new_words);
        }

        return $message;
    }

    /**
     * Check if the word at index $i is in OTP or password/PIN context (previous word indicates it).
     * Only then should we hash it.
     *
     * @param array $words
     * @param int   $i
     * @return bool
     */
    private static function is_otp_or_password_context(array $words, $i)
    {
        if ($i < 1) {
            return false;
        }
        $prev = trim($words[$i - 1]);
        $prev_lower = strtolower($prev);
        $prev_upper = strtoupper($prev);

        // OTP: 697125 or OTP 697125
        if (strpos($prev_upper, 'OTP') !== false) {
            return true;
        }
        // PIN: 12345 or PIN 12345 or pin is
        if (strpos($prev_upper, 'PIN') !== false) {
            return true;
        }
        // password is 12345 (numeric part)
        if (strpos($prev_lower, 'password') !== false) {
            return true;
        }
        // "is" after "pin" or "password" or "otp" (e.g. "pin is 12345", "password is 12345")
        if ($prev_lower === 'is' && $i >= 2) {
            $prev2 = strtolower(trim($words[$i - 2]));
            if (in_array($prev2, ['pin', 'password', 'otp'], true)) {
                return true;
            }
        }
        // "Your OTP for VUSER Login is 18180" - number after "is" when message contains "OTP"
        if ($prev_lower === 'is' && $i >= 2) {
            for ($j = 0; $j <= $i - 2; $j++) {
                if (strpos(strtolower(trim($words[$j])), 'otp') !== false) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * Check if the word at index $i is the password value (word right after "Password is").
     * Used to hash alphanumeric passwords like "rs20061590".
     *
     * @param array $words
     * @param int   $i
     * @return bool
     */
    private static function is_password_value_context(array $words, $i)
    {
        if ($i < 2) {
            return false;
        }
        $prev = strtolower(trim($words[$i - 1]));
        $prev2 = strtolower(trim($words[$i - 2]));
        return ($prev === 'is' && $prev2 === 'password');
    }

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

    public static function get_string($string, $start, $end) {
        $string = " " . $string;
        $pos = strpos($string, $start);
        if ($pos == 0)
            return "";
        $pos += strlen($start);
        $len = strpos($string, $end, $pos) - $pos;
        return substr($string, $pos, $len);
    }

    public static function round_currency($value) {
        if(empty($value)) {
            return 0;
        }
        else if($value/1000000.0 >=1) {
            return round($value/1000000.0, 2).'M';
        }
//        else if($value/100000.0 >=1) {
//            return round($value/1000.0, 1).'K';
//        }
        else {
            return round($value, 3, PHP_ROUND_HALF_DOWN);
        }
    }

    public static function get_esme_credit(User $user) {
        if(!empty($user) && $user->role->name === 'esme') {
            $username = $user->username;
            $data = DB::connection('kannel')->select("select * from credits where username='$username'");
            if(!empty($data)) {
                return (double) $data[0]->balance;
            } else {
                return 0;
            }
        }
        return false;
    }

    public static function sync_esme_credit(User $user) {
        if(!empty($user) && $user->role->name === 'esme') {
            $username = $user->username;
            $data = DB::connection('kannel')->select("select * from credits where username=?", [$username]);
            if(!empty($data)) {
                $bal = (double) $data[0]->balance;
                $new_bal = $bal * (!empty($user->credit) ? $user->credit->price: 0);
                if(!empty($user->credit)) {
                    $user->credit->new_bal = $new_bal;
                    $user->credit->save();
                }
            }
        }
    }

    public static function get_msisdn_network(User $user, $msisdn) {
        $msisdn = self::format_gh_number($msisdn);
        foreach (Network::with('country')->get() as $network) {
            $prefixes = explode(',', $network->prefix);
            foreach ($prefixes as $prefix) {
                $prefix = trim($prefix);
                if(starts_with($msisdn, $prefix)) {

                    $usr_price = UserNetwork::where([
                        ['user_id', '=', $user->id],
                        ['network_id', '=', $network->id],
                        ['country_id', '=', $network->country_id]
                    ])->first();
                    return [
                        'network_id' => $network->id,
                        'network' => $network->nice_name,
                        'country_id' => $network->country_id,
                        'country' => $network->country->name,
                        'sms_price' => empty($usr_price) ? $network->sms_price : $usr_price->sms_price
                    ];
                }
            }
        }
        return [
            'network_id' => null,
            'network' => null,
            'country_id' => null,
            'country' => null,
            'sms_price' => $user->credit->price
        ];
    }

    public static function deduct_esme_credit(User $user, $amount) {
        if(!empty($user) && $user->role->name === 'esme') {
            $username = $user->username;
            $amount = (double)$amount;
            $data = DB::connection('kannel')->select("select * from credits where username=?", [$username]);
            if(!empty($data)) {
                $bal = (double) $data[0]->balance;
                $new_bal = $bal * $user->credit->price - $amount;
                //$sms_qty = (int)($amount / $user->credit->price);
                //$kannel_new_bal = $bal - $sms_qty;
                //DB::connection('kannel')->update("update credits set balance='$kannel_new_bal' where username=?", [$username]);
                $user->credit()->update([
                    'new_bal' => $new_bal,
                    'credit_used' => $user->credit->credit_used + $amount
                ]);
            }
        }
    }

    public static function sendBlastAlert(User $user, $totalRecipient, $type='sms') {
        if($type == 'sms')
            SendBlastAlert::dispatch($user, $totalRecipient)
                ->onConnection('redis')
                ->onQueue('notification');
        else
            SendBlastEmailAlert::dispatch($user, $totalRecipient)
                ->onConnection('redis')
                ->onQueue('notification');;
    }

    public static function string_incl($x, $r, $str) {
        $out = "";
        $temp = substr($str, $x);
        $out = substr_replace($str, "$r", $x);
        $out .= $temp;
        return $out;
    }

    public static function string_date($submit_date) {
        $date1 = self::string_incl('2', '-', $submit_date);
        $date2 = self::string_incl('5', '-', $date1);
        $date3 = self::string_incl('8', ' ', $date2);
        $date4 = self::string_incl('11', ':', $date3);
        $timestamp = self::string_incl('15', '', $date4);
        return $timestamp;
    }

    /**
     * @param $year
     * @param $month
     * @param $week
     * @return static
     * @throws \Exception
     */
    public static function get_end_of_week($year, $month, $week)
    {
        $week_number = (int)$week;
        if($week_number <1 || $week_number>5) {
            throw new \Exception('Invalid week number');
        }
        $max_day = $week_number * 7;
        if($max_day > 30) {
            $date = Carbon::create($year, $month, 30, 23, 59, 59);
            if($date->copy()->addDay()->month == $date->month)
                $date = $date->addDay();
        } else {
            $date = Carbon::create($year, $month, $max_day, 23, 59, 59);

            while (!$date->isSunday()) {
                $date = $date->addDays(-1);
            }
        }
        return $date;
    }

    public static function get_start_of_week(Carbon $endDate)
    {
        $date = $endDate->copy();
        if($date->day -6 < 1) {
            $date->day = 1;
        } else {
            while (!$date->isMonday()) {
                $date = $date->addDays(-1);
            }
        }
        $date->setTime(0, 0, 0);
        return $date;
    }

    public static function generate_new_sms_id() {
        return uniqid('DWO.', true);
    }

    public static function send_sms($msisdn, $sender, $msgs, $id) {
        $msgs = urlencode(rawurldecode($msgs));
        $msgs = str_replace("%5Cr", '%20', $msgs);
        $msgs = str_replace("%5Cn", '%0A', $msgs);
        $msgs = str_replace("%5C", '%20', $msgs);
        $dlr = "https://deywuro.com/api/dlr-receiver-route?source=%P&destination=%p&SVC=%n&msgID=%F&msg=%a&msglen=%L&timestamp=%t&status=%d&smsc=%i&smsid=%I&dlrv=%d&MDS=%D&DLRS=%A&osms=%b&mid=" . $id;
        $from = urlencode($sender);
        $dlrEncode = urlencode($dlr);
        $url = "http://esme.npontutechnologies.com:13014/cgi-bin/sendsms?username=mtnnpontu3&password=O14ns0&to=" . $msisdn . "&from=" . $from . "&text=" . $msgs . "&dlr-mask=31&dlr-url=" . $dlrEncode;
        return file_get_contents($url);
    }

    public static function msisdn_prep($number) {
        if(isset($number[0]) && isset($number[1])) {
            $firstletter = $number[0];
            $secondletter = $number[1];
            $numcode = $firstletter . $secondletter;
            if ($firstletter == '+') {
                $number = substr($number, 1);
            } elseif ($numcode == 00) {
                $number = substr($number, 2);
            } elseif ($firstletter == 0 && $secondletter !== 0) {
                $remove = substr($number, 1);
                $number = '233' . $remove;
            }
        }
        return $number;

    }

    public static function which_network($msisdn) {
        $no = substr($msisdn, 3, 2);

        if ($no == '24' || $no == '54' || $no = '55') {
            $net = 'MTN';
        } elseif ($no == '20' || $no == '50') {
            $net = 'VODAFONE';
        } elseif ($no == '27' || $no == '57') {
            $net = 'TIGO';
        } elseif ($no == '26') {
            $net = 'AIRTEL';
        } elseif ($no == '23') {
            $net = 'GLO';
        } elseif ($no == '28') {
            $net = 'EXPRESSO';
        } else {
            $net = 'UNKNOWN';
        }

        return $net;
    }


    public static function checkCode($msisdn) {
        if (substr($msisdn, 0, 1) == '1') {
            $code = substr($msisdn, 0, 1);
            $ccLength = strlen($code);
        } elseif (substr($msisdn, 0, 1) == '9') {
            $code = substr($msisdn, 0, 1);
            $ccLength = strlen($code);
        } elseif (substr($msisdn, 0, 2) == '44') {
            $code = substr($msisdn, 0, 2);
            $ccLength = strlen($code);
        } elseif (substr($msisdn, 0, 2) == '27') {
            $code = substr($msisdn, 0, 2);
            $ccLength = strlen($code);
        } else {
            $code = substr($msisdn, 0, 3);
            $ccLength = strlen($code);
        }

        if ($code == '246') {
            $msisdnLeng = 6;
        } elseif ($code == '238' || $code == '241' || $code == '239' || $code == '220') {
            $msisdnLeng = 7;
        } elseif ($code == '229' || $code == '257' || $code == '237' || $code == '236' || $code == '235' || $code == '225' || $code == '243' || $code == '223' || $code == '227' || $code == '228' || $code == '226') {
            $msisdnLeng = 8;
        } elseif ($code == '34' || $code == '32' || $code == '41' || $code == '242' || $code == '240' || $code == '254' || $code == '265' || $code == '250' || $code == '231' || $code == '221' || $code == '232' || $code == '211' || $code == '255' || $code == '256' || $code == '260' || $code == '233') {
            $msisdnLeng = 9;
        } elseif    ($code == '1' || $code == '44' || $code == '234' || $code == '218' || $code == '263' || $code == '39' || $code == '91') {
            $msisdnLeng = 10;
        } else {
            $msisdnLeng = 10;
        }

        $standard_len = $ccLength + $msisdnLeng;
        $new_len = strlen($msisdn);
        return $standard_len === $new_len;
    }

    public static function no_pages($no_chars) {

        if ($no_chars <= 160) {
            $no_pages = 1;
        }
        if ($no_chars > 160 && $no_chars <= 306) {
            $no_pages = 2;
        }
        if ($no_chars > 306 && $no_chars <= 459) {
            $no_pages = 3;
        }
        if ($no_chars > 459 && $no_chars <= 621) {
            $no_pages = 4;
        }

        if ($no_chars > 621) {
            $no_pages = 5;
        }

        if ($no_chars > 766) {
            $no_pages = 6;
        }
        if ($no_chars > 919) {
            $no_pages = 7;
        }
        if ($no_chars > 1072) {
            $no_pages = 8;
        }

        return $no_pages;
    }

    public static function send_internal_sms($msisdn, $msgs)
    {
        if (!App::environment('local')) {
            if (!empty(trim($msisdn))) {
                $msisdn = self::format_gh_number($msisdn);
                $sender = 'Deywuro';
                $msgs = str_replace("%5Cr", '%20', $msgs);
                $msgs = str_replace("%5Cn", '%0A', $msgs);
                $msgs = str_replace("%5C", '%20', $msgs);
                $client = new Client();
                $response = $client->request('GET', 'http://5.9.61.79:13013/cgi-bin/sendsms', [
                    'query' => [
                        'username' => 'mtnnpontu3',
                        'password' => 'O14ns0',
                        'to' => $msisdn,
                        'from' => $sender,
                        'text' => $msgs,
                        'dlr-mask' => '31',
                        'dlr-url' => ''
                    ]
                ]);
                $response->getBody();
            }
        }
    }

}
