<?php

defined('ABSPATH') || exit;

/**
 * Status class
 * Класс статусов
 *
 * Class Roles
 *
 * @version 6.4.0
 */
class BfwRoles
{

    /**
     * Adding status
     * Добавления статуса
     *
     * @param $name string
     * @param float $percent
     * @param $summaStart float
     *
     * @return string
     * @version 6.4.3
     */
    public static function addRole(string $name, float $percent, float $summaStart): string
    {
        global $wpdb;
        // Удаление лишних преобразований
        $slug = trim(preg_replace("/\s+/", ' ', wp_strip_all_tags($name)));
        $slug = function_exists('mb_strtolower') ? mb_strtolower($slug) : strtolower($slug);
        $slug = str_replace(" ", "-", $slug);

        // Транслитерация
        $transliterationMap = array(
            'а' => 'a',
            'б' => 'b',
            'в' => 'v',
            'г' => 'g',
            'д' => 'd',
            'е' => 'e',
            'ё' => 'e',
            'ж' => 'j',
            'з' => 'z',
            'и' => 'i',
            'й' => 'y',
            'к' => 'k',
            'л' => 'l',
            'м' => 'm',
            'н' => 'n',
            'о' => 'o',
            'п' => 'p',
            'р' => 'r',
            'с' => 's',
            'т' => 't',
            'у' => 'u',
            'ф' => 'f',
            'х' => 'h',
            'ц' => 'c',
            'ч' => 'ch',
            'ш' => 'sh',
            'щ' => 'shch',
            'ы' => 'y',
            'э' => 'e',
            'ю' => 'yu',
            'я' => 'ya',
            'ъ' => '',
            'ь' => ''
        );

        $slug = strtr($slug, $transliterationMap);
        $table_name = $wpdb->prefix . 'bfw_computy';

        // Проверка существующего имени
        $existing_name = $wpdb->get_var($wpdb->prepare("SELECT name FROM $table_name WHERE name = %s", $name));

        $existing_sumaStart = $wpdb->get_row($wpdb->prepare("SELECT summa_start, name FROM $table_name WHERE summa_start = %s",
            $summaStart));
        $message = '';
        $message_type = 'bfw-notice-warning';
        if (!empty($existing_name)) {
            $message = __('Status',
                    'bonus-for-woo') . ' «' . esc_html($name) . '» ' . __('is already in use. Please enter another status name.',
                    'bonus-for-woo');
        } elseif ($summaStart < 0) {
            $message = __('The accumulated amount cannot be less than 0', 'bonus-for-woo');
        } elseif (empty($name) || empty($slug)) {
            $message = __('The status name cannot be empty.', 'bonus-for-woo');
        } elseif ($existing_sumaStart) {
            $message = sprintf(__('This amount of orders is in the <b>%s</b> status, change it to another amount.',
                'bonus-for-woo'), $existing_sumaStart->name);
        } else {
            $inserted = $wpdb->insert($table_name,
                array('name' => $name, 'slug' => $slug, 'percent' => $percent, 'summa_start' => $summaStart),
                array("%s", "%s", "%s", "%s"));
            if (!$inserted) {
                $message_type = 'bfw-notice-error';
                $message = __('Error adding status. Please try again.', 'bonus-for-woo');
            }else{
                $message_type = 'bfw-notice-success';
                $message = __('Status', 'bonus-for-woo') . ' «' . esc_html($name) . '» ' . __('added', 'bonus-for-woo') . '.';
            }
        }

        return '<div class="bfw-notice ' . esc_attr($message_type) . '"><span class="dashicons dashicons-yes-alt"></span>  ' . wp_kses_post($message) . '</div>';

    }


    /**
     * Обновление статуса админом
     *
     * @param string $name
     * @param float $percent
     * @param float $summaStart
     *
     * @return string
     * @version 6.4.3
     */
    public static function updateStatus(string $name, float $percent, float $summaStart, int $id): string
    {
        global $wpdb;
        $updated = $wpdb->update($wpdb->prefix . "bfw_computy",
            array('name'=>$name, 'percent' => $percent, 'summa_start' => $summaStart), array('id' => $id));

        if ($updated === false) {
            return '<div   class="bfw-notice bfw-notice-error is-dismissible"><p>' . __('Error updating status. Please try again.',
                    'bonus-for-woo') . '</p></div>';
        }

        return '<div class="bfw-notice bfw-notice-success"><span class="dashicons dashicons-yes-alt"></span> '. __('Status',
                'bonus-for-woo') . ' «' . esc_html($_POST['name_role']) . '» ' . __('updated','bonus-for-woo').'</div>';
    }


    /**
     * Удаление статуса
     *
     * @param int $id
     *
     * @return void
     * @version 6.4.3
     */
    public static function deleteStatus(int $id): void
    {
        global $wpdb;
        $table_name = $wpdb->prefix . 'bfw_computy';
        $wpdb->query($wpdb->prepare("DELETE FROM {$table_name} WHERE id = %d", $id));
    }

    /**
     * Display all statuses
     * Вывод всех статусов
     *
     * @return mixed
     * @version 6.4.0
     */
    public static function getRoles()
    {
        global $wpdb;
        return $wpdb->get_results("SELECT id,name,slug,percent,summa_start FROM  {$wpdb->prefix}bfw_computy ORDER BY summa_start + 0 asc");
    }


    /**
     * Display user status
     * Вывод статуса пользователя
     *
     * @param int $userId
     *
     * @return array
     * @version 6.3.5
     */
    public static function getRole(int $userId): array
    {
        global $wpdb;
        $status_id = get_user_meta($userId, 'bfw_status', true);
        $user_info = get_userdata($userId);
        if (empty($user_info)) {
            return ['name' => __('User deleted', 'bonus-for-woo'), 'percent' => 0, 'slug' => 'no_status'];
        }

        // Получаем первую роль пользователя безопасно
        $roles = is_array($user_info->roles) ? $user_info->roles : [];
        $role = reset($roles); // получаем первую роль


        $exclude_role = BfwSetting::get('exclude-role', array());

        if (in_array($role, (array)$exclude_role) || empty($status_id)) {
            return ['name' => __('No status', 'bonus-for-woo'), 'percent' => 0, 'slug' => 'no_status'];
        }


        $cache_key = 'bfw_computy_role_'.$status_id;
        $you_role = wp_cache_get($cache_key);
        if (false === $you_role) {
            $you_role = $wpdb->get_row($wpdb->prepare("SELECT name, percent, slug FROM {$wpdb->prefix}bfw_computy WHERE id = %d",
                $status_id));
            wp_cache_set($cache_key, $you_role, '', HOUR_IN_SECONDS);
        }



        return apply_filters('bfw_get_role_filter', [
            'name' => $you_role->name ?? __('Client', 'bonus-for-woo'),
            'percent' => $you_role->percent ?? 0,
            'slug' => $you_role->slug ?? 'client'
        ], $userId, $status_id);
    }


    /**
     * Method to update user status
     * Метод обновления статуса пользователя
     * (только для участников бонусной программы)
     *
     * @param int $userId
     * @param bool $sendEmail
     * @param bool $nocache true - удалить кеш
     * @return void
     * @version 6.3.4
     */
    public static function updateRole(int $userId, bool $sendEmail = true, $nocache = false): void
    {
        $total_all = BfwPoints::getSumUserOrders($userId,$nocache);
        global $wpdb;
        $allrole = $wpdb->get_results("SELECT id, name, percent, summa_start FROM " . $wpdb->prefix . "bfw_computy ORDER BY summa_start+0 ASC");
        if (!empty($allrole)) {
            $status_id = null;
            $status_name = null;
            $status_percent = null;
            foreach ($allrole as $bfw) {
                if ($total_all >= $bfw->summa_start) {
                    $status_id = $bfw->id;
                    $status_name = $bfw->name;
                    $status_percent = $bfw->percent;
                } else {
                    break;
                }
            }
            if (!empty($status_id)) {
                if ((int)$status_id !== (int)get_user_meta($userId, 'bfw_status', true)) {
                    update_user_meta($userId, 'bfw_status', $status_id);

                    // Добавляем лог
                    BfwLogs::addLog('status_change', $userId, sprintf(__('Status changed to: %s', 'bonus-for-woo'), $status_name));

                    if (BfwSetting::get('email-when-status-chenge') && !empty($sendEmail)) {
                        $text_email = BfwSetting::get('email-when-status-chenge-text', '');
                        $title_email = BfwSetting::get('email-when-status-chenge-title',
                            __('Changing your status', 'bonus-for-woo'));
                        $user = get_userdata($userId);
                        $get_referral = get_user_meta($userId, 'bfw_points_referral', true);
                        $text_email_array = [
                            '[referral-link]' => esc_url(site_url() . '?bfwkey=' . $get_referral),
                            '[user]' => $user->display_name,
                            '[role]' => $status_name,
                            '[cashback]' => $status_percent
                        ];
                        $message_email = BfwEmail::template($text_email, $text_email_array);
                        (new BfwEmail())->getMail($userId, '', $title_email, $message_email);
                    }
                }
            } else {
                delete_user_meta($userId, 'bfw_status');
            }


        }
    }


    /**
     * How much money do you need to spend before reaching the next status?
     * Сколько надо потратить денег до следующего статуса
     *
     * @param int $userId
     *
     * @return array
     * @version 8.1.3
     */
    public static function getNextRole(int $userId): array
    {
        global $wpdb;

        static $statuses_cache = null;

        // Кэшируем статусы в статической переменной для всех вызовов
        if ($statuses_cache === null) {
            $statuses_cache = $wpdb->get_results(
                "SELECT name, percent, summa_start 
             FROM " . $wpdb->prefix . "bfw_computy 
             ORDER BY CAST(summa_start AS DECIMAL) ASC",
                ARRAY_A
            );
        }

        // Быстрая проверка на пустые данные
        if (empty($statuses_cache)) {
            return ['status' => 'no'];
        }

        $total_all = max(BfwPoints::getSumUserOrders($userId), 0);

        // Ищем следующий статус через бинарный поиск (если summa_start уникальны и отсортированы)
        $next_status_index = null;
        foreach ($statuses_cache as $index => $status) {
            if ($total_all < (float)$status['summa_start']) {
                $next_status_index = $index;
                break;
            }
        }

        // Если статус не найден - достигнут максимум
        if ($next_status_index === null) {
            return ['status' => 'max'];
        }

        $next = $statuses_cache[$next_status_index];
        $summa = (float)$next['summa_start'];
        $ostatok = $summa - $total_all;

        return [
            'percent-zarabotannogo' => ($summa > 0) ? 100 * $total_all / $summa : 0,
            'sum' => $ostatok,
            'name' => $next['name'],
            'percent' => $next['percent'],
            'status' => 'next'
        ];
    }


    /**
     * Checking whether the user is participating in the bonus system
     * Проверка участвует ли пользователь в бонусной системе
     *
     * @param int $userId
     *
     * @return bool
     * @version 8.1.3
     */
    public static function isInvalve(int $userId): bool
    {
        static $exclude_roles = null;
        static $cache = [];

        // Проверка кэша
        if (isset($cache[$userId])) {
            return $cache[$userId];
        }


        // Инициализация исключенных ролей один раз
        if ($exclude_roles === null) {
            $exclude_roles = (array) BfwSetting::get('exclude-role', []);
        }


        if ($userId === 0) {
            return $cache[$userId] = false;
        }

        // Быстрая проверка - если нет исключенных ролей, все участвуют
        if (empty($exclude_roles)) {
            return $cache[$userId] = true;
        }

        $user = get_user_by('id', $userId);
        if (!$user || empty($user->roles)) {
            return $cache[$userId] = false;
        }

        return $cache[$userId] = !array_intersect($user->roles, $exclude_roles);
    }



    /**
     * Check for pro
     * Проверка на про
     *
     * @return bool
     * @version 6.3.4
     */
    public static function isPro(): bool
    {
        return get_option(base64_decode('Ym9udXMtZm9yLXdvby1wcm8=')) === base64_decode('YWN0aXZl');
    }


    /**
     * Find the maximum percentage of statuses
     * Находим максимальный процент статусов
     *
     * @return float
     * @version 6.3.4
     */
    public static function maxPercent(): float
    {
        global $wpdb;
        return (float)($wpdb->get_var(
            "SELECT MAX(percent) FROM {$wpdb->prefix}bfw_computy"
        ) ?? 0.0);
    }


    /**
     * Ability for managers to customize the plugin
     * Возможность менеджерам настраивать плагин
     *
     * @param $roles
     *
     * @return array
     * @version 6.3.4
     */
    public static function bfwManagerRoleEditCapabilities($roles): array
    {
        global $wpdb;
        $table_bfw = $wpdb->get_results("SELECT slug FROM {$wpdb->prefix}bfw_computy ORDER BY summa_start + 0 ASC");

        foreach ($table_bfw as $bfw) {
            $roles[] = $bfw->slug;
        }

        return array_merge($roles, ['subscriber', 'customer']);
    }

}
