<?php
/**
 * @copyright    OCTemplates
 * @support      https://octemplates.net/
 * @license      LICENSE.txt
 */

class ModelOctemplatesModuleOctSmsNotify extends Model {
    private $sender;
    private $settings;
    private $moduleToken;

    public function __construct($registry) {
        parent::__construct($registry);
        $this->settings = $this->config->get('oct_sms_settings');
        $this->sender = $this->settings['sender_name'] ?? '';
        $this->moduleToken = $this->settings['oct_sms_token'] ?? '';
    }

    public function sendNotification(array $data = []) {
        $access_token = isset($data['access_token']) ? trim($data['access_token']) : '';
        
        if ($access_token !== $this->moduleToken || empty($this->sender)) {
            return false;
        }
    
        if (!empty($data['phone']) && !empty($data['message']) && !empty($data['template_code'])) {
            $phone = $this->sanitizePhone($data['phone']);
            $message = $this->sanitizeMessage($data['message']);
            $template_code = $this->sanitizeTemplateCode($data['template_code']);
    
            if ($this->validatePhone($phone) && $this->validateTemplateCode($template_code)) {
                return $this->sendSms($phone, $message, $template_code);
            } 
        }
    
        return false;
    }
    
    public function addSmsLog($data) {
        $this->db->query("INSERT INTO `" . DB_PREFIX . "oct_sms_notify_log` SET phone = '" . $this->db->escape($data['phone']) . "', message = '" . $this->db->escape($data['message']) . "', provider = '" . $this->db->escape($data['provider']) . "', response = '" . $this->db->escape($data['response']) . "', template_code = '" . $this->db->escape($data['template_code']) . "', date_added = NOW()");
    }

    private function sendSms($phone, $message, $template_code) {
        if (!$this->isSmsEnabled($template_code)) {
            return false;
        }
        
        $providerName = $this->settings['provider'] ?? '';
        $response = $this->sendSmsViaProvider($providerName, $phone, $message);

        if ($response === false) {
            return false;
        }

        if ($this->isLogEnabled()) {
            $this->logSms($phone, $message, $providerName, $response, $template_code);
        }

        return $response;
    }

    private function isSmsEnabled($template_code) {

        if (!isset($this->settings['status'])) {
            exit('Sms is disabled');
            return false;
        }

        $custom_codes = ['oct_order_sms_templates'];
        if (in_array($template_code, $custom_codes)) {
            return true;
        }

        return !empty($this->settings['templates'][$template_code]['status']);
    }

    private function isLogEnabled() {
        return !empty($this->settings['logging']);
    }

    private function sendSmsViaProvider($providerName, $phone, $message) {
        switch ($providerName) {
            case 'turbosms':
                return $this->sendSmsViaTurboSMS($phone, $message);
            case 'alphasms':
                return $this->sendSmsViaAlphaSMS($phone, $message);
            default:
                return false;
        }
    }

    private function sanitizePhone($phone) {
        return preg_replace('/[^0-9+]/', '', $phone);
    }

    private function sanitizeMessage($message) {
        $message = html_entity_decode($message, ENT_QUOTES, 'UTF-8');

        if (!empty($this->settings['translit'])) {
            $message = $this->translit($message);
        }

        $message = strip_tags($message);
        $message = str_replace('[br]', "\n", $message);

        return trim($message);
    }

    private function sanitizeTemplateCode($template_code) {
        return preg_replace('/[^a-zA-Z0-9_]/', '', trim($template_code));
    }

    private function validatePhone($phone) {
        return preg_match('/^\+?[0-9]{9,15}$/', $phone);
    }

    private function validateTemplateCode($template_code) {
        $custom_codes = ['oct_order_sms_templates'];
        if (in_array($template_code, $custom_codes)) {
            return true;
        }
        return isset($this->settings['templates'][$template_code]);
    }

    private function sendSmsViaTurboSMS($phoneNumber, $message) {
        $turbosms_settings = $this->settings['turbosms'] ?? [];
        $hybridSending = $turbosms_settings['hybrid_sending'] ?? false;
        $token = $turbosms_settings['token'] ?? '';
        $viber_sender = $turbosms_settings['viber_sender'] ?? '';

        if (empty($token)) {
            return 'TurboSMS token is missing';
        }

        $url = "https://api.turbosms.ua/message/send.json";
        $data = [
            'recipients' => [$phoneNumber],
            'sms' => [
                'sender' => $this->sender,
                'text' => $message
            ]
        ];

        if ($hybridSending) {
            $data['viber'] = [
                'sender' => $viber_sender,
                'text' => $message,
                'image_url' => null,
                'button' => null
            ];
        }

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Authorization: Bearer ' . $token,
            'Content-Type: application/json'
        ]);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

        $response = curl_exec($ch);
        if ($response === false) {
            $error = curl_error($ch);
            curl_close($ch);
            return $error;
        }

        curl_close($ch);
        return $response;
    }

    private function sendSmsViaAlphaSMS($phoneNumber, $message) {
        $alphasms_settings = $this->settings['alphasms'] ?? [];
        $hybridSending = $alphasms_settings['hybrid_sending'] ?? false;
        $apiKey = $alphasms_settings['api_key'] ?? '';
        $viber_sender = $alphasms_settings['viber_sender'] ?? '';

        if (empty($apiKey)) {
            return 'AlphaSMS credentials are missing';
        }

        $url = "https://alphasms.ua/api/http.php";
        $data = [
            'version' => 'http',
            'from' => $this->sender,
            'to' => $phoneNumber,
            'key' => $apiKey,
            'message' => $message,
            'command' => 'send'
        ];

        if ($hybridSending) {
            $data['viber'] = 1;
            $data['viber_type'] = 'text';
            $data['viber_message'] = $message;
            $data['viber_from'] = $viber_sender;
            $data['viber_lifetime'] = 60;
            $data['viber_sms'] = 1;
        }

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

        $response = curl_exec($ch);
        if ($response === false) {
            $error = curl_error($ch);
            curl_close($ch);
            return $error;
        }

        curl_close($ch);
        return $response;
    }

    private function logSms($phone, $message, $providerName, $response, $template_code) {
        $this->model_octemplates_module_oct_sms_notify->addSmsLog([
            'phone' => $phone,
            'message' => $message,
            'provider' => $providerName,
            'response' => $response,
            'template_code' => $template_code
        ]);
    }

    private function translit($text) {
        $translit = [
            'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'h', 'ґ' => 'g', 'д' => 'd',
            'е' => 'e', 'є' => 'ye', 'ж' => 'zh', 'з' => 'z', 'и' => 'y', 'і' => 'i',
            'ї' => 'yi', 'й' => 'y', 'к' => 'k', 'л' => 'l', 'м' => 'm', 'н' => 'n',
            'о' => 'o', 'п' => 'p', 'р' => 'r', 'с' => 's', 'т' => 't', 'у' => 'u',
            'ф' => 'f', 'х' => 'kh', 'ц' => 'ts', 'ч' => 'ch', 'ш' => 'sh', 'щ' => 'shch',
            'ь' => '', 'ю' => 'yu', 'я' => 'ya',
            'А' => 'A', 'Б' => 'B', 'В' => 'V', 'Г' => 'H', 'Ґ' => 'G', 'Д' => 'D',
            'Е' => 'E', 'Є' => 'Ye', 'Ж' => 'Zh', 'З' => 'Z', 'И' => 'Y', 'І' => 'I',
            'Ї' => 'Yi', 'Й' => 'Y', 'К' => 'K', 'Л' => 'L', 'М' => 'M', 'Н' => 'N',
            'О' => 'O', 'П' => 'P', 'Р' => 'R', 'С' => 'S', 'Т' => 'T', 'У' => 'U',
            'Ф' => 'F', 'Х' => 'Kh', 'Ц' => 'Ts', 'Ч' => 'Ch', 'Ш' => 'Sh', 'Щ' => 'Shch',
            'Ь' => '', 'Ю' => 'Yu', 'Я' => 'Ya'
        ];

        return strtr($text, $translit);
    }

	public function createVerificationRecord($phone, $code, $ip) {
		$current_time = time();
		$expires_at = $current_time + 300;

		$this->db->query("
			INSERT INTO `" . DB_PREFIX . "oct_sms_verification` SET
			phone = '" . $this->db->escape($phone) . "',
			code = '" . $this->db->escape($code) . "',
			ip = '" . $this->db->escape($ip) . "',
			attempts = 0,
			created_at = " . (int)$current_time . ",
			expires_at = " . (int)$expires_at . ",
			verified = 0
        ");

		return $this->db->getLastId();
	}

	public function getActiveVerification($sms_id) {
		$current_time = time();
		
		$query = $this->db->query("
			SELECT * FROM `" . DB_PREFIX . "oct_sms_verification`
			WHERE id = " . (int)$sms_id . "
			AND expires_at > " . (int)$current_time . "
			AND verified = 0
			LIMIT 1
		");

		return $query->num_rows ? $query->row : false;
	}

	public function getActiveVerificationByPhone($phone) {
		$current_time = time();
		
		$query = $this->db->query("
			SELECT * FROM `" . DB_PREFIX . "oct_sms_verification`
			WHERE phone = '" . $this->db->escape($phone) . "'
			AND expires_at > " . (int)$current_time . "
			AND verified = 0
			ORDER BY id DESC
			LIMIT 1
		");

		return $query->num_rows ? $query->row : false;
	}

    public function incrementAttempts($sms_id) {
        $this->db->query("
            UPDATE `" . DB_PREFIX . "oct_sms_verification`
            SET attempts = attempts + 1
            WHERE id = " . (int)$sms_id . "
        ");
    }

    public function markAsVerified($sms_id) {
        $current_time = time();
        
        $this->db->query("
            UPDATE `" . DB_PREFIX . "oct_sms_verification`
            SET verified = 1
            WHERE id = " . (int)$sms_id . "
            AND expires_at > " . (int)$current_time . "
        ");
    }

	public function updateVerificationCode($sms_id, $new_code) {
		$current_time = time();
		$expires_at = $current_time + 300;

		$this->db->query("
			UPDATE `" . DB_PREFIX . "oct_sms_verification` SET
			code = '" . $this->db->escape($new_code) . "',
			attempts = 0,
			created_at = " . (int)$current_time . ",
			expires_at = " . (int)$expires_at . "
            WHERE id = " . (int)$sms_id . ";
        ");
	}

	public function deleteVerification($sms_id) {
		$this->db->query("
			DELETE FROM `" . DB_PREFIX . "oct_sms_verification`
			WHERE id = " . (int)$sms_id . ";
		");
	}

	public function cleanupExpired() {
		$this->db->query("
			DELETE FROM `" . DB_PREFIX . "oct_sms_verification`
			WHERE expires_at < " . (int)time() . "
		");
	}
}