<?php

/**
 * Class for creating shortcodes.
 * copyright Simple Direct Plugins - support@simpledirectplugins.com
 *
 * @author 					Simple Direct Plugins
 * @link					https://simpledirectplugins.com/
 * @since					1.0.0
 * @package					SMATWoo
 *
 */

defined ('ABSPATH') or exit;

if (!class_exists ('SMAT_Shortcodes')) :

	#[AllowDynamicProperties]

	Class SMAT_Shortcodes {

        private $customer = null;

		public function __construct () {

            foreach ($this->get_all_shortcodes()['tabs'] as $integration)
                foreach ($integration['shortcodes'] as $sc)
                    add_shortcode ($sc['id'], [$this, 'handle_shortcode']);
            }

        public static function get_all_shortcodes(): array {

            $all_shortcodes = [
                'tabs' => [
                    'wp' => [
                        'label'         => esc_html__('WordPress', 'default'),
                        'shortcodes'    => [
                            ['id' => 'smat_wp_username', 'label' => esc_html__('Username', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_wp_first_name', 'label' => esc_html__('First name', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_wp_last_name', 'label' => esc_html__('Last name', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_wp_nickname', 'label' => esc_html__('Nickname', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_wp_display_name', 'label' => esc_html__('Display name', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_wp_user_email', 'label' => esc_html__('User email', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_wp_user_website', 'label' => esc_html__('User website', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_wp_user_bio', 'label' => esc_html__('User bio', 'sdp-my-account-tabs-for-woocommerce')],
                            [
                                'id'    => 'smat_wp_profile_picture',
                                'label' => esc_html__('Profile picture', 'sdp-my-account-tabs-for-woocommerce'),
                                'atts'  => [
                                    'size' => [
                                        'label'   => esc_html__('Size', 'sdp-my-account-tabs-for-woocommerce'),
                                        'default' => 100,
                                        'type'    => 'number',
                                        'min'     => 10,
                                        'max'     => 500,
                                        ],
                                    ],
                                ],
                            ['id' => 'smat_wp_user_role', 'label' => esc_html__('User role', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_wp_registration_date', 'label' => esc_html__('Registration date', 'sdp-my-account-tabs-for-woocommerce')],
                            [
                                'id'    => 'smat_wp_user_meta',
                                'label' => esc_html__('User meta', 'sdp-my-account-tabs-for-woocommerce'),
                                'atts'  => [
                                    'key' => [
                                        'label'   => esc_html__('Key', 'sdp-my-account-tabs-for-woocommerce'),
                                        'default' => '',
                                        'type'    => 'text',
                                        ],
                                    ],
                                ], 
                            ],
                        ],

                    'woo' => [
                        'label'         => esc_html__('WooCommerce', 'woocommerce'),
                        'shortcodes'    => [
                            ['id' => 'smat_woo_customer_email', 'label' => esc_html__('Customer email', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_woo_billing_first_name', 'label' => esc_html__('Billing first name', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_woo_billing_last_name', 'label' => esc_html__('Billing last name', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_woo_billing_company', 'label' => esc_html__('Billing company', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_woo_billing_address_1', 'label' => esc_html__('Billing address 1', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_woo_billing_address_2', 'label' => esc_html__('Billing address 2', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_woo_billing_postcode', 'label' => esc_html__('Billing postcode', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_woo_billing_city', 'label' => esc_html__('Billing city', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_woo_billing_state', 'label' => esc_html__('Billing state', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_woo_billing_country', 'label' => esc_html__('Billing country', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_woo_billing_phone', 'label' => esc_html__('Billing phone', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'hr'],
                            ['id' => 'smat_woo_shipping_first_name', 'label' => esc_html__('Shipping first name', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_woo_shipping_last_name', 'label' => esc_html__('Shipping last name', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_woo_shipping_company', 'label' => esc_html__('Shipping company', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_woo_shipping_address_1', 'label' => esc_html__('Shipping address 1', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_woo_shipping_address_2', 'label' => esc_html__('Shipping address 2', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_woo_shipping_postcode', 'label' => esc_html__('Shipping postcode', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_woo_shipping_city', 'label' => esc_html__('Shipping city', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_woo_shipping_state', 'label' => esc_html__('Shipping state', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_woo_shipping_country', 'label' => esc_html__('Shipping country', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_woo_shipping_phone', 'label' => esc_html__('Shipping phone', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'hr'],
                            [
                                'id'      => 'smat_woo_last_order_date',
                                'label'   => esc_html__('Last order date', 'sdp-my-account-tabs-for-woocommerce'),
                                'tooltip' => esc_html__('Supports filters to modify which statuses are excluded before rendering the output.', 'sdp-my-account-tabs-for-woocommerce'),
                                ],
                            [
                                'id'      => 'smat_woo_last_order_total',
                                'label'   => esc_html__('Last order total', 'sdp-my-account-tabs-for-woocommerce'),
                                'tooltip' => esc_html__('Supports filters to modify which statuses are excluded before rendering the output.', 'sdp-my-account-tabs-for-woocommerce'),
                                ],
                            [
                                'id'      => 'smat_woo_last_order_id',
                                'label'   => esc_html__('Last order ID', 'sdp-my-account-tabs-for-woocommerce'),
                                'tooltip' => esc_html__('Supports filters to modify which statuses are excluded before rendering the output.', 'sdp-my-account-tabs-for-woocommerce'),
                                'atts'    => [
                                    'link' => [
                                        'label'     => esc_html__('Include link', 'sdp-my-account-tabs-for-woocommerce'),
                                        'default'   => 'no',
                                        'options'   => [
                                            'yes'   => esc_html__('Yes', 'default'),
                                            'no'    => esc_html__('No', 'default'),
                                            ],
                                        ],
                                    ],
                                ],
                            [
                                'id'      => 'smat_woo_purchased_products',
                                'label'   => esc_html__('Purchased products', 'sdp-my-account-tabs-for-woocommerce'),
                                'tooltip' => esc_html__('Supports filters to modify which statuses are excluded before rendering the output.', 'sdp-my-account-tabs-for-woocommerce'),
                                'atts'    => [
                                    'limit' => [
                                        'label'   => esc_html__('Quantity', 'sdp-my-account-tabs-for-woocommerce'),
                                        'default' => 4,
                                        'type'    => 'number',
                                        'min'     => 1,
                                        'max'     => 50,
                                        ],
                                    ],
                                ],
                            ['id' => 'smat_woo_number_orders', 'label' => esc_html__('Number of orders', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_woo_total_spent', 'label' => esc_html__('Total spent', 'sdp-my-account-tabs-for-woocommerce')],
                            [
                                'id'        => 'smat_woo_orders_table',
                                'label'     => esc_html__('Orders table', 'sdp-my-account-tabs-for-woocommerce'),
                                'tooltip'   => esc_html__('Displaying a large number of orders may slow down the My Account page, especially for customers with many orders.', 'sdp-my-account-tabs-for-woocommerce'),
                                'atts'  => [
                                    'limit' => [
                                        'label'   => esc_html__('Maximum number of orders to display', 'sdp-my-account-tabs-for-woocommerce'),
                                        'default' => 20,
                                        'type'    => 'number',
                                        'min'     => 1,
                                        ],
                                    ],
                                ],
                            ['id' => 'smat_woo_downloads_table', 'label' => esc_html__('Downloads table', 'sdp-my-account-tabs-for-woocommerce')],
                            ['id' => 'smat_woo_coupons', 'label' => esc_html__('Available coupons', 'sdp-my-account-tabs-for-woocommerce')],
                            ],
                        ],

                    'subscriptions' => [
                        'label'         => esc_html__('Subscriptions', 'sdp-my-account-tabs-for-woocommerce') . ' <span class="smat-pro">PRO</span>',
                        // translators: link to SPD My Account Tabs Pro and closing tag.
                        'message'       => sprintf (esc_html__('WooCommerce Subscriptions integration is available in %1$sSDP My Account Tabs Pro%2$s', 'sdp-my-account-tabs-for-woocommerce'), '<a target="_blank" href="' . SMAT_PRO_LINK . '">', '</a>') . ' <a style="text-decoration:none" target="_blank" href="' . SMAT_PRO_LINK . '"><span class="dashicons dashicons-external"></span></a>',
                        'shortcodes'    => [],
                        ],

                    'memberships' => [
                        'label'         => esc_html__('Memberships', 'sdp-my-account-tabs-for-woocommerce') . ' <span class="smat-pro">PRO</span>',
                        // translators: link to SPD My Account Tabs Pro and closing tag.
                        'message'       => sprintf (esc_html__('WooCommerce Memberships integration is available in %1$sSDP My Account Tabs Pro%2$s', 'sdp-my-account-tabs-for-woocommerce'), '<a target="_blank" href="' . SMAT_PRO_LINK . '">', '</a>') . ' <a style="text-decoration:none" target="_blank" href="' . SMAT_PRO_LINK . '"><span class="dashicons dashicons-external"></span></a>',
                        'shortcodes'    => [],
                        ],

                    'bookings' => [
                        'label'         => esc_html__('Bookings', 'sdp-my-account-tabs-for-woocommerce') . ' <span class="smat-pro">PRO</span>',
                        // translators: link to SPD My Account Tabs Pro and closing tag.
                        'message'       => sprintf (esc_html__('WooCommerce Bookings integration is available in %1$sSDP My Account Tabs Pro%2$s', 'sdp-my-account-tabs-for-woocommerce'), '<a target="_blank" href="' . SMAT_PRO_LINK . '">', '</a>') . ' <a style="text-decoration:none" target="_blank" href="' . SMAT_PRO_LINK . '"><span class="dashicons dashicons-external"></span></a>',
                        'shortcodes'    => [],
                        ],

                    'euvat' => [
                        'label'         => esc_html__('EU VAT Number', 'sdp-my-account-tabs-for-woocommerce') . ' <span class="smat-pro">PRO</span>',
                        // translators: link to SPD My Account Tabs Pro and closing tag.
                        'message'       => sprintf (esc_html__('WooCommerce EU VAT Number integration is available in %1$sSDP My Account Tabs Pro%2$s', 'sdp-my-account-tabs-for-woocommerce'), '<a target="_blank" href="' . SMAT_PRO_LINK . '">', '</a>') . ' <a style="text-decoration:none" target="_blank" href="' . SMAT_PRO_LINK . '"><span class="dashicons dashicons-external"></span></a>',
                        'shortcodes'    => [],
                        ],

                    'buddypress' => [
                        'label'         => esc_html__('BuddyPress', 'buddypress') . ' <span class="smat-pro">PRO</span>',
                        // translators: link to SPD My Account Tabs Pro and closing tag.
                        'message'       => sprintf (esc_html__('BuddyPress integration is available in %1$sSDP My Account Tabs Pro%2$s', 'sdp-my-account-tabs-for-woocommerce'), '<a target="_blank" href="' . SMAT_PRO_LINK . '">', '</a>') . ' <a style="text-decoration:none" target="_blank" href="' . SMAT_PRO_LINK . '"><span class="dashicons dashicons-external"></span></a>',
                        'shortcodes'    => [],
                        ],
                    ],

                'title'     => esc_html__('SMAT Shortcodes', 'sdp-my-account-tabs-for-woocommerce'),
                'insert'    => esc_html__('Insert', 'sdp-my-account-tabs-for-woocommerce'),
                'cancel'    => esc_html__('Cancel', 'default'),
                'width'     => apply_filters ('smat_shortcodes_modal_width', wp_is_mobile() ? 300 : 700),
                'height'    => apply_filters ('smat_shortcodes_modal_height', 650),
                ];

            if (!function_exists ('is_plugin_active'))
                require_once ABSPATH . 'wp-admin/includes/plugin.php';

            // Unset useless tabs.
            $plugins = [
                'subscriptions' => 'woocommerce-subscriptions/woocommerce-subscriptions.php',
                'memberships'   => 'woocommerce-memberships/woocommerce-memberships.php',
                'bookings'      => 'woocommerce-bookings/woocommerce-bookings.php',
                'euvat'         => 'woocommerce-eu-vat-number/woocommerce-eu-vat-number.php',
                'buddypress'    => 'buddypress/bp-loader.php',
                ];

            foreach ($plugins as $tab => $plugin)
                if (!is_plugin_active ($plugin))
                    unset ($all_shortcodes['tabs'][$tab]);

            return $all_shortcodes;
            }

        public function handle_shortcode ($atts = [], $content = null, $tag = '') {

            $atts = (array) $atts;

            return $this->return_data($tag, $atts, $content);
            }

        private function return_data ($shortcode, array $atts = [], $content = null) {

            if (!$user = wp_get_current_user())
                return apply_filters ('smat_shortcode_guest', '', ['shortcode' => $shortcode, 'atts' => $atts]);

            $this->empty = apply_filters ('smat_shortcode_empty', '', ['shortcode' => $shortcode, 'atts' => $atts, 'user_id' => $user->ID]);

            $method = 'render_' . str_replace ('smat_', '', $shortcode);

            if (method_exists ($this, $method))
                return $this->$method($user, $atts, $content);
 
            return $this->empty;
            }

        private function render_wp_username ($user, $atts, $content) {

            return esc_html ($user->user_login);
            }

        private function render_wp_first_name ($user, $atts, $content) {
            
            return esc_html (get_user_meta ($user->ID, 'first_name', true));
            }

        private function render_wp_last_name ($user, $atts, $content) {

            return esc_html (get_user_meta ($user->ID, 'last_name', true));
            }

        private function render_wp_nickname ($user, $atts, $content) {

            return esc_html (get_user_meta ($user->ID, 'nickname', true));
            }

        private function render_wp_display_name ($user, $atts, $content) {
            
            return esc_html ($user->display_name);
            }

        private function render_wp_user_email ($user, $atts, $content) {
            
            return esc_html ($user->user_email);
            }

        private function render_wp_user_website ($user, $atts, $content) {
            
            return esc_html ($user->user_url);
            }

        private function render_wp_user_bio ($user, $atts, $content) {
            
            return esc_html (get_user_meta ($user->ID, 'description', true));
            }

        private function render_wp_profile_picture ($user, $atts, $content) {
            
            $atts = shortcode_atts([
                'size' => 100,
                ], $atts);

            $default = apply_filters ('smat_profile_picture_default_image', false, ['shortcode' => 'smat_wp_profile_picture', 'atts' => $atts, 'user_id' => $user->ID]);

            return get_avatar ($user->ID, absint ($atts['size']), esc_url ($default), esc_html ($user->display_name), [
                'class' => 'smat-gravatar',
                ]);
            }

        private function render_wp_user_role ($user, $atts, $content) {

            global $wp_roles;

            $role = reset ($user->roles);

            if ($role && isset ($wp_roles->roles[$role]))
                return esc_html (translate_user_role ($wp_roles->roles[$role]['name']) ?? $wp_roles->roles[$role]['name']);

            return $this->empty;
            }

        private function render_wp_registration_date ($user, $atts, $content) {

            if (!$timestamp = strtotime ($user->user_registered))
                return $this->empty;

            return apply_filters ('smat_user_registered_format', wp_date (get_option ('date_format'), $timestamp), ['shortcode' => 'smat_wp_registration_date', 'atts' => $atts, 'user_id' => $user->ID]);
            }

        private function render_wp_user_meta ($user, $atts, $content) {
            
            $atts = shortcode_atts ([
                'key' => '',
                ], $atts);

            if (empty ($atts['key']))
                return $this->empty;

            return get_user_meta ($user->ID, $atts['key'], true) ?: $this->empty;
            }

        private function render_woo_customer_email ($user, $atts, $content) {

            $customer = $this->get_customer($user);

            return esc_html ($customer->get_billing_email());
            }

        private function render_woo_billing_first_name ($user, $atts, $content) {

            $customer = $this->get_customer($user);

            return esc_html ($customer->get_billing_first_name());
            }

        private function render_woo_billing_last_name ($user, $atts, $content) {

            $customer = $this->get_customer($user);

            return esc_html ($customer->get_billing_last_name());
            }

        private function render_woo_billing_company ($user, $atts, $content) {

            $customer = $this->get_customer($user);

            return esc_html ($customer->get_billing_company());
            }

        private function render_woo_billing_address_1 ($user, $atts, $content) {

            $customer = $this->get_customer($user);
            return esc_html ($customer->get_billing_address_1());
            }

        private function render_woo_billing_address_2 ($user, $atts, $content) {

            $customer = $this->get_customer($user);

            return esc_html ($customer->get_billing_address_2());
            }

        private function render_woo_billing_postcode ($user, $atts, $content) {

            $customer = $this->get_customer($user);

            return esc_html ($customer->get_billing_postcode());
            }

        private function render_woo_billing_city ($user, $atts, $content) {

            $customer = $this->get_customer($user);

            return esc_html ($customer->get_billing_city());
            }

        private function render_woo_billing_state ($user, $atts, $content) {

            $customer = $this->get_customer($user);
            $states   = WC()->countries->get_states();
            $state    = $customer->get_billing_state();
            $country  = $customer->get_billing_country();

            return esc_html ($states[$country][$state] ?? $state);
            }

        private function render_woo_billing_country ($user, $atts, $content) {

            $customer = $this->get_customer($user);
            $country  = $customer->get_billing_country();

            return esc_html (WC()->countries->countries[$country] ?? $country);
            }

        private function render_woo_billing_phone ($user, $atts, $content) {

            $customer = $this->get_customer($user);

            return esc_html ($customer->get_billing_phone());
            }

        private function render_woo_shipping_first_name ($user, $atts, $content) {

            $customer = $this->get_customer($user);

            return esc_html ($customer->get_shipping_first_name());
            }

        private function render_woo_shipping_last_name ($user, $atts, $content) {

            $customer = $this->get_customer($user);

            return esc_html ($customer->get_shipping_last_name());
            }

        private function render_woo_shipping_company ($user, $atts, $content) {

            $customer = $this->get_customer($user);

            return esc_html ($customer->get_shipping_company());
            }

        private function render_woo_shipping_address_1 ($user, $atts, $content) {

            $customer = $this->get_customer($user);

            return esc_html ($customer->get_shipping_address_1());
            }

        private function render_woo_shipping_address_2 ($user, $atts, $content) {

            $customer = $this->get_customer($user);

            return esc_html ($customer->get_shipping_address_2());
            }

        private function render_woo_shipping_postcode ($user, $atts, $content) {

            $customer = $this->get_customer($user);

            return esc_html ($customer->get_shipping_postcode());
            }

        private function render_woo_shipping_city ($user, $atts, $content) {

            $customer = $this->get_customer($user);

            return esc_html ($customer->get_shipping_city());
            }

        private function render_woo_shipping_state ($user, $atts, $content) {

            $customer = $this->get_customer($user);
            $states   = WC()->countries->get_states();
            $state    = $customer->get_shipping_state();
            $country  = $customer->get_shipping_country();

            return esc_html ($states[$country][$state] ?? $state);
            }

        private function render_woo_shipping_country ($user, $atts, $content) {

            $customer = $this->get_customer($user);
            $country  = $customer->get_shipping_country();

            return esc_html (WC()->countries->countries[$country] ?? $country);
            }

        private function render_woo_shipping_phone ($user, $atts, $content) {

            $customer = $this->get_customer($user);
            return esc_html ($customer->get_shipping_phone());
            }
            
        private function render_woo_last_order_date ($user, $atts, $content) {

            $exclude = apply_filters ('smat_exclude_woo_statuses', ['wc-refunded', 'wc-failed', 'wc-cancelled', 'trash', 'draft'], ['shortcode' => 'smat_woo_last_order_date', 'atts' => $atts, 'user_id' => $user->ID]);
            $args    = [
                'customer_id' => $user->ID,
                'limit'       => 1,
                'status'      => array_values (array_diff (array_keys (wc_get_order_statuses()), is_array ($exclude) ? $exclude : [])),
                'orderby'     => 'date',
                'order'       => 'DESC',
                'return'      => 'ids',
                ];

            if (empty ($orders = wc_get_orders ($args)))
                return $this->empty;

            $order = wc_get_order ($orders[0]);

            if ($date_created = $order->get_date_created())
                return wp_date (get_option ('date_format'), ($date_created->getTimestamp()));

            return $this->empty;
            }

        private function render_woo_last_order_total ($user, $atts, $content) {

            $exclude = apply_filters ('smat_exclude_woo_statuses', ['wc-refunded', 'wc-failed', 'wc-cancelled', 'trash', 'draft'], ['shortcode' => 'smat_woo_last_order_total', 'atts' => $atts, 'user_id' => $user->ID]);
            $args    = [
                'customer_id' => $user->ID,
                'limit'       => 1,
                'status'      => array_values (array_diff (array_keys (wc_get_order_statuses()), is_array ($exclude) ? $exclude : [])),
                'orderby'     => 'date',
                'order'       => 'DESC',
                'return'      => 'ids',
                ];

            if (empty ($orders = wc_get_orders ($args)))
                return $this->empty;

            if (!$order = wc_get_order ($orders[0]))
                return $this->empty;

            return wc_price ($order->get_total());
            }

        private function render_woo_last_order_id ($user, $atts, $content) {

            $exclude = apply_filters ('smat_exclude_woo_statuses', ['wc-refunded', 'wc-failed', 'wc-cancelled', 'trash', 'draft'], ['shortcode' => 'smat_woo_last_order_id', 'atts' => $atts, 'user_id' => $user->ID]);
            $args    = [
                'customer_id' => $user->ID,
                'limit'       => 1,
                'status'      => array_values (array_diff (array_keys (wc_get_order_statuses()), is_array ($exclude) ? $exclude : [])),
                'orderby'     => 'date',
                'order'       => 'DESC',
                'return'      => 'ids',
                ];

            if (empty ($orders = wc_get_orders ($args)))
                return $this->empty;

            $order_id = $orders[0];
            
            $atts = shortcode_atts ([
                'link' => 'no', // 'yes' || 'no'
                ], $atts);

            if ('yes' === $atts['link']) {

                if (!$order = wc_get_order ($order_id))
                    return $this->empty;

                return sprintf ('<a href="%s">%s</a>', esc_url ($order->get_view_order_url()), esc_html ($order_id));
                }

            return esc_html ($order_id);
            }

        private function render_woo_purchased_products ($user, $atts, $content) {
            
            $atts = shortcode_atts([
                'limit' => 4,
                ], $atts);

            $limit_products = absint ($atts['limit']);

            if (!$limit_products)
                return $this->empty;

            $exclude = apply_filters ('smat_exclude_woo_statuses', ['wc-refunded', 'wc-failed', 'wc-cancelled', 'trash', 'draft'], ['shortcode' => 'smat_woo_purchased_products', 'atts' => $atts, 'user_id' => $user->ID]);
            $args    = [
                'customer_id' => $user->ID,
                'limit'       => 1,
                'status'      => array_values (array_diff (array_keys (wc_get_order_statuses()), is_array ($exclude) ? $exclude : [])),
                'limit'       => 50, 
                'orderby'     => 'date',
                'order'       => 'DESC',
                'return'      => 'ids',
                ];

            $order_ids = wc_get_orders ($args);

			if (!$order_ids)
				return $this->empty;

            $product_ids = [];

			foreach ($order_ids as $order_id) {

                $order = wc_get_order ($order_id);

				foreach ($order->get_items() as $item) {

					$product_ids[] = $item->get_product_id();
                    $product_ids = array_unique ($product_ids);

                    if (count ($product_ids) >= $limit_products)
                        break 2;
                    }
                }

            return wp_kses_post (do_shortcode (sprintf ('[products ids="%s"]', implode (',', $product_ids))));
            }

        private function render_woo_number_orders ($user, $atts, $content) {

            return wc_get_customer_order_count ($user->ID);
            }

        private function render_woo_total_spent ($user, $atts, $content) {

            $amount   = wc_get_customer_total_spent ($user->ID);
            $formated = apply_filters ('smat_woo_total_spent_apply_format', true);

            return $formated ? wc_price ($amount) : $amount;
            }

        private function render_woo_orders_table ($user, $atts, $content) {
            
            $atts = shortcode_atts([
                'limit' => 20,
                ], $atts);

            if (!$orders = wc_get_orders (
				[
					'customer_id' 	=> $user->ID,
					'post_type'   	=> wc_get_order_types(),
					'post_status'	=> array_keys (wc_get_order_statuses()),
					'numberposts'	=> $atts['limit'],
					]
				)) return sprintf ('<div class="woocommerce-message woocommerce-message--info woocommerce-Message woocommerce-Message--info woocommerce-info smat-orders-table-message">%s <a class="woocommerce-Button button" href="%s">%s</a></div>', esc_html__('No order has been made yet.', 'sdp-my-account-tabs-for-woocommerce'), esc_url (get_permalink (wc_get_page_id ('shop'))), esc_html__('Browse products', 'sdp-my-account-tabs-for-woocommerce'));

            $table = sprintf ('<table class="woocommerce-orders-table woocommerce-MyAccount-orders shop_table shop_table_responsive my_account_orders account-orders-table smat-orders-table">
                <thead>
                    <tr>
						<th class="woocommerce-orders-table__header woocommerce-orders-table__header-order-number"><span class="nobr">%s</span></th>
						<th class="woocommerce-orders-table__header woocommerce-orders-table__header-order-date"><span class="nobr">%s</span></th>
						<th class="woocommerce-orders-table__header woocommerce-orders-table__header-order-status"><span class="nobr">%s</span></th>
						<th class="woocommerce-orders-table__header woocommerce-orders-table__header-order-total"><span class="nobr">%s</span></th>
						<th class="woocommerce-orders-table__header woocommerce-orders-table__header-order-actions"><span class="nobr">%s</span></th>
					</tr>
				</thead>
				<tbody>',
                    esc_html__('Order', 'sdp-my-account-tabs-for-woocommerce'),
                    esc_html__('Date', 'sdp-my-account-tabs-for-woocommerce'),
                    esc_html__('Status', 'sdp-my-account-tabs-for-woocommerce'),
                    esc_html__('Total', 'sdp-my-account-tabs-for-woocommerce'),
                    esc_html__('Actions', 'sdp-my-account-tabs-for-woocommerce')
                    );

                foreach ($orders as $order) {

                    $items   = $order->get_item_count();
                    $date    = $order->get_date_created();
                    $actions = '';

                    foreach (wc_get_account_orders_actions ($order) as $key => $action)
                        $actions .= sprintf ('<a href="%s" class="woocommerce-button button %s">%s</a>', esc_url ($action['url']), $key, $action['name']);

					$table .= sprintf ('
                        <tr class="woocommerce-orders-table__row order">
							<td class="woocommerce-orders-table__cell woocommerce-orders-table__cell-order-number" data-title="%s">
								<a href="%s">#%s</a>
							</td>
							<td class="woocommerce-orders-table__cell woocommerce-orders-table__cell-order-date" data-title="%s">
								<time datetime="%s">%s</time>
							</td>
							<td class="woocommerce-orders-table__cell woocommerce-orders-table__cell-order-status" data-title="%s">%s</td>
							<td class="woocommerce-orders-table__cell woocommerce-orders-table__cell-order-total" data-title="%s">%s</td>
							<td class="woocommerce-orders-table__cell woocommerce-orders-table__cell-order-actions" data-title="%s">%s</td>
						</tr>',
						esc_html__('Order', 'sdp-my-account-tabs-for-woocommerce'),
						esc_url ($order->get_view_order_url()),
						$order->get_id(),
						esc_html__('Date', 'sdp-my-account-tabs-for-woocommerce'),
						$date,
						date_i18n (get_option ('date_format'), strtotime ($date)),
						esc_html__('Status', 'sdp-my-account-tabs-for-woocommerce'),
						wc_get_order_status_name ($order->get_status()),
						esc_html__('Total', 'sdp-my-account-tabs-for-woocommerce'),
                        // translators: 1: total paid for the order; 2: no. of items in the order
						sprintf (esc_html (_n('%1$s for %2$s item', '%1$s for %2$s items', $items, 'sdp-my-account-tabs-for-woocommerce')), wc_price ($order->get_total()), $items),
						esc_html__('Actions', 'sdp-my-account-tabs-for-woocommerce'),
						$actions
						);
                    }

            return $table . '</tbody></table>';
            }

        private function render_woo_downloads_table ($user, $atts, $content) {

            if (!$downloads = wc_get_customer_available_downloads ($user->ID))
                return sprintf ('<div class="woocommerce-message woocommerce-message--info woocommerce-Message woocommerce-Message--info woocommerce-info smat-downloads-table-message">%s <a class="woocommerce-Button button" href="%s">%s</a></div>', esc_html__('No downloads available yet.', 'sdp-my-account-tabs-for-woocommerce'), esc_url (get_permalink (wc_get_page_id ('shop'))), esc_html__('Browse products', 'sdp-my-account-tabs-for-woocommerce'));

            $table = sprintf ('<table class="woocommerce-table woocommerce-table--order-downloads shop_table shop_table_responsive order_details smat-downloads-table">
				<thead>
					<tr>
						<th class="download-product"><span class="nobr">%s</span></th>
						<th class="download-remaining"><span class="nobr">%s</span></th>
						<th class="download-expires"><span class="nobr">%s</span></th>
						<th class="download-file"><span class="nobr">%s</span></th>
					</tr>
				</thead>
				<tbody>',
                    esc_html__('Product', 'sdp-my-account-tabs-for-woocommerce'),
                    esc_html__('Downloads remaining', 'sdp-my-account-tabs-for-woocommerce'),
                    esc_html__('Expires', 'sdp-my-account-tabs-for-woocommerce'),
                    esc_html__('Download', 'sdp-my-account-tabs-for-woocommerce'));

            foreach ($downloads as $download)
				$table .= sprintf ('
					<tr>
						<td class="download-product smat-downloads-table-product" data-title="%s">
							<a href="%s">%s</a>
						</td>
						<td class="download-remaining smat-downloads-table-remaining" data-title="%s">%s</td>
						<td class="download-expires smat-downloads-table-expires" data-title="%s">%s</td>
						<td class="download-file smat-downloads-table-file" data-title="%s">
							<a href="%s" class="woocommerce-MyAccount-downloads-file button alt smat-downloads-table-button">%s</a>
						</td>
					</tr>',
					esc_html__('Product', 'sdp-my-account-tabs-for-woocommerce'),
					$download['product_url'],
					$download['product_name'],
					esc_html__('Downloads remaining', 'sdp-my-account-tabs-for-woocommerce'),
					$download['downloads_remaining'] ? : '∞',
					esc_html__('Expires', 'sdp-my-account-tabs-for-woocommerce'),
					isset ($download['access_expires']) ? date_i18n (get_option ('date_format'), strtotime ($download['access_expires'])) : esc_html__('Never', 'sdp-my-account-tabs-for-woocommerce'),
					esc_html__('Download', 'sdp-my-account-tabs-for-woocommerce'),
					$download['download_url'],
					$download['download_name']
					);

            return $table . '</tbody></table>';
            }

        private function render_woo_coupons ($user, $atts, $content) {

            $customer   = $this->get_customer($user);
            $user_email = $customer->get_billing_email();

            global $wpdb;

            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $coupon_ids = $wpdb->get_col(
                $wpdb->prepare(
                    "SELECT DISTINCT p.ID
                    FROM {$wpdb->posts} p
                    LEFT JOIN {$wpdb->postmeta} pm 
                        ON p.ID = pm.post_id 
                        AND pm.meta_key = 'customer_email'
                    WHERE p.post_type = 'shop_coupon'
                    AND p.post_status = 'publish'
                    AND (
                        pm.meta_value IS NULL
                        OR pm.meta_value = ''
                        OR pm.meta_value LIKE %s
                        )",
                    '%' . $wpdb->esc_like($user_email) . '%'
                    )
                );

            $valid_coupons = [];

            foreach ($coupon_ids as $coupon_id) {

                $coupon = new WC_Coupon($coupon_id);

                if (!$coupon->get_id())
                    continue;

                $expires = $coupon->get_date_expires();

                if ($expires && $expires->getTimestamp() < time())
                    continue;

                $limit = $coupon->get_usage_limit();

                if ($limit && $coupon->get_usage_count() >= $limit)
                    continue;

                $valid_coupons[] = $coupon;
                }

            if (empty ($valid_coupons))
                return apply_filters ('smat_no_coupons_available', '');

            $table = sprintf ('<table class="woocommerce-table woocommerce-table--order-downloads shop_table shop_table_responsive order_details smat-coupons-table">
				<thead>
					<tr>
						<th class="smat-coupons-table-code"><span class="nobr">%s</span></th>
						<th class="smat-coupons-table-desc"><span class="nobr">%s</span></th>
						<th class="smat-coupons-table-discount"><span class="nobr">%s</span></th>
						<th class="smat-coupons-table-remaining"><span class="nobr">%s</span></th>
					</tr>
				</thead>
				<tbody>',
                    esc_html__('Code', 'sdp-my-account-tabs-for-woocommerce'),
                    esc_html__('Description', 'default'),
                    esc_html__('Discount', 'sdp-my-account-tabs-for-woocommerce'),
                    esc_html__('Remaining uses', 'sdp-my-account-tabs-for-woocommerce')
                    );

            foreach ($valid_coupons as $coupon) {

				if ('fixed_cart' == ($type = $coupon->get_discount_type()) || 'fixed_product' == $type)
					$discount = wc_price ($coupon->get_amount());

				else if ('percent' == $type)
					$discount = $coupon->get_amount() . '%';

				$coupon_limit = $coupon->get_usage_limit();
                $user_limit   = $coupon->get_usage_limit_per_user();

                // Uso global restante.
                $remaining_global = $coupon_limit ? max (0, $coupon_limit - $coupon->get_usage_count()) : null;

                $used_by_user = 0;

                if ($user_limit) {

                    foreach ((array) $coupon->get_used_by() as $used)
                        if ((string) $used === (string) $user->ID || strtolower ($used) === strtolower ($user_email))
                            $used_by_user++;

                    $remaining_user = max (0, $user_limit - $used_by_user);
                    }

                else
                    $remaining_user = null;

                if ($remaining_global !== null && $remaining_user !== null)
                    $limit = min ($remaining_global, $remaining_user);

                elseif ($remaining_global !== null)
                    $limit = $remaining_global;

                elseif ($remaining_user !== null)
                    $limit = $remaining_user;

                else
                    $limit = '∞';

				$table .= sprintf ('
					<tr>
						<td class="smat-coupons-table-code" data-title="%s">%s</td>
						<td class="smat-coupons-table-desc" data-title="%s">%s</td>
						<td class="smat-coupons-table-discount" data-title="%s">%s</td>
						<td class="smat-coupons-remaining" data-title="%s">%s</td>
					</tr>',
                    esc_html__('Code', 'sdp-my-account-tabs-for-woocommerce'),
					esc_html ($coupon->get_code()),
                    esc_html__('Description', 'default'),
					wp_kses_post ($coupon->get_description()),
                    esc_html__('Discount', 'sdp-my-account-tabs-for-woocommerce'),
					wp_kses_post ($discount),
                    esc_html__('Remaining uses', 'sdp-my-account-tabs-for-woocommerce'),
					esc_html ($limit)
					);
				}

            return $table . '</tbody></table>';
            }

        private function get_customer (WP_User $user): ? WC_Customer {

            if (null === $this->customer) {

                if (!class_exists ('WC_Customer'))
                    return false;

                $this->customer = new WC_Customer($user->ID);
                }

            return $this->customer;
            }

		}

endif;