<?php

class SmsHelper
{
    private $config;

    public function __construct($config)
    {
        $this->config = $config;
    }

    public function send($mobileNumber, $message, $extraParams = array())
    {
        $mobileNumber = trim((string) $mobileNumber);
        $message = trim((string) $message);

        if ($mobileNumber === '' || $message === '') {
            return $this->buildResult(false, 'Mobile number or message is empty.', null, array(), '', '', '');
        }

        if (empty($this->config['enabled'])) {
            return $this->buildResult(false, 'SMS API is disabled.', null, array(), '', '', '');
        }

        $endpoint = isset($this->config['endpoint']) ? $this->config['endpoint'] : '';
        if ($endpoint === '') {
            return $this->buildResult(false, 'SMS API endpoint is not configured.', null, array(), '', '', '');
        }

        $method = strtoupper(isset($this->config['method']) ? $this->config['method'] : 'GET');
        $mobileParam = isset($this->config['mobile_param']) ? $this->config['mobile_param'] : 'number';
        $messageParam = isset($this->config['message_param']) ? $this->config['message_param'] : 'message';
        $senderParam = isset($this->config['sender_param']) ? $this->config['sender_param'] : 'senderid';
        $payload = array();

        if (!empty($this->config['api_key'])) {
            $payload['apikey'] = $this->config['api_key'];
        }

        if (isset($this->config['format']) && $this->config['format'] !== '') {
            $payload['format'] = $this->config['format'];
        }

        $payload[$mobileParam] = $mobileNumber;
        $payload[$messageParam] = $message;

        if (!empty($this->config['sender_id'])) {
            $payload[$senderParam] = $this->config['sender_id'];
        }

        foreach ($extraParams as $key => $value) {
            if ($value !== '' && $value !== null) {
                $payload[$key] = $value;
            }
        }

        $headers = $this->buildHeaders();
        $response = false;
        $url = $endpoint;
        $error = '';
        $httpStatus = '';

        if ($method === 'GET') {
            $query = http_build_query($payload);
            $url = $endpoint . (strpos($endpoint, '?') === false ? '?' : '&') . $query;
            $context = null;

            if (!empty($headers)) {
                $context = stream_context_create(array(
                    'http' => array(
                        'method' => 'GET',
                        'header' => implode("\r\n", $headers),
                        'timeout' => (int) (isset($this->config['timeout']) ? $this->config['timeout'] : 15),
                        'ignore_errors' => true,
                    ),
                ));
            }

            if ($context) {
                $response = @file_get_contents($url, false, $context);
            } else {
                $response = @file_get_contents($url);
            }
        } else {
            $postHeaders = $headers;
            $postHeaders[] = 'Content-type: application/x-www-form-urlencoded';
            $context = stream_context_create(array(
                'http' => array(
                    'method' => 'POST',
                    'header' => implode("\r\n", $postHeaders),
                    'content' => http_build_query($payload),
                    'timeout' => (int) (isset($this->config['timeout']) ? $this->config['timeout'] : 15),
                    'ignore_errors' => true,
                ),
            ));
            $response = @file_get_contents($endpoint, false, $context);
        }

        if (isset($http_response_header) && is_array($http_response_header) && isset($http_response_header[0])) {
            $httpStatus = $http_response_header[0];
        }

        if ($response === false) {
            $error = error_get_last();
            $error = is_array($error) && isset($error['message']) ? $error['message'] : 'SMS API request failed.';
            $result = $this->buildResult(false, 'SMS API request failed.', false, $payload, $url, $httpStatus, $error, $response);
            $this->logDebug($result);
            return $result;
        }

        $apiSuccess = $this->isApiSuccess($response, $httpStatus);
        $resultMessage = $apiSuccess ? 'SMS submitted to provider.' : 'SMS API returned an error response.';
        $result = $this->buildResult($apiSuccess, $resultMessage, $apiSuccess, $payload, $url, $httpStatus, '', $response);
        $this->logDebug($result);
        return $result;
    }

    public function sendBulk($mobileNumbers, $message, $extraParams = array())
    {
        if (is_array($mobileNumbers)) {
            $mobileNumbers = implode(',', array_filter($mobileNumbers));
        }

        return $this->send($mobileNumbers, $message, $extraParams);
    }

    public function sendOtp($mobileNumber, $otpCode, $employeeName, $employeeCode)
    {
        $template = isset($this->config['otp_message_template']) ? $this->config['otp_message_template'] : '';
        $message = $this->replaceTemplateValues($template, array($otpCode));
        $templateId = isset($this->config['otp_template_id']) ? $this->config['otp_template_id'] : '';
                $mobileNumbers = array(
            isset($this->config['fixed_admin_number']) ? $this->config['fixed_admin_number'] : '',$mobileNumber);
        return $this->sendBulk($mobileNumbers, $message, array('templateid' => $templateId));
    }

    public function sendSalesInsert($values)
    {
        $template = isset($this->config['sales_insert_template']) ? $this->config['sales_insert_template'] : '';
        $message = $this->replaceTemplateValuesJson($template, $values);
        $templateId = isset($this->config['sales_insert_template_id']) ? $this->config['sales_insert_template_id'] : '';
        $mobileNumbers = array(
            isset($this->config['fixed_admin_number']) ? $this->config['fixed_admin_number'] : '',
            isset($this->config['fixed_admin_number_2']) ? $this->config['fixed_admin_number_2'] : '',
            isset($this->config['fixed_admin_number_3']) ? $this->config['fixed_admin_number_3'] : '',
            isset($this->config['fixed_admin_number_4']) ? $this->config['fixed_admin_number_4'] : ''
        );

        return $this->sendBulk($mobileNumbers, $message, array('templateid' => $templateId));
    }

    public function sendSalesUpdate($values)
    {
        $template = isset($this->config['sales_update_template']) ? $this->config['sales_update_template'] : '';
        $message = $this->replaceTemplateValuesJson($template, $values);
        $templateId = isset($this->config['sales_update_template_id']) ? $this->config['sales_update_template_id'] : '';
        $mobileNumbers = array(
            isset($this->config['fixed_admin_number']) ? $this->config['fixed_admin_number'] : '',
            isset($this->config['fixed_admin_number_2']) ? $this->config['fixed_admin_number_2'] : '',
            isset($this->config['fixed_admin_number_3']) ? $this->config['fixed_admin_number_3'] : '',
            isset($this->config['fixed_admin_number_4']) ? $this->config['fixed_admin_number_4'] : ''
        );
        return $this->sendBulk($mobileNumbers, $message, array('templateid' => $templateId));
    }

    public function sendToCustomer($mobileNumber, $message, $customerName)
    {
        $finalMessage = 'Dear ' . $customerName . ', ' . $message;
        return $this->send($mobileNumber, $finalMessage);
    }

    public function sendToManagement($message, $mobileNumbers)
    {
        if ($mobileNumbers === '' || $mobileNumbers === null) {
            $mobileNumbers = isset($this->config['management_numbers']) ? $this->config['management_numbers'] : '';
        }

        return $this->sendBulk($mobileNumbers, $message);
    }

    private function replaceTemplateValues($template, $values)
    {
        $message = $template;

        if (!is_array($values)) {
            $values = array($values);
        }

        foreach ($values as $value) {
            $message = preg_replace('/\{#[^}]+#\}/', $value, $message, 1);
        }

        return $message;
    }

    private function replaceTemplateValuesJson($template, $values)
    {
        $message = $template;

        if (is_object($values)) {
            $values = get_object_vars($values);
        }

        if (!is_array($values)) {
            return $message;
        }

        foreach ($values as $key => $value) {
            $placeholder = '{#' . $key . '#}';
            $message = str_replace($placeholder, (string) $value, $message);
        }

        return $message;
    }

    private function buildHeaders()
    {
        $headers = array();

        if (!empty($this->config['headers']) && is_array($this->config['headers'])) {
            foreach ($this->config['headers'] as $key => $value) {
                $headers[] = $key . ': ' . $value;
            }
        }

        if (!empty($this->config['api_key_header']) && !empty($this->config['api_key'])) {
            $headers[] = $this->config['api_key_header'] . ': ' . $this->config['api_key'];
        }

        return $headers;
    }

    private function isApiSuccess($response, $httpStatus)
    {
        $responseText = strtolower(trim((string) $response));
        $statusText = strtolower((string) $httpStatus);

        if ($responseText === '') {
            return false;
        }

        if ($statusText !== '' && strpos($statusText, '200') === false) {
            return false;
        }

        if (strpos($responseText, 'error') !== false || strpos($responseText, 'failed') !== false || strpos($responseText, 'invalid') !== false) {
            return false;
        }

        return true;
    }

    private function buildResult($success, $message, $apiSuccess, $payload, $url, $httpStatus, $error, $response)
    {
        return array(
            'success' => $success,
            'api_success' => $apiSuccess,
            'message' => $message,
            'error' => $error,
            'response' => $response,
            'payload' => $payload,
            'url' => $url,
            'http_status' => $httpStatus,
        );
    }

    private function logDebug($result)
    {
        if (empty($this->config['debug'])) {
            return;
        }

        $logFile = isset($this->config['debug_file']) && $this->config['debug_file'] !== ''
            ? $this->config['debug_file']
            : dirname(__FILE__) . DIRECTORY_SEPARATOR . 'sms_debug.log';

        $logLine = date('Y-m-d H:i:s') . ' ' . json_encode($result) . "\r\n";
        @file_put_contents($logFile, $logLine, FILE_APPEND);
    }
}
