<?php

namespace Kanzu\StoreVoiceAI;

// Prevent direct file access.
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

use Kanzu\StoreVoiceAI\Services\Store_Voice_AI_API;

class Call_Widget
{
    public function render()
    {
        if (!is_admin() && !is_shop()) {
            return;
        }
?>
        <div id="retell-wrapper">
            <div id="retell-btn-wrap">
                <div class="ripple-ring"></div>
                <div class="ripple-ring"></div>
                <div class="ripple-ring"></div>

                <button id="retell-btn" aria-label="<?php esc_attr_e('Call us', 'storevoiceai-for-woocommerce'); ?>">
                    <span class="retell-btn__visual">
                        <svg class="icon-phone" xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 24 24" aria-hidden="true">
                            <path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07A19.5 19.5 0 0 1 4.69 12 19.79 19.79 0 0 1 1.61 3.4 2 2 0 0 1 3.6 1.22h3a2 2 0 0 1 2 1.72c.127.96.361 1.903.7 2.81a2 2 0 0 1-.45 2.11L7.91 8.85a16 16 0 0 0 6.29 6.29l.95-.95a2 2 0 0 1 2.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0 1 22 16.92z" />
                        </svg>

                        <span class="icon-spinner" aria-hidden="true"></span>

                        <span id="retell-bars" aria-hidden="true">
                            <span></span><span></span><span></span><span></span><span></span>
                        </span>
                    </span>

                    <span id="retell-label" class="retell-btn__label">
                        <?php esc_html_e('Call us', 'storevoiceai-for-woocommerce'); ?>
                    </span>
                </button>
            </div>
        </div>
<?php
    }

    public function create_call()
    {
        if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'storevoiceai-for-woocommerce-nonce')) {
            wp_send_json_error(['message' => __('Invalid nonce', 'storevoiceai-for-woocommerce')], 403);
            return;
        }

        // Rate-limit guest call initiations to prevent abuse of the paid upstream API.
        if (!$this->check_create_call_rate_limit()) {
            wp_send_json_error(
                [
                    'message' => __('Too many requests. Please wait a moment and try again.', 'storevoiceai-for-woocommerce'),
                    'code'    => 'rate_limited',
                ],
                429
            );
            return;
        }

        $api    = new Store_Voice_AI_API();
        $result = $api->create_call();

        if (is_wp_error($result)) {
            $payload = [
                'message' => $result->get_error_message(),
                'code'    => $result->get_error_code(),
            ];
            $data    = $result->get_error_data();
            if (!empty($data)) {
                $payload['data'] = $data;
            }
            wp_send_json_error($payload);
            return;
        }

        wp_send_json_success($result);
        return;
    }

    /**
     * Speed bump against scripted abuse of the guest create_call endpoint.
     * Real quota / abuse enforcement lives on the upstream service.
     */
    private function check_create_call_rate_limit()
    {
        $max_attempts = 30;
        $window       = 60; // seconds

        $key_source = '';
        if (is_user_logged_in()) {
            $key_source = 'u:' . get_current_user_id();
        } else {
            $ip = isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : '';
            $key_source = 'ip:' . ($ip !== '' ? $ip : 'unknown');
        }

        $cache_key = 'storevoiceai_call_rl_' . md5($key_source);

        // When a persistent object cache is in use, prefer an atomic increment
        // so two concurrent requests can't both pass a near-limit check.
        if (function_exists('wp_using_ext_object_cache') && wp_using_ext_object_cache()) {
            wp_cache_add($cache_key, 0, 'storevoiceai', $window);
            $attempts = wp_cache_incr($cache_key, 1, 'storevoiceai');

            if ($attempts === false) {
                // Cache backend refused; fall through to the transient path.
            } else {
                return ((int) $attempts) <= $max_attempts;
            }
        }

        // Best-effort fallback: small race window is acceptable for a speed bump
        // (real quota enforcement lives on the upstream service).
        $attempts = (int) get_transient($cache_key);
        if ($attempts >= $max_attempts) {
            return false;
        }
        set_transient($cache_key, $attempts + 1, $window);
        return true;
    }
}
