<?php

/**
 * SMS Gateway handler class
 *
 * @author wpuf
 */
class wpuf_SMS_Gateways {

    private static $_instance;

    /**
     * Gateway slug
     *
     * @param string $provider name of the gateway
     */
    function __construct() {
        add_action( 'wpuf_sms_via_smsglobal', [ $this, 'smsGlobalAPI' ] );
        add_action( 'wpuf_sms_via_clickatell', [ $this, 'clickatellAPI' ] );
        add_action( 'wpuf_sms_via_twilio', [ $this, 'twilio_api' ] );
        add_action( 'wpuf_sms_via_nexmo', [ $this, 'nexmo_api' ] );
    }

    public static function instance() {
        if ( !self::$_instance ) {
            self::$_instance = new wpuf_SMS_Gateways();
        }

        return self::$_instance;
    }



    /**
     * Sends SMS via SMS Global REST API v2
     *
     * @uses `wpuf_sms_via_smsglobal` filter to fire
     *
     * @param array|object $sms_data SMS data containing mob_number, sms_body, sms_sender_name
     * @return array Response array with success status, message, and optional message_id
     */
    function smsGlobalAPI( $sms_data ) {
        $response = [
            'success' => false,
            'message' => 'Failed to send SMS'
        ];

        // Get API credentials - SMS Global now uses API Key and Secret instead of username/password
        $api_key = wpuf_get_option( 'smsglobal_api_key', 'wpuf_sms' );
        $api_secret = wpuf_get_option( 'smsglobal_api_secret', 'wpuf_sms' );
        
        // Handle both array and object data types
        $sender_name = isset($sms_data->sms_sender_name) ? $sms_data->sms_sender_name : '';
        $mob_number  = isset($sms_data->mob_number) ? $sms_data->mob_number : '';
        $sms_body    = isset($sms_data->sms_body) ? $sms_data->sms_body : '';
        
        if ( empty( $api_key ) || empty( $api_secret ) || empty( $mob_number ) || empty( $sms_body ) ) {
            $response['message'] = 'Missing required SMS Global API credentials or SMS data';
            return $response;
        }

        // SMS Global REST API v2 endpoint
        $url = 'https://api.smsglobal.com/v2/sms/';
        
        // Prepare request body for REST API
        $body = [
            'message'     => $sms_body,
            'destination' => $mob_number
        ];
        
        // Add sender if provided
        if ( !empty( $sender_name ) ) {
            $body['origin'] = $sender_name;
        }

        // Prepare authentication header
        $auth_string = base64_encode( $api_key . ':' . $api_secret );
        
        $args = [
            'method' => 'POST',
            'headers' => [
                'Authorization' => 'Basic ' . $auth_string,
                'Content-Type' => 'application/json',
                'Accept' => 'application/json'
            ],
            'body' => json_encode($body),
            'timeout' => 30
        ];

        // Make the API request
        $api_response = wp_remote_request( $url, $args );

        if ( is_wp_error( $api_response ) ) {
            $response['message'] = 'HTTP error: ' . $api_response->get_error_message();
            return $response;
        }

        $http_code     = wp_remote_retrieve_response_code( $api_response );
        $response_body = wp_remote_retrieve_body( $api_response );
        
        // Parse JSON response
        $json_response = json_decode( $response_body, true );

        if ( 200 === $http_code || 201 === $http_code ) {
            // Success response
            if ( isset( $json_response['messages'] ) && is_array( $json_response['messages'] ) && count( $json_response['messages'] ) > 0 ) {
                $message_info = $json_response['messages'][0];

                if ( isset($message_info['id']) ) {
                    $response = [
                        'success'    => true,
                        'message'    => 'SMS sent successfully via SMS Global',
                        'message_id' => $message_info['id']
                    ];
                } else {
                    $response['message'] = 'SMS sent but no message ID returned';
                }
            } else {
                $response['message'] = 'Invalid response format from SMS Global API';
            }
        } else {
            // Error response
            if ( isset( $json_response['errors'] ) && is_array( $json_response['errors'] ) ) {
                $errors = [];
                foreach ( $json_response['errors'] as $error ) {
                    if ( isset( $error['message'] ) ) {
                        $errors[] = $error['message'];
                    }
                }
                $response['message'] = 'SMS Global API error: ' . implode(', ', $errors) . ' (HTTP Status: ' . $http_code . ')';
            } elseif ( isset( $json_response['message'] ) ) {
                $response['message'] = 'SMS Global API error: ' . $json_response['message'] . ' (HTTP Status: ' . $http_code . ')';
            } else {
                $response['message'] = 'SMS Global API error - HTTP Status: ' . $http_code;
            }
        }

        return $response;
    }

    /**
     * Sends SMS via Clickatell api
     *
     * @uses `wpuf_sms_via_clickatell` filter to fire
     *
     * @param array|object $sms_data SMS data containing mob_number, sms_body
     * @return array Response array with success status and message
     */
    function clickatellAPI( $sms_data ) {
        $api_key = wpuf_get_option( 'clickatell_api_key', 'wpuf_sms' );
        $mob_number = isset($sms_data->mob_number) ? $sms_data->mob_number : '';
        $sms_body = isset($sms_data->sms_body) ? $sms_data->sms_body : '';
        $response = ['success' => false];

        // Bail out if nothing provided
        if ( empty( $api_key ) || empty( $mob_number ) || empty( $sms_body ) ) {
            return $response;
        }

        // Use the new Clickatell Platform API endpoint
        $baseurl = "https://platform.clickatell.com/messages/http/send";
        $url = sprintf('%s?apiKey=%s&to=%s&content=%s', $baseurl, urlencode($api_key), urlencode($mob_number), urlencode($sms_body));

        $api_response = wp_remote_get($url);
        if ( is_wp_error( $api_response ) ) {
            $error_message = $api_response->get_error_message();
            $response['message'] = 'HTTP error: ' . $error_message;
            return $response;
        }

        $http_code = wp_remote_retrieve_response_code($api_response);
        $body = wp_remote_retrieve_body($api_response);

        if ( $http_code == 200 && $body ) {
            $json = json_decode($body, true);
            if (isset( $json['messages'] ) && is_array( $json['messages'] )) {
                // Check if the response contains messages
                $response['success'] = true;
                $response['message'] = 'SMS sent via Clickatell Platform API.';
            } elseif ( isset( $json['error'] ) || isset( $json['errorDescription'] ) ) {
                // Handle error response
                $error_msg = '';
                if ( isset( $json['error'] ) ) {
                    $error_msg .= $json['error'];
                }
                if ( isset( $json['errorDescription'] ) ) {
                    $error_msg .= ($error_msg ? ': ' : '') . $json['errorDescription'];
                }
                $response['message'] = $error_msg;
            } else {
                $response['message'] = 'Unknown response from Clickatell.';
            }
        } else {
            $json = json_decode($body, true);
            if ( is_array( $json ) && ( isset( $json['error'] ) || isset( $json['errorDescription'] ) ) ) {
                $error_msg = '';
                
                if ( isset( $json['error'] ) ) {
                    $error_msg .= $json['error'];
                }

                if ( isset( $json['errorDescription'] ) ) {
                    $error_msg .= ($error_msg ? ': ' : '') . $json['errorDescription'];
                }
                $response['message'] = $error_msg . ' (HTTP Status: ' . $http_code . ')';
            } else {
                $response['message'] = 'No valid response from Clickatell Platform API. HTTP Status: ' . $http_code;
            }
        }

        return $response;
    }

    /**
     * Sends SMS via Nexmo api
     *
     * @uses `wpuf_sms_via_nexmo` filter to fire
     *
     * @param array|object $sms_data SMS data containing mob_number, sms_body, sms_sender_name, code
     * @return array Response array with success status and message
     */
    function nexmo_api( $sms_data ) {

        $api_key    = wpuf_get_option( 'nexmo_api_key', 'wpuf_sms' );
        $api_secret = wpuf_get_option( 'nexmo_api_Secret', 'wpuf_sms' );

        $from       = isset($sms_data->sms_sender_name) ? $sms_data->sms_sender_name : '';
        $mob_number = isset($sms_data->mob_number) ? $sms_data->mob_number : '';
        $sms_body   = isset($sms_data->sms_body) ? $sms_data->sms_body : '';
        $code       = isset($sms_data->code) ? $sms_data->code : '';

        $url = 'https://rest.nexmo.com/sms/json';
        $args = [
            'body' => [
                'api_key' => $api_key,
                'api_secret' => $api_secret,
                'from' => $from,
                'to' => $mob_number,
                'type' => 'text',
                'text' => $sms_body
            ]
        ];

        $response = ['success' => false];
        $response_obj = wp_remote_post( $url, $args );

        if ( !is_wp_error( $response_obj ) ) {
            $api_response = json_decode( wp_remote_retrieve_body( $response_obj ) );

                if ( isset( $api_response->messages[0]->status ) && '0' === $api_response->messages[0]->status ) {
                $response = [
                    'success' => true,
                    'code'    => $code,
                    'message' => wpuf_get_option( 'sms_sent_msg', 'wpuf_sms' )
                ];
            } elseif ( isset( $api_response->messages[0]->error_text ) ) {
                $response['message'] = $api_response->messages[0]->error_text;
            }
        } else {
            $response['message'] = $response_obj->get_error_message();
        }

        return $response;
    }

    /**
     * Sends SMS via Twilio api
     *
     * @uses `wpuf_sms_via_twilio` filter to fire
     *
     * @param array|object $sms_data SMS data containing sid, token, from, mob_number, sms_body
     * @return string|WP_Error message SID on success or WP_Error on failure
     */
    function twilio_api( $sms_data ) {
        $sid    = wpuf_get_option( 'twilio_sid', 'wpuf_sms' );
        $token  = wpuf_get_option( 'twilio_token', 'wpuf_sms' );
        $from   = wpuf_get_option( 'twilio_number', 'wpuf_sms' );
        
        $to       = isset($sms_data->mob_number) ? $sms_data->mob_number : '';
        $sms_body = isset($sms_data->sms_body) ? $sms_data->sms_body : '';
        
        if (empty($sid) || empty($token) || empty($from) || empty($to) || empty($sms_body)) {
            return new WP_Error('missing_twilio_data', 'Missing required Twilio configuration or SMS data.');
        }

        // twilio requires + at the beginning
        if ( ! preg_match( '/^\+/', $to ) ) {
            $to = '+' . $to;
        }

        require_once dirname( __FILE__ ) . '/../lib/Twilio/autoload.php';

        $client = new Twilio\Rest\Client($sid, $token);

        try {
            $message = $client->messages->create(
                    $to, // Text this number
                    [
                        'from' => $from, // From a valid Twilio number
                        'body' => $sms_body
                    ]
                );

            return $message->sid;

        } catch (\Twilio\Exceptions\TwilioException $e) {
            return new WP_Error( 'error_sending_sms_using_twilio', $e->getMessage() );
        }
    }

}

new wpuf_SMS_Gateways();
