<?php

namespace Mnv\Core;

use JsonException;
use Mnv\Core\Bot\Telegram;
use Mnv\Core\Bot\TelegramNotifications;
use Mnv\Core\Locale\I18N;
use Mnv\Core\Test\Log;
use Mnv\Models\Users\UserTypes;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

class Feedback
{
    private $charset;
    private $smtp_server;
    private $smtp_mail;
    private $smtp_user;
    private $smtp_pass;
    private $smtp_secure;
    private $smtp_port;
    private $smtp_debug;

    private $remoteIp;
    private $private_key;

    public $errors;
    public $message;
    public $success = [];

    private $type;
    private $captchaEnabled;
    private $allowCaptcha;

    protected $companyName;
    protected $recipient;

    private $telegramConfig;

    private $messenger;
    /**
     * Feedback constructor.
     */
    public function __construct()
    {

        $this->telegramConfig = TelegramNotifications::init()->config();
        $this->type = Config::getValue('mail_transport');

        $this->charset     = Config::getValue('charset');
        $this->smtp_debug  = Config::getValue('smtp_debug');
        $this->smtp_server = Config::getValue('smtp_server');
        $this->smtp_mail   = Config::getValue('smtp_mail');
        $this->smtp_user   = Config::getValue('smtp_user');
        $this->smtp_pass   = Config::getValue('smtp_pass');
        $this->smtp_secure = Config::getValue('smtp_secure');
        $this->smtp_port   = Config::getValue('smtp_port');

        $this->companyName =  Config::getValue('company_name');
        $this->recipient = Config::getValue('email');
        $this->remoteIp    = $_SERVER['REMOTE_ADDR'];

        if (Config::getValue('allow_recaptcha') === 1) {
            $this->private_key = Config::getValue('recaptcha_private_key');
        }

    }

    /**
     * получение параметра, включена капча или нет
     * @param $param
     */
    public function getCaptchaEnabled($param): void
    {
        $this->captchaEnabled = $param;
    }

    /**
     * @return mixed
     */
    public function setCaptchaEnabled()
    {
        return $this->captchaEnabled;
    }

    /**
     * тип капти
     * @param $param
     */
    public function getAllowCaptcha($param): void
    {
        $this->allowCaptcha = $param;
    }

    /**
     * @return mixed
     */
    public function setAllowCaptcha()
    {
        return $this->allowCaptcha;
    }

    /**
     * метод для проверки длины строки
     * @param $string
     * @param $minLength
     * @param $maxLength
     * @return bool
     */
    public function checkStringLength($string, $minLength, $maxLength): bool
    {
        $length = mb_strlen($string, Config::getValue('charset'));
        return !(($length < $minLength) || ($length > $maxLength));
    }

    /**
     * метод проверки имени (name)
     *
     * @param $name
     * @return bool
     */
    public function checkName($name): bool
    {
        if (!empty($name)) {
            if (!$this->checkStringLength($name, 2, 30)) {
                $this->errors = I18N::locale(
                    "* Поля имя содержит недопустимое количество символов!",
                    "* Maydon nomi belgilar nomaqbul sonini o'z ichiga oladi!",
                    "* The name field contains an invalid number of characters!");;
                $this->errors = 'Поля имя содержит недопустимое количество символов!';
                return false;
            }
        } else {
            $this->errors =  I18N::locale(
                "* Не допустимо оставлять поле имя пустым!",
                "* Maydon nomini bo'sh qoldirish joiz emas!",
                "* It is unacceptable to leave the name field empty!"
            );
            return false;
        }
        return true;
    }


    /**
     * проверка капча (reCaptcha:v3)
     *
     * @param $captcha
     * @return bool
     * @throws JsonException
     */
    public function captchaToken($captcha): bool
    {
        if (isset($captcha)) {
            $params = [
                'secret' => $this->private_key,
                'response' => $captcha,
                'remoteip' => $this->remoteIp
            ];
        } else {
            $this->errors = 'Captcha doesn\'t work well. Contact your administrator!';
        }

        $curl = curl_init('https://www.google.com/recaptcha/api/siteverify');
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $params);
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($curl, CURLOPT_HEADER, 0);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $response = curl_exec($curl);
        if (!empty($response)) {
            $decoded_response = json_decode($response, false, 512, JSON_THROW_ON_ERROR);
        }
        if ($decoded_response && $decoded_response->success && $decoded_response->score > 0) {
            //$success = $decoded_response->success;
            return true;
        }

        $this->message = I18N::locale("* Вы не прошли тест", "* Sinovdan o'tolmading.", "* You did not pass the test, I am a robot");
        $this->errors = "You did not pass the test";
    }

    /**
     * Анти бот
     * @param $bot_one
     * @param $bot_two
     * @param $bot_email
     * @return bool
     */
    public function antiBot($bot_one, $bot_two, $bot_email): bool
    {
        if (trim($bot_one) !== date('Y')){
            if (trim($bot_one) !== trim($bot_two)) {
                $this->message =  I18N::locale("Я робот! Подобрал капчу", "Men robotman! Oldi captcha", 'I am a robot! Picked up captcha');
                $this->errors = "I'm a robot! Picked up a captcha";
            } elseif (empty($bot_two)) {
                $this->message = I18N::locale("Ошибка: пустой ответ.", "Xato: bo'sh javob.", "Error: empty response.");
                $this->errors = "An empty answer";
            } else {
                $this->message = I18N::locale("Ошибка: неправильный ответ.", "Xato: noto'g'ri javob.", "Error: wrong answer.");
                $this->errors = "Wrong answer";
            }
        } elseif (!empty($bot_email)) {
            $this->errors = 'Bots go no!';
        } else {
            return true;
        }
    }

    /**
     * Отправка письма PHPMailer (smtp)
     *
     * @param string|null $user_email
     * @param string|null $user_name
     * @param $subject
     * @param $htmlBody
     * @param null $attachment
     * @return bool
     */
    public function send(?string  $user_email = null, ?string $user_name, $subject, $htmlBody, $attachment = null)
    {
        $mail = new PHPMailer(true);
        try {
            $mail->CharSet      = $this->charset;
            $mail->Encoding     = "base64";
            $mail->isSMTP();
            $mail->Timeout = 10;
            $mail->SMTPAutoTLS  = false;
            $mail->SMTPDebug    = $this->smtp_debug;
            $mail->Host         = $this->smtp_server;
            $mail->SMTPSecure   = $this->smtp_secure;
            $mail->Port         = $this->smtp_port;

            if ($mail->SMTPSecure === 'ssl') {
                $mail->SMTPOptions = array(
                    "ssl" => array(
                        "verify_peer" => false,
                        "verify_peer_name" => false
                    )
                );
            }

            if ($mail->SMTPSecure === 'tls') {
                $mail->SMTPOptions = array(
                    "tls" => array(
                        "verify_peer" => false,
                        "verify_peer_name" => false
                    )
                );
            }

            if ($this->smtp_user) {
                $mail->SMTPAuth = true;
                $mail->Username = $this->smtp_user;
                $mail->Password = $this->smtp_pass;
            }

            if ($this->smtp_mail) {
                $mail->From = $this->smtp_mail;
                $mail->Sender = $this->smtp_mail;
            }

            $mail->setFrom($this->smtp_user, $this->companyName);
            if (!empty($this->recipient)) {
                $mail->addAddress($this->recipient, $this->companyName);
            }

            if (!empty($user_email)) {
                $mail->addReplyTo($user_email, $user_name);
                $mail->addAddress($user_email, $this->companyName);
            }

            $managers = $this->managersReceiveEmails();
            if (!empty($managers)) {
                foreach ($managers as $manager) {
                    $mail->addBCC($manager->email, $this->companyName);
                    $mail->addAddress($manager->email, $this->companyName);
                }
            }

            if (!empty($attachment) ) {
                $mail->addAttachment($attachment['tmp_name'], $attachment['name']);
            }

            $mail->isHTML(true);
            $mail->Subject = $subject;
            $mail->Body    = $htmlBody;

            $mail->send();

            return true;

        } catch (Exception $e) {

            $this->message = "Message could not be sent";
            $this->errors = $mail->ErrorInfo;

            return false;
        }

    }

    private function managersReceiveEmails()
    {
        return connect('users')->select('email')->in('userType', [UserTypes::DEVELOPER, UserTypes::ADMIN])->where('receiveEmails', '=', 0)->where('email', '<>', '')->orderBy('userId', 'ASC')->getAll();
    }
    /**
     * Скрыть несколько симоволов в email
     * @param $email
     * @param int $minLength
     * @param int $maxLength
     * @param string $mask
     * @return string
     */
    public function maskEmail($email, $minLength = 3, $maxLength = 10, $mask = "***"): string
    {
        $atPos = strrpos($email, "@");
        $name = substr($email, 0, $atPos);
        $len = strlen($name);
        $domain = substr($email, $atPos);

        if (($len / 2) < $maxLength) $maxLength = ($len / 2);

        $shortenedEmail = (($len > $minLength) ? substr($name, 0, $maxLength) : "");
        return  "{$shortenedEmail}{$mask}{$domain}";
    }

    public function maskPhone($phone)
    {
        return substr_replace($phone,'****',4,13);
    }

    public function insertMail($feedback, $htmlBody): void
    {
        $mails = array_filter([
            'fullName'  => $feedback['fullName'],
            'email'     => $feedback['email'] ?? null,
            'phone'     => $feedback['phone'] ?? null,
            'subject'   => $feedback['subject'],
            'message'   => $htmlBody,
            'created'   => gmdate('Y-m-d H:i:s'),

        ]);
        connect()->table('feedback')->insert($mails);
    }


    public function send_telegram($template, $data)
    {
        if (isset($data[0]) && !empty($data[0]) && isset($data[1]) && !empty($data[1]) && ($this->telegramConfig['status'] == 'V')) {
            $this->options($template, $data);
        }
    }

    private function options(string $templateName, $data = [])
    {
        $userData = $this->telegramConfig['telegram_user_data'];
        $groupData = $this->telegramConfig['telegram_user_groupdata'];

        $key = $this->telegramConfig['telegram_key'];

        if (!empty($key)) {
            $this->messenger = new Telegram($key, $this->telegramConfig['timeout']);
            $this->messenger->setLog( new Log('telegram.log'), $this->telegramConfig['logs']);

            if (!empty($userData)) {
                $userData = json_decode($userData, true);
                foreach ($userData as $user) {
//                  if (isset($user[$option . 'telegram']) && (($user[$option . 'telegram'] == 'on') || ((isset($info[1])) && (isset($user[$option . 'telegram'][$info[1]])) && ($user[$option . 'telegram'][$info[1]] == 'on'))) && !empty($user['id_telegram']) && ($key)) {
                    if ((isset($user['checked']) && $user['checked'] == 'on') && !empty($user['id_telegram']) && ($key)) {
                        $this->sendMessage($user, $templateName, $data);
                    }
                }
            }

            if (!empty($groupData)) {
                $groupData = json_decode($groupData, true);
                foreach ($groupData as $user) {
//                    if (isset($user[$templateName]) && (($user[$templateName] == 'on') || ((isset($info[1])) && (isset($user[$templateName][$info[1]])) && ($user[$templateName][$info[1]] == 'on'))) && !empty($user['id_telegram']) && ($key)) {
                    if ((isset($user['checked']) && $user['checked'] == 'on') && !empty($user['id_telegram']) && ($key)) {
                        $this->sendMessage($user, $templateName, $data);
                    }
                }
            }

        }
    }

    private function sendMessage($user, $templateName, $data)
    {
        $send = false;
        $webhook = $this->telegramConfig['webhook'];

        $dr = $templateName . 'template';
        $text = htmlspecialchars_decode($this->$dr($data));
        $this->messenger->setTo($user['id_telegram']);

        if (empty($webhook) || ($webhook == 'no')) {
            $send = false;
        } else {
            $send = $this->messenger->sendMessage($text, $this->telegramConfig['trim_messages']);
        }

        // proxy
        if ((!$send) && ($this->telegramConfig['proxy'] == '1') && !empty($this->telegramConfig['telegram_proxy_data'])) {
            $telegram_proxy_data = json_decode($this->telegramConfig['telegram_proxy_data'], true);
            foreach ($telegram_proxy_data as $key => $proxy) {
                if ((!$send) && isset($proxy['status']) && !empty($proxy['ip']) && !empty($proxy['port'])) {
                    $proxydata = $proxy['ip'] . ':' . $proxy['port'];
                    if (!empty($proxy['login']) || !empty($proxy['password'])) {
                        $proxydata .= '@' . $proxy['login'] . ':' . $proxy['password'];
                    }

                    $this->messenger->setProxy($proxydata);
                    $proxydata = '';
                    $send = $this->messenger->sendMessage($text, $this->telegramConfig['trim_messages']);
                }
            }
        }
    }


    /** ШАБЛОНЫ */

    private function call_me_template($data)
    {
        $message = '';
        if (!empty($this->telegramConfig['telegram_langdata'])) {
            $message = json_decode($this->telegramConfig['telegram_langdata'], true)['call_me_telegram'];
        }

        $find = array(
            '{date_added}',
            '{fullName}',
            '{phone}',
        );

        $feedback = $data[1];

        $replace = array(
            '{date_added}'    => date("Y-m-d H:i:s"),
            '{fullName}'      => $feedback['fullName'] ?? '',
            '{phone}'         => $feedback['phone'] ?? '',

        );

        return str_replace(array("\r\n", "\r", "\n"), chr(10), preg_replace(array("/\s\s+/", "/\r\r+/", "/\n\n+/"), chr(10), str_replace($find, $replace, $message)));
    }


    private function feedback_template($data)
    {
        $message = '';
        if (!empty($this->telegramConfig['telegram_langdata'])) {
            $message = json_decode($this->telegramConfig['telegram_langdata'], true)['feedback_telegram'];
        }

        $find = array(
            '{firstName}',
            '{lastName}',
            '{fullName}',
            '{phone}',
            '{email}',
            '{message}',
            '{date_added}'
        );

        $feedback = $data[1];


        $replace = array(
            '{firstName}'     => $feedback['firstName'] ?? '',
            '{lastName}'      => $feedback['lastName'] ?? '',
            '{fullName}'      => $feedback['fullName'] ?? '',
            '{phone}'         => $feedback['phone'] ?? '',
            '{email}'         => $feedback['email'] ?? '',
            '{message}'       => $feedback['message'] ?? '',
            '{date_added}'    => date("Y-m-d H:i:s")
        );

        return str_replace(array("\r\n", "\r", "\n"), chr(10), preg_replace(array("/\s\s+/", "/\r\r+/", "/\n\n+/"), chr(10), str_replace($find, $replace, $message)));
    }

    private function question_template($data)
    {
        $message = '';
        if (!empty($this->telegramConfig['telegram_langdata'])) {
            $message = json_decode($this->telegramConfig['telegram_langdata'], true)['question_telegram'];
        }

        $find = array(
            '{firstName}',
            '{lastName}',
            '{fullName}',
            '{phone}',
            '{email}',
            '{type}',
            '{message}',
            '{date_added}'
        );

        $feedback = $data[1];


        $replace = array(
            '{firstName}'     => $feedback['firstName'] ?? '',
            '{lastName}'      => $feedback['lastName'] ?? '',
            '{fullName}'      => $feedback['fullName'] ?? '',
            '{phone}'         => $feedback['phone'] ?? '',
            '{email}'         => $feedback['email'] ?? '',
            '{type}'         => $feedback['type'] ?? '',
            '{message}'       => $feedback['message'] ?? '',
            '{date_added}'    => date("Y-m-d H:i:s")
        );

        return str_replace(array("\r\n", "\r", "\n"), chr(10), preg_replace(array("/\s\s+/", "/\r\r+/", "/\n\n+/"), chr(10), str_replace($find, $replace, $message)));
    }

    private function service_template($data)
    {
        $message = '';
        if (!empty($this->telegramConfig['telegram_langdata'])) {
            $message = json_decode($this->telegramConfig['telegram_langdata'], true)['service_telegram'];
        }

        $find = array(
            '{firstName}',
            '{lastName}',
            '{fullName}',
            '{phone}',
            '{email}',
            '{course}',
            '{product_id}',
            '{quantity}',
            '{product_name}',
            '{message}',
            '{date_added}'
        );

        $feedback = $data[1];


        $replace = array(
            '{firstName}'     => $feedback['firstName'] ?? '',
            '{lastName}'      => $feedback['lastName'] ?? '',
            '{fullName}'      => $feedback['fullName'] ?? '',
            '{phone}'         => $feedback['phone'] ?? '',
            '{email}'         => $feedback['email'] ?? '',
            '{course}'        => $feedback['course'] ?? '',
            '{type}'          => $feedback['type'] ?? '',
            '{message}'       => $feedback['message'] ?? '',
            '{date_added}'    => date("Y-m-d H:i:s")
        );

        return str_replace(array("\r\n", "\r", "\n"), chr(10), preg_replace(array("/\s\s+/", "/\r\r+/", "/\n\n+/"), chr(10), str_replace($find, $replace, $message)));
    }

    private function quick_order_template($data)
    {
        $message = '';
        if (!empty($this->telegramConfig['telegram_langdata'])) {
            $message = json_decode($this->telegramConfig['telegram_langdata'], true)['quickOrder_telegram'];
        }

        $find = array(
            '{firstName}',
            '{lastName}',
            '{fullName}',
            '{phone}',
            '{email}',
            '{type}',
            '{product_id}',
            '{quantity}',
            '{product_name}',
            '{message}',
            '{date_added}'
        );

        $feedback = $data[1];

        $replace = array(
            '{firstName}'     => $feedback['firstName'] ?? '',
            '{lastName}'      => $feedback['lastName'] ?? '',
            '{fullName}'      => $feedback['fullName'] ?? '',
            '{phone}'         => $feedback['phone'] ?? '',
            '{email}'         => $feedback['email'] ?? '',
            '{type}'          => $feedback['type'] ?? '',
            '{product_id}'    => $feedback['product_id'] ?? '',
            '{quantity}'      => $feedback['quantity'] ?? '',
            '{product_name}'  => $feedback['product_name'] ?? '',
            '{message}'       => $feedback['message'] ?? '',
            '{date_added}'    => date("Y-m-d H:i:s")
        );

        return str_replace(array("\r\n", "\r", "\n"), chr(10), preg_replace(array("/\s\s+/", "/\r\r+/", "/\n\n+/"), chr(10), str_replace($find, $replace, $message)));
    }

    private function agree_purchase_template($data)
    {
        $message = '';
        if (!empty($this->telegramConfig['telegram_langdata'])) {
            $message = json_decode($this->telegramConfig['telegram_langdata'], true)['agreePurchase_telegram'];
        }

        $find = array(
            '{firstName}',
            '{lastName}',
            '{fullName}',
            '{phone}',
            '{email}',
            '{type}',
            '{product_id}',
            '{quantity}',
            '{product_name}',
            '{message}',
            '{date_added}'
        );

        $feedback = $data[1];

        $replace = array(
            '{firstName}'     => $feedback['firstName'] ?? '',
            '{lastName}'      => $feedback['lastName'] ?? '',
            '{fullName}'      => $feedback['fullName'] ?? '',
            '{phone}'         => $feedback['phone'] ?? '',
            '{email}'         => $feedback['email'] ?? '',
            '{type}'          => $feedback['type'] ?? '',
            '{product_id}'    => $feedback['product_id'] ?? '',
            '{quantity}'      => $feedback['quantity'] ?? '',
            '{product_name}'  => $feedback['product_name'] ?? '',
            '{message}'       => $feedback['message'] ?? '',
            '{date_added}'    => date("Y-m-d H:i:s")
        );

        return str_replace(array("\r\n", "\r", "\n"), chr(10), preg_replace(array("/\s\s+/", "/\r\r+/", "/\n\n+/"), chr(10), str_replace($find, $replace, $message)));
    }

    private function orders_template($data) {
        return $this->order_template($data[0], $data[1]);
    }

    private function new_order_template($data) {
        return $this->order_template($data[0], 'Вы получили новый заказ №{order_id}, магазин {store_name}, номер телефона: {user_phone}, e-mail покупателя: {user_email}');
    }

    private function order_template($order_id, $data)
    {
        $message = '';
        if (!empty($this->telegramConfig['telegram_langdata'])) {
            $message = json_decode($this->telegramConfig['telegram_langdata'], true)['order_telegram'];
        }

        $format = '{fullName} {firstname} {lastname}' . "\n"  . "\n" . '{address}';

        $find = array(
            '{fullName}',
            '{firstname}',
            '{lastname}',
            '{address}',
            '{zone}'
        );

        $replace = array(
            'fullName'  => $data['fullName'],
            'firstname' => $data['firstName'],
            'lastname'  => $data['lastName'],
            'address'   => $data['address'],
            'zone'      => $data['shipping_zone'],
        );

        $shipping_address = str_replace(array("\r\n", "\r", "\n"), ' ', preg_replace(array("/\s\s+/", "/\r\r+/", "/\n\n+/"), ' ', trim(str_replace($find, $replace, $format))));

        $find = array(
            '{order_id}',
            '{store_name}',
            '{user_fullName}',
            '{user_firstname}',
            '{user_lastname}',
            '{user_email}',
            '{user_phone}',
            '{payment_method}',
            '{shipping_address}',
            '{shipping_method}',
            '{shipping_date}',
            '{total}',
            '{message}',
            '{order_status}',
            '{date_added}',
            '{date_modified}'
        );

        $replace = array(
            '{order_id}'           		=> $order_id ?? '',
            '{store_name}'         		=> $data['store_name'] ?? '',
            '{user_fullName}' 		    => $data['fullName'] ?? '',
            '{user_firstname}' 		    => $data['firstName'] ?? '',
            '{user_lastname}'  		    => $data['lastName'] ?? '',
            '{user_email}'     		    => $data['email'] ?? '',
            '{user_phone}' 		        => $data['phone'] ?? '',
            '{payment_method}'     		=> $data['payment_method'] ?? '',
            '{shipping_address}'    	=> $data['address'] ?? '',
            '{shipping_method}'    		=> $data['shipping_method'] ?? '',
            '{shipping_date}'    		=> $data['shipping_date'] ?? '',
            '{total}'              		=> isset($data['totals'][2]['value']) ? number_format($data['totals'][2]['value'], 0, '.', ',') . ' сум' : '',
            '{message}'            		=> $data['message'] ?? '',
            '{order_status}'       		=> $data['order_status'] ?? '',
            '{date_added}'         		=> $data['date_added'] ?? '',
            '{date_modified}'      		=> $data['date_modified'] ?? '',
        );

        $message = str_replace(array("\r\n", "\r", "\n"), chr(10), preg_replace(array("/\s\s+/", "/\r\r+/", "/\n\n+/"), chr(10), trim(str_replace($find, $replace, $message))));

        if (!empty($data['products'])) {
            if (preg_match("!{cart_start}(.*?){cart_finish}!si", $message, $matches)) {
                $text = '';

                foreach ($data['products'] as $product) {
                    $find = array(
                        '{product_name}',
                        '{product_options}',
                        '{product_url}',
                        '{product_sku}',
                        '{product_price}',
                        '{product_quantity}',
                        '{product_total}'
                    );

                    $options = '';
                    if (!empty($product['option'])) {
                        foreach ($product['option'] as $option) {
//                            $options = "-" . $option['name'] . ": " . $option['value'];
                            $options = "-" . $option['value'];
                        }
                    }

                    $replace = array(
                        'product_name'      => "<a href='" . SITE_URL . $product['url'] . "'>" . $product['name'] . "</a>" ?? '',
                        'product_options'   => $options,
                        'product_url'       => SITE_URL . $product['url'],
                        'product_sku'       => $product['sku'] ?? '',
                        'product_price'     => !empty($product['price']) ? number_format($product['price'], 0, '.', ',') . ' сум' : '',
                        'product_quantity'  => $product['quantity'] ?? '',
                        'product_total'     => !empty($product['total']) ? number_format($product['total'], 0, '.', ',') . ' сум' : ''
                    );

                    $text .= trim(str_replace($find, $replace, $matches[1])) . "\n\n";
                }

                if (!empty($text)) {
                    $message = trim(str_replace($matches[0], $text, $message));
                }
            }
        }

        return $message;

    }

}
