<?php

namespace FluentMail\App\Services;

use InvalidArgumentException;
use FluentMail\App\Models\Settings;
use FluentMail\App\Services\Notification\Manager as NotificationManager;
use FluentMail\Includes\Support\Arr;

class NotificationHelper
{
    public static function getRemoteServerUrl()
    {
        if (defined('FLUENTSMTP_SERVER_REMOTE_SERVER_URL')) {
            return FLUENTSMTP_SERVER_REMOTE_SERVER_URL;
        }

        return 'https://fluentsmtp.com/wp-json/fluentsmtp_notify/v1/';
    }

    public static function issueTelegramPinCode($data)
    {
        return self::sendTeleRequest('register-site', $data, 'POST');
    }

    public static function registerSlackSite($data)
    {
        return self::sendSlackRequest('register-site', $data, 'POST');
    }

    public static function getTelegramConnectionInfo($token)
    {
        return self::sendTeleRequest('get-site-info', [], 'GET', $token);
    }

    public static function sendTestTelegramMessage($token = '')
    {
        if (!$token) {
            $settings = (new Settings())->notificationSettings();
            $token = Arr::get($settings, 'telegram.token');
        }

        return self::sendTeleRequest('send-test', [], 'POST', $token);
    }

    public static function sendTestPushoverMessage($apiToken, $userKey)
    {
        $message = __('This is a test message for ', 'fluent-smtp') . site_url() . '. ' .
            __('If you get this message, then your site is connected successfully.', 'fluent-smtp');

        return self::sendPushoverMessage($message, $apiToken, $userKey, true, 1);
    }

    public static function disconnectTelegram($token)
    {
        self::sendTeleRequest('disconnect', [], 'POST', $token);

        self::updateChannelSettings('telegram', [
            'status' => 'no',
            'token'  => ''
        ]);

        return true;
    }

    public static function getTelegramBotTokenId()
    {
        static $token = null;

        if ($token !== null) {
            return $token;
        }

        $settings = (new Settings())->notificationSettings();

        $token = Arr::get($settings, 'telegram.token', false);

        if (!$token) {
            $token = false;
        }

        return $token;
    }

    public static function getSlackWebhookUrl()
    {
        static $url = null;

        if ($url !== null) {
            return $url;
        }

        $settings = (new Settings())->notificationSettings();

        $url = Arr::get($settings, 'slack.webhook_url');

        if (!$url) {
            $url = false;
        }

        return $url;
    }

    public static function sendFailedNotificationTele($data)
    {
        wp_remote_post(self::getRemoteServerUrl() . 'telegram/send-failed-notification', array(
            'timeout'   => 0.01,
            'blocking'  => false,
            'body'      => $data,
            'cookies'   => false,
            'sslverify' => false,
        ));

        return true;
    }

    private static function sendTeleRequest($route, $data = [], $method = 'POST', $token = '')
    {
        $url = self::getRemoteServerUrl() . 'telegram/' . $route;

        if ($token) {
            $url .= '?site_token=' . $token;
        }

        if ($method == 'POST') {
            $response = wp_remote_post($url, [
                'body'      => $data,
                'sslverify' => false,
                'timeout'   => 50
            ]);
        } else {
            $response = wp_remote_get($url, [
                'sslverify' => false,
                'timeout'   => 50
            ]);
        }

        if (is_wp_error($response)) {
            return $response;
        }

        $responseCode = wp_remote_retrieve_response_code($response);

        $body = wp_remote_retrieve_body($response);
        $responseData = json_decode($body, true);

        if (!$responseData || empty($responseData['success']) || $responseCode !== 200) {
            return new \WP_Error('invalid_data', 'Something went wrong', $responseData);
        }

        return $responseData;
    }

    private static function sendSlackRequest($route, $data = [], $method = 'POST', $token = '')
    {
        $url = self::getRemoteServerUrl() . 'slack/' . $route;

        if ($token) {
            $url .= '?site_token=' . $token;
        }

        if ($method == 'POST') {
            $response = wp_remote_post($url, [
                'body'      => $data,
                'sslverify' => false,
                'timeout'   => 50
            ]);
        } else {
            $response = wp_remote_get($url, [
                'sslverify' => false,
                'timeout'   => 50
            ]);
        }

        if (is_wp_error($response)) {
            return $response;
        }

        $responseCode = wp_remote_retrieve_response_code($response);

        $body = wp_remote_retrieve_body($response);

        $responseData = json_decode($body, true);

        if (!$responseData || empty($responseData['success']) || $responseCode !== 200) {
            return new \WP_Error('invalid_data', 'Something went wrong', $responseData);
        }

        return $responseData;
    }

    public static function sendSlackMessage($message, $webhookUrl, $blocking = false)
    {

        if (is_array($message)) {
            $body = wp_json_encode($message);
        } else {
            $body = wp_json_encode(array('text' => $message));
        }

        $args = array(
            'body'        => $body,
            'headers'     => array(
                'Content-Type' => 'application/json',
            ),
            'cookies'     => null,
            'timeout'     => 60,
            'redirection' => 5,
            'blocking'    => true,
            'httpversion' => '1.0',
            'sslverify'   => false,
            'data_format' => 'body',
        );

        if (!$blocking) {
            $args['blocking'] = false;
            $args['timeout'] = 0.01;
        }

        $response = wp_remote_post($webhookUrl, $args);

        if (!$blocking) {
            return true;
        }

        if (is_wp_error($response)) {
            return $response;
        }


        $body = wp_remote_retrieve_body($response);


        return json_decode($body, true);
    }

    public static function sendDiscordMessage($message, $webhookUrl, $blocking = false)
    {
        $body = wp_json_encode(array(
            'content'  => $message,
            'username' => 'FluentSMTP'
        ));

        $args = array(
            'body'        => $body,
            'headers'     => array(
                'Content-Type' => 'application/json',
            ),
            'timeout'     => 60,
            'redirection' => 5,
            'blocking'    => true,
            'httpversion' => '1.0',
            'sslverify'   => false,
            'data_format' => 'body',
        );

        if (!$blocking) {
            $args['blocking'] = false;
            $args['timeout'] = 0.01;
        }

        $response = wp_remote_post($webhookUrl, $args);

        if (!$blocking) {
            return true;
        }

        if (is_wp_error($response)) {
            return $response;
        }

        $body = wp_remote_retrieve_body($response);
        return json_decode($body, true);
    }

    public static function sendPushoverMessage($message, $apiToken, $userKey, $blocking = false, $priority = 1)
    {
        $title = sprintf(__('[%s] Failed to send email', 'fluent-smtp'), get_bloginfo('name'));

        $args = array(
            'body'        => array(
                'token'   => $apiToken,
                'user'    => $userKey,
                'message' => $message,
                'title'   => $title,
                'priority' => $priority,
                'html'    => 1, // Enable HTML formatting
            ),
            'timeout'     => 60,
            'redirection' => 5,
            'blocking'    => true,
            'httpversion' => '1.0',
            'sslverify'   => true,
        );

        if (!$blocking) {
            $args['blocking'] = false;
            $args['timeout'] = 0.01;
        }

        $response = wp_remote_post('https://api.pushover.net/1/messages.json', $args);

        if (!$blocking) {
            return true;
        }

        if (is_wp_error($response)) {
            return $response;
        }

        $responseCode = wp_remote_retrieve_response_code($response);
        $body = wp_remote_retrieve_body($response);
        $responseData = json_decode($body, true);

        if ($responseCode !== 200 || empty($responseData['status']) || $responseData['status'] != 1) {
            $errorMessage = __('Pushover API error', 'fluent-smtp');
            if (!empty($responseData['errors'])) {
                $errorMessage = is_array($responseData['errors']) ? implode(', ', $responseData['errors']) : $responseData['errors'];
            }
            return new \WP_Error('pushover_api_error', $errorMessage, $responseData);
        }

        return $responseData;
    }

    public static function formatSlackMessageBlock($handler, $logData = [])
    {
        $sendingTo = self::unserialize(Arr::get($logData, 'to'));

        if (is_array($sendingTo)) {
            $sendingTo = Arr::get($sendingTo, '0.email', '');
        }

        if (is_array($sendingTo) || !$sendingTo) {
            $sendingTo = Arr::get($logData, 'to');
        }

        $heading = sprintf(__('[%s] Failed to send email', 'fluent-smtp'), get_bloginfo('name'));

        return [
            'text'   => $heading,
            'blocks' => [
                [
                    'type' => 'header',
                    'text' => [
                        'type'  => 'plain_text',
                        'text'  => $heading,
                        "emoji" => true
                    ]
                ],
                [
                    'type'   => 'section',
                    'fields' => [
                        [
                            'type' => "mrkdwn",
                            'text' => "*Website URL:*\n " . site_url()
                        ],
                        [
                            'type' => "mrkdwn",
                            'text' => "*Sending Driver:*\n " . strtoupper($handler->getSetting('provider'))
                        ],
                        [
                            'type' => "mrkdwn",
                            'text' => "*To Email Address:*\n " . $sendingTo
                        ],
                        [
                            'type' => "mrkdwn",
                            'text' => "*Email Subject:*\n " . Arr::get($logData, 'subject')
                        ]
                    ]
                ],
                [
                    'type' => 'section',
                    'text' => [
                        'type' => "mrkdwn",
                        'text' => "*Error Message:*\n ```" . self::getErrorMessageFromResponse(self::unserialize(Arr::get($logData, 'response'))) . "```"
                    ]
                ],
                [
                    'type' => 'section',
                    'text' => [
                        'type' => "mrkdwn",
                        'text' => "<" . admin_url('options-general.php?page=fluent-mail#/logs?per_page=10&page=1&status=failed&search=') . "|View Failed Email(s)>"
                    ]
                ]
            ]
        ];
    }

    public static function formatDiscordMessageBlock($handler, $logData = [])
    {
        $sendingTo = self::unserialize(Arr::get($logData, 'to'));

        if (is_array($sendingTo)) {
            $sendingTo = Arr::get($sendingTo, '0.email', '');
        }

        if (is_array($sendingTo) || !$sendingTo) {
            $sendingTo = Arr::get($logData, 'to');
        }

        $heading = sprintf(__('[%s] Failed to send email', 'fluent-smtp'), get_bloginfo('name'));

        $content = '## ' . $heading . "\n";
        $content .= __('**Website URL:** ', 'fluent-smtp') . site_url() . "\n";
        $content .= __('**Sending Driver:** ', 'fluent-smtp') . strtoupper($handler->getSetting('provider')) . "\n";
        $content .= __('**To Email Address:** ', 'fluent-smtp') . $sendingTo . "\n";
        $content .= __('**Email Subject:** ', 'fluent-smtp') . Arr::get($logData, 'subject') . "\n";
        $content .= __('**Error Message:** ```', 'fluent-smtp') . self::getErrorMessageFromResponse(self::unserialize(Arr::get($logData, 'response'))) . "```\n";
        $content .= __('[View Failed Email(s)](', 'fluent-smtp') . admin_url('options-general.php?page=fluent-mail#/logs?per_page=10&page=1&status=failed&search=') . ')';

        return $content;
    }

    public static function formatPushoverMessage($handler, $logData = [])
    {
        $sendingTo = self::unserialize(Arr::get($logData, 'to'));

        if (is_array($sendingTo)) {
            $sendingTo = Arr::get($sendingTo, '0.email', '');
        }

        if (is_array($sendingTo) || !$sendingTo) {
            $sendingTo = Arr::get($logData, 'to');
        }

        $provider = strtoupper($handler->getSetting('provider'));
        $subject = Arr::get($logData, 'subject');

        $message = '<b>' . __('Website URL:', 'fluent-smtp') . '</b> ' . esc_html(site_url()) . "<br>";
        $message .= '<b>' . __('Sending Driver:', 'fluent-smtp') . '</b> ' . esc_html($provider) . "<br>";
        $message .= '<b>' . __('To Email Address:', 'fluent-smtp') . '</b> ' . esc_html($sendingTo) . "<br>";
        $message .= '<b>' . __('Email Subject:', 'fluent-smtp') . '</b> ' . esc_html($subject) . "<br>";
        $message .= '<b>' . __('Error Message:', 'fluent-smtp') . '</b><br>';
        $message .= '<code>' . esc_html(self::getErrorMessageFromResponse(
            self::unserialize(Arr::get($logData, 'response'))
        )) . '</code><br>';
        $logsUrl = admin_url(
            'options-general.php?page=fluent-mail#/logs?per_page=10&page=1&status=failed&search='
        );
        $message .= '<a href="' . esc_url($logsUrl) . '">' . __('View Failed Email(s)', 'fluent-smtp') . '</a>';

        return $message;
    }

    public static function getErrorMessageFromResponse($response)
    {
        if (!$response || !is_array($response)) {
            return '';
        }

        if (!empty($response['fallback_response']['message'])) {
            $message = $response['fallback_response']['message'];
        } else {
            $message = Arr::get($response, 'message');
        }

        if (!$message) {
            return '';
        }

        if (!is_string($message)) {
            $message = json_encode($message);
        }

        return $message;
    }

    protected static function unserialize($data)
    {
        if (is_serialized($data)) {
            if (preg_match('/(^|;)O:[0-9]+:/', $data)) {
                return '';
            }
            return unserialize(trim($data), ['allowed_classes' => false]);
        }

        return $data;
    }

    public static function updateChannelSettings($channelName, $channelSettings)
    {
        $settings = (new Settings())->notificationSettings();

        $settings[$channelName] = $channelSettings;

        $isActive = Arr::get($channelSettings, 'status') === 'yes' ? true : false;

        $activeChannels = $settings['active_channel'];

        if ($isActive) {
            if (!in_array($channelName, $activeChannels)) {
                $activeChannels[] = $channelName;
            }
        } else {
            if (($key = array_search($channelName, $activeChannels)) !== false) {
                unset($activeChannels[$key]);
            }
        }

        $activeChannels = array_values($activeChannels);
        $settings['active_channel'] = $activeChannels;

        update_option('_fluent_smtp_notify_settings', $settings, false);

        return true;
    }
}
