<?php

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

//'public' is a reserved keyword, which you can't use for namespacing :_(
//namespace MDirectorNewsletter\public;

/**
 *
 * @link       http://mdirector.com
 * @since      1.0.0
 *
 * @package    Mdirector_Newsletter
 * @subpackage Mdirector_Newsletter/public
 */

use EmblueNewsletter\Log\Log;
use MDirectorNewsletter\includes\Mdirector_Newsletter_Api;
use MDirectorNewsletter\includes\Mdirector_Newsletter_Utils;

require_once(plugin_dir_path(__FILE__) . '../vendor/autoload.php');

/**
 * The public-facing functionality of the plugin.
 *
 *
 * @package    Mdirector_Newsletter
 * @subpackage Mdirector_Newsletter/public
 * @author     MDirector
 */
class Mdirector_Newsletter_Public
{

    /**
     * The ID of this plugin.
     *
     * @since    1.0.0
     * @access   private
     * @var      string $mdirectorNewsletter The ID of this plugin.
     */
    private $mdirectorNewsletter;

    /**
     * The version of this plugin.
     *
     * @since    1.0.0
     * @access   private
     * @var      string $version The current version of this plugin.
     */
    private $version;

    /**
     * @var Mdirector_Newsletter_Utils
     */
    private $MdirectorUtils;

    /**
     * @var Mdirector_Newsletter_Api
     */
    private $MdirectorNewsletterApi;

    /**
     * Mdirector_Newsletter_Public constructor.
     *
     * @param $mdirectorNewsletter
     * @param $version
     *
     * @throws \Twig\Error\LoaderError
     * @throws \Twig\Error\RuntimeError
     * @throws \Twig\Error\SyntaxError
     */
    public function __construct($mdirectorNewsletter, $version)
    {
        require_once MDIRECTOR_NEWSLETTER_PLUGIN_DIR .
            'includes/class-mdirector-newsletter-widget.php';
        require_once MDIRECTOR_NEWSLETTER_PLUGIN_DIR .
            'includes/class-mdirector-newsletter-utils.php';

        $mdirectorActive = get_option('mdirector_active');
        $this->MdirectorUtils = new Mdirector_Newsletter_Utils();

        if ($mdirectorActive
            === Mdirector_Newsletter_Utils::SETTINGS_OPTION_ON) {
            $this->MdirectorNewsletterApi = new Mdirector_Newsletter_Api();
            $this->mdirectorNewsletter = $mdirectorNewsletter;
            $this->version = $version;

            // shortcodes
            add_shortcode('emblue_subscription', [$this, 'mdirectorSubscriptionBox']);
            add_shortcode('mdirector_subscriptionbox', [$this, 'mdirectorSubscriptionBox']); // legacy, mantiene compatibilidad

            // ajax calls
            add_action('wp_ajax_emblue_get_nonce', [$this, 'mdirectorAjaxRefreshNonce']);
            add_action('wp_ajax_nopriv_emblue_get_nonce', [$this, 'mdirectorAjaxRefreshNonce']);
            add_action('wp_ajax_emblue_new', [$this, 'mdirectorAjaxNew']);
            add_action('wp_ajax_nopriv_emblue_new', [$this, 'mdirectorAjaxNew']);

            // cron jobs
            add_filter('cron_schedules', [$this, 'mdAddNewInterval']);

            add_action('emblue_newsletter_build', [$this, 'mdEventCron']);

            // Clean up legacy cron hook from versions prior to the emblue_ rename.
            if (wp_next_scheduled('md_newsletter_build')) {
                wp_clear_scheduled_hook('md_newsletter_build');
            }

            if (!wp_next_scheduled('emblue_newsletter_build')) {
                wp_schedule_event(
                    time(), 'every_thirty_minutes',
                    'emblue_newsletter_build'
                );
            }

            register_deactivation_hook(
                MDIRECTOR_NEWSLETTER_PLUGIN_DIR .
                'mdirector-newsletter.php', [$this, 'mdCronDeactivation']
            );
        }
    }

    /**
     * @return bool|string
     * @throws Throwable
     */
    public function mdirectorSubscriptionBox() {
        $output = $this->MdirectorUtils->getRegisterFormHTML();
        if ( $output !== false ) {
            $css_url  = plugin_dir_url( __FILE__ ) . 'css/mdirector-newsletter-public.css';
            $css_path = plugin_dir_path( __FILE__ ) . 'css/mdirector-newsletter-public.css';
            $version  = file_exists( $css_path ) ? (string) filemtime( $css_path ) : $this->version;

            wp_enqueue_style(
                'mdirector-newsletter-public',
                esc_url( $css_url ),
                [],
                $version
            );
            wp_enqueue_script( 'mdirector-public' );
        }
        return $output === false ? $output : wp_kses( $output, Mdirector_Newsletter_Utils::allowedHtml() );
    }

    /**
     * Returns a fresh nonce for cached pages (admin-ajax.php is not page-cached).
     */
    public function mdirectorAjaxRefreshNonce() {
        nocache_headers();
        header( 'Cache-Control: no-store, no-cache, must-revalidate, max-age=0' );
        header( 'Pragma: no-cache' );
        header( 'Expires: Wed, 11 Jan 1984 05:00:00 GMT' );

        wp_send_json_success(
            [ 'nonce' => Mdirector_Newsletter_Utils::createPublicSubscribeNonce() ]
        );
    }

    /**
     * Verifies the subscription AJAX nonce from POST body or header.
     */
    private function verifySubscribeAjaxNonce() {
        $nonce = '';

        // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Reading nonce input only, to verify it below.
        if ( isset( $_REQUEST['emblue_nonce'] ) ) {
            $nonce = sanitize_text_field( wp_unslash( $_REQUEST['emblue_nonce'] ) );
        } elseif ( isset( $_REQUEST['security'] ) ) {
            $nonce = sanitize_text_field( wp_unslash( $_REQUEST['security'] ) );
        } elseif ( isset( $_REQUEST['_ajax_nonce'] ) ) {
            $nonce = sanitize_text_field( wp_unslash( $_REQUEST['_ajax_nonce'] ) );
        } elseif ( ! empty( $_SERVER['HTTP_X_WP_NONCE'] ) ) {
            $nonce = sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_WP_NONCE'] ) );
        }
        // phpcs:enable WordPress.Security.NonceVerification.Recommended

        if ( ! Mdirector_Newsletter_Utils::verifyPublicSubscribeNonce( $nonce ) ) {
            wp_send_json_error( [ 'response' => 'invalid_nonce' ], 403 );
        }
    }

    /**
     */
    public function mdirectorAjaxNew() {
        $this->verifySubscribeAjaxNonce();

        $mdirectorActive = get_option( 'mdirector_active' );
        $settings        = get_option( 'mdirector_settings' );
        $currentList     = 'list';

        // phpcs:disable WordPress.Security.NonceVerification.Missing -- Nonce verified in verifySubscribeAjaxNonce() above.
        $currentLanguage = isset( $_POST['userLang'] )
            ? sanitize_text_field( wp_unslash( $_POST['userLang'] ) )
            : '';
        $list_key = isset( $_POST['list'] )
            ? sanitize_key( wp_unslash( $_POST['list'] ) )
            : '';
        // phpcs:enable WordPress.Security.NonceVerification.Missing

        if ( $mdirectorActive === Mdirector_Newsletter_Utils::SETTINGS_OPTION_ON ) {
            $token      = $settings['mdirector_bearer_token'];
            $targetList = 'mdirector_' . $list_key . '_custom_' . $currentList . '_' . $currentLanguage;

            if ( empty( $settings[ $targetList ] ) ) {
                $targetList = 'mdirector_' . $list_key . '_' . $currentList . '_' . $currentLanguage;
            }

            $list = $settings[ $targetList ] ?? false;

            // Fallback to default language in case user language does not exist.
            if ( ! $list ) {
                $targetList = 'mdirector_' . $list_key . '_' . $currentList . '_' . $this->MdirectorUtils->getCurrentLang();
                $list       = $settings[ $targetList ] ?? false;
            }

            if ($list) {
                if (!is_array($list)) {
                    $list = [$list];
                }                
                
                $groupIds = array_map('intval', $list);

                // phpcs:disable WordPress.Security.NonceVerification.Missing -- Nonce verified in verifySubscribeAjaxNonce() above.
                $email = isset( $_POST['email'] )
                    ? sanitize_email( wp_unslash( $_POST['email'] ) )
                    : '';
                // phpcs:enable WordPress.Security.NonceVerification.Missing
                $results = [];

                $apiResponse =$this->MdirectorNewsletterApi->callAPI(
                    $token,
                    Mdirector_Newsletter_Utils::MDIRECTOR_API_CONTACT_ENDPOINT,
                    'POST', [                            
                        'items' =>[ ['email' => $email]],
                    ]
                );
                if (is_wp_error($apiResponse)) {
                    $this->MdirectorUtils->log(
                        'Error calling contact API',
                        [
                            'email' => $email,
                            'error_code' => $apiResponse->get_error_code(),
                            'error_message' => $apiResponse->get_error_message()
                        ],
                        Mdirector_Newsletter_Utils::LOG_ERROR
                    );
                    echo wp_json_encode(['response' => 'error']);
                    wp_die();
                }
                $decodedResponse = json_decode($apiResponse);
                if (!$decodedResponse || !is_array($decodedResponse)) {
                    $this->MdirectorUtils->log(
                        'Invalid JSON response from contact API',
                        [
                            'email' => $email,
                            'raw_response' => $apiResponse
                        ],
                        Mdirector_Newsletter_Utils::LOG_ERROR
                    );
                    echo wp_json_encode(['response' => 'error']);
                    wp_die();
                }

                $result = $decodedResponse[0];
              
                if (isset($result->status) && $result->status === 'SUCCESS') {
                    $contactId = $result->contactId;
                    
                    $contactData = [
                        'contactId' => $contactId,
                        'email' => $result->correctedEmail,
                        'newContact' => $result->newContact
                    ];
                    
                    $groupResponse = $this->MdirectorNewsletterApi->callAPI(
                        $token,
                        Mdirector_Newsletter_Utils::MDIRECTOR_API_CONTACT_TO_GROUP_ENDPOINT,
                        'POST', [                            
                            'addGroupIds' => $groupIds,
                            'contactIds' => [(int)$contactId]
                        ]
                    );
                    
                    if (is_wp_error($groupResponse)) {
                        $this->MdirectorUtils->log(
                            'Error adding contact to groups after creation',
                            [
                                'contactId' => $contactId,
                                'email' => $contactData['email'],
                                'groupIds' => $groupIds,
                                'error_code' => $groupResponse->get_error_code(),
                                'error_message' => $groupResponse->get_error_message()
                            ],
                            Mdirector_Newsletter_Utils::LOG_ERROR
                        );
                        
                        echo wp_json_encode(['response' => 'error']);
                        wp_die();
                    }

                    $groupData = json_decode($groupResponse);
                    
                    if (!$groupData || !isset($groupData->successful) || !in_array($contactId, $groupData->successful)) {
                        $this->MdirectorUtils->log(
                            'Contact created but failed to add to groups',
                            [
                                'contactId' => $contactId,
                                'email' => $contactData['email'],
                                'groupIds' => $groupIds,
                                'groupResponse' => $groupData
                            ],
                            Mdirector_Newsletter_Utils::LOG_ERROR
                        );
                        
                        echo wp_json_encode(['response' => 'error']);
                        wp_die();
                    }

                    $this->MdirectorUtils->log(
                        'Contact created and added to groups successfully',
                        [
                            'contactId' => $contactId,
                            'email' => $contactData['email'],
                            'groupIds' => $groupIds,
                            'groupsAdded' => count($groupIds)
                        ],
                        Mdirector_Newsletter_Utils::LOG_INFO
                    );
                    
                    echo wp_json_encode(['response' => 'success']);
                    
                } else {
                    $errorMessage = isset($result->errors) && !empty($result->errors) 
                        ? implode(', ', $result->errors) 
                        : 'Unknown error';
                    
                    $this->MdirectorUtils->log(
                        'Error creating contact',
                        [
                            'email' => $email,
                            'error' => $errorMessage,
                            'result' => $result
                        ],
                        Mdirector_Newsletter_Utils::LOG_ERROR
                    );
                    
                    echo wp_json_encode(['response' => 'error']);
                }
            }
        }

        wp_die();
    }

    /**
     * CRON JOBS
     * The scheduled hook is assigned in the constructor because
     * it has given problems in the register_activation_hook.
     */
    public function mdCronDeactivation()
    {
        $this->MdirectorUtils->log(
            'Cron have been deactivated.',
            [],
            $this->MdirectorUtils::LOG_INFO
        );
        wp_clear_scheduled_hook('emblue_newsletter_build');
        wp_clear_scheduled_hook('md_newsletter_build'); // legacy hook, pre emblue_ rename
    }

    public function mdAddNewInterval($schedules)
    {
        $schedules['every_thirty_minutes'] = [
            'interval' => 1800,
            'display' => __( 'Every 30 minutes', 'emblue-newsletter' )
        ];

        return $schedules;
    }

    /**
     * @throws \Twig\Error\LoaderError
     * @throws \Twig\Error\RuntimeError
     * @throws \Twig\Error\SyntaxError
     */
    public function mdEventCron()
    {
        $mdirectorActive = get_option('mdirector_active');
        $settings = get_option('mdirector_settings');
        $optionsForLog = array_diff_key($settings, array_flip(['mdirector_secret']));

        $triggerTime = time();
        $lastCronLauncher = $settings['mdirector_last_cron_launcher'] ?: 0;
        $deltaTime = 60;

        $this->MdirectorUtils->log(
            'Cron event initialized...',
            [$optionsForLog],
            $this->MdirectorUtils::LOG_INFO
        );

        if ($triggerTime < $lastCronLauncher + $deltaTime) {
            $this->MdirectorUtils->log(
                'Cron has been triggered twice.',
                [],
                $this->MdirectorUtils::LOG_INFO
            );

            return false;
        }

        $settings['mdirector_last_cron_launcher'] = $triggerTime;
        $this->MdirectorUtils->updateMDirectorSettingsWithLog(
            $settings,
            'Cron has been triggered twice.'
        );

        if ($mdirectorActive
            === Mdirector_Newsletter_Utils::SETTINGS_OPTION_ON) {
            $utilsInstance = new Mdirector_Newsletter_Utils();
            if ($settings['mdirector_frequency_daily']
                === Mdirector_Newsletter_Utils::SETTINGS_OPTION_ON) {
                $this->MdirectorUtils->log(
                    'Cron is building a DAILY delivery.',
                    [$optionsForLog],
                    $this->MdirectorUtils::LOG_INFO
                );
                $utilsInstance->buildDailyMails();
            } else {
                $this->MdirectorUtils->log(
                    'DAILY deliveries are disabled.',
                    [],
                    $this->MdirectorUtils::LOG_INFO
                );
            }

            if ($settings['mdirector_frequency_weekly']
                === Mdirector_Newsletter_Utils::SETTINGS_OPTION_ON) {
                $this->MdirectorUtils->log(
                    'Cron is building a WEEKLY delivery.',
                    [$optionsForLog],
                    $this->MdirectorUtils::LOG_INFO
                );
                $utilsInstance->buildWeeklyMails();
            } else {
                $this->MdirectorUtils->log(
                    'WEEKLY deliveries are disabled.',
                    [],
                    $this->MdirectorUtils::LOG_INFO
                );
            }
        } else {
            $this->MdirectorUtils->log(
                'MDirector integration is disabled. Nothing to do by now.',
                [],
                $this->MdirectorUtils::LOG_INFO
            );
        }
    }

    /**
     * Register the stylesheets for the public-facing side of the site.
     *
     * @since    1.0.0
     */
    public function enqueueStyles()
    {
        $css_file = plugin_dir_path(__FILE__) . 'css/mdirector-newsletter-public.css';
        $version = file_exists($css_file) ? filemtime($css_file) : $this->version;
        wp_enqueue_style(
            $this->mdirectorNewsletter,
            plugin_dir_url(__FILE__) . 'css/mdirector-newsletter-public.css',
            [],
            $version,
            'all'
        );
    }

    /**
     * Register the stylesheets for the public-facing side of the site.
     *
     * @since    1.0.0
     */
    public function enqueueScripts()
    {
        $js_file    = plugin_dir_path( __FILE__ ) . 'js/mdirector-newsletter-public.js';
        $js_version = file_exists( $js_file ) ? (string) filemtime( $js_file ) : MDIRECTOR_NEWSLETTER_VERSION;
        $ajax_url   = admin_url( 'admin-ajax.php' );

        wp_register_script(
            'mdirector-public',
            MDIRECTOR_NEWSLETTER_PLUGIN_URL . 'public/js/mdirector-newsletter-public.js',
            [ 'jquery' ],
            $js_version,
            true
        );

        wp_localize_script(
            'mdirector-public',
            'emblueNewsletter',
            [
                'ajaxUrl' => $ajax_url,
                'nonce'   => Mdirector_Newsletter_Utils::createPublicSubscribeNonce(),
                'i18n'    => [
                    'success'                => __( 'WIDGET-SCRIPT-SUCCESS', 'emblue-newsletter' ),
                    'emailValidation'        => __( 'WIDGET-SCRIPT-EMAIL-VALIDATION', 'emblue-newsletter' ),
                    'emailText'              => __( 'WIDGET-SCRIPT-EMAIL-TEXT', 'emblue-newsletter' ),
                    'policyValidation'       => __( 'WIDGET-SCRIPT-POLICY-VALIDATION', 'emblue-newsletter' ),
                    'emailAlreadyRegistered' => __( 'WIDGET-SCRIPT-EMAIL-ALREADY-REGISTERED', 'emblue-newsletter' ),
                    'generalError'           => __( 'WIDGET-SCRIPT-GENERAL-ERROR', 'emblue-newsletter' ),
                ],
            ]
        );

        // Backward compatibility for cached JS builds that still reference ajaxurl.
        wp_add_inline_script(
            'mdirector-public',
            'var ajaxurl = ' . wp_json_encode( $ajax_url ) . ';',
            'before'
        );

        wp_enqueue_script( 'mdirector-public' );
    }

}

