<?php
/**
 * Widget Endpoint for BoostBot REST API.
 *
 * @package BoostBot
 */

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

/**
 * BoostBot_Widget_Endpoint class.
 *
 * Handles interactive widget operations (forms, calendars, etc.).
 *
 * @since 1.0.0
 */
class BoostBot_Widget_Endpoint extends BoostBot_Base_Endpoint
{
    /**
     * The base path for this endpoint.
     *
     * @since 1.0.0
     * @access protected
     * @var string $rest_base
     */
    protected $rest_base = 'widget';

    /**
     * Register the routes for this endpoint.
     *
     * @since 1.0.0
     */
    public function register()
    {
        // POST /wp-json/boostbot/v1/widget/{type} - Trigger a widget
        $this->register_route(
            '/(?P<type>[a-zA-Z0-9_-]+)',
            'POST',
            [$this, 'trigger_widget'],
            [$this, 'public_with_validation']
        );

        // POST /wp-json/boostbot/v1/widget/{type}/submit - Submit widget data
        $this->register_route(
            '/(?P<type>[a-zA-Z0-9_-]+)/submit',
            'POST',
            [$this, 'submit_widget'],
            [$this, 'public_with_validation']
        );

        // GET /wp-json/boostbot/v1/widget/types - Get available widget types
        $this->register_route(
            '/types',
            'GET',
            [$this, 'get_widget_types'],
            array( $this, 'public_with_api_rate_limit' )
        );
    }

    /**
     * Trigger a widget to display.
     *
     * @since 1.0.0
     * @param WP_REST_Request $request The REST request object.
     * @return WP_REST_Response|WP_Error The response or error.
     */
    public function trigger_widget($request)
    {
        $widget_type = sanitize_text_field($request->get_param('type'));
        $conversation_id = sanitize_text_field($request->get_param('conversation_id'));
        $config = $request->get_param('config');

        BoostBot_Logger::debug('Widget trigger requested', [
            'type'            => $widget_type,
            'conversation_id' => $conversation_id,
        ]);

        // Check if widget type exists
        $available_widgets = $this->get_available_widgets();
        if (!isset($available_widgets[$widget_type])) {
            BoostBot_Logger::warning('Widget trigger error: widget type not found', [
                'endpoint'        => 'widget/trigger',
                'widget_type'     => $widget_type,
                'conversation_id' => $conversation_id,
            ]);
            return $this->error(__('Widget type not found', 'boostbot'), 404);
        }

        // Check if user has Pro for certain widgets
        if (class_exists('BoostBot_License_Manager')) {
            $license_manager = new BoostBot_License_Manager();
            if (!$license_manager->is_feature_enabled('widgets')) {
                BoostBot_Logger::warning('Widget trigger error: widgets feature disabled', [
                    'endpoint'        => 'widget/trigger',
                    'widget_type'     => $widget_type,
                    'conversation_id' => $conversation_id,
                ]);
                return $this->error(
                    __('Interactive widgets require Pro subscription', 'boostbot'),
                    403
                );
            }
        }

        // Get widget configuration
        $widget_config = $this->get_widget_config($widget_type, $config);

        // Track widget usage
        $this->track_widget_usage($widget_type, $conversation_id);

        return $this->success([
            'widget_type' => $widget_type,
            'config'      => $widget_config,
            'html'        => $this->render_widget($widget_type, $widget_config),
        ]);
    }

    /**
     * Submit widget data (e.g., form submission).
     *
     * @since 1.0.0
     * @param WP_REST_Request $request The REST request object.
     * @return WP_REST_Response|WP_Error The response or error.
     */
    public function submit_widget($request)
    {
        $widget_type = sanitize_text_field($request->get_param('type'));
        $conversation_id = sanitize_text_field($request->get_param('conversation_id'));
        $visitor_id = sanitize_text_field($request->get_param('visitor_id'));
        $data = $request->get_param('data');

        // Extract context from top-level request parameters (not inside $data)
        $context = array(
            'widget_id'       => absint($request->get_param('widget_id')),
            'widget_type'     => sanitize_text_field($request->get_param('widget_type') ?: $widget_type),
            'bot_id'          => absint($request->get_param('bot_id')),
            'source_page'     => esc_url_raw($request->get_param('source_page')),
            'conversation_id' => $conversation_id,
            'visitor_id'      => $visitor_id,
            'language'        => $this->get_request_language( $request ),
        );

        BoostBot_Logger::debug('Widget submission received', [
            'type'            => $widget_type,
            'conversation_id' => $conversation_id,
            'widget_id'       => $context['widget_id'],
            'source_page'     => $context['source_page'],
        ]);

        // Validate widget type
        $available_widgets = $this->get_available_widgets();
        if (!isset($available_widgets[$widget_type])) {
            BoostBot_Logger::warning('Widget submit error: widget type not found', [
                'endpoint'        => 'widget/submit',
                'widget_type'     => $widget_type,
                'conversation_id' => $conversation_id,
                'widget_id'       => $context['widget_id'],
                'bot_id'          => $context['bot_id'],
                'language'        => $context['language'],
            ]);
            return $this->error(__('Widget type not found', 'boostbot'), 404);
        }

        // Process submission based on widget type (pass context separately)
        $result = $this->process_widget_submission($widget_type, $data, $context);

        if (is_wp_error($result)) {
            BoostBot_Logger::warning('Widget submit error: processor returned WP_Error', [
                'endpoint'        => 'widget/submit',
                'widget_type'     => $widget_type,
                'conversation_id' => $conversation_id,
                'widget_id'       => $context['widget_id'],
                'bot_id'          => $context['bot_id'],
                'language'        => $context['language'],
                'error_code'      => $result->get_error_code(),
                'error_message'   => $result->get_error_message(),
            ]);
            return $result;
        }

        BoostBot_Logger::info('Widget submitted successfully', [
            'type'            => $widget_type,
            'conversation_id' => $conversation_id,
            'widget_id'       => $context['widget_id'],
        ]);

        return $this->success($result);
    }

    /**
     * Get available widget types.
     *
     * @since 1.0.0
     * @param WP_REST_Request $request The REST request object.
     * @return WP_REST_Response The response with widget types.
     */
    public function get_widget_types($request)
    {
        $widgets = $this->get_available_widgets();

        // Check license for pro widgets (use is_pro() to include Dev Mode)
        $is_pro = false;
        if (class_exists('BoostBot_License_Manager')) {
            $license_manager = new BoostBot_License_Manager();
            $is_pro = $license_manager->is_pro();
        }

        // Mark which widgets are available
        foreach ($widgets as $key => &$widget) {
            $widget['available'] = $is_pro || $widget['free'];
        }

        return $this->success($widgets);
    }

    /**
     * Get available widgets configuration.
     *
     * @since 1.0.0
     * @return array Available widgets.
     */
    private function get_available_widgets()
    {
        return [
            'contact_form'  => [
                'name'        => __('Contact Form', 'boostbot'),
                'description' => __('Collect contact information', 'boostbot'),
                'free'        => false,
                'fields'      => ['name', 'email', 'phone', 'message'],
            ],
            'lead_capture'  => [
                'name'        => __('Lead Capture', 'boostbot'),
                'description' => __('Quick lead capture form', 'boostbot'),
                'free'        => true, // Available in free for homepage
                'fields'      => ['name', 'email', 'phone'],
            ],
            'lead_form'     => [
                'name'        => __('Lead Form', 'boostbot'),
                'description' => __('Lead capture form', 'boostbot'),
                'free'        => true,
                'fields'      => ['name', 'email', 'phone'],
            ],
            'dynamic_form'  => [
                'name'        => __('Dynamic Form', 'boostbot'),
                'description' => __('Dynamic form with custom fields', 'boostbot'),
                'free'        => false,
                'fields'      => [],
            ],
            'form'          => [
                'name'        => __('Form', 'boostbot'),
                'description' => __('Custom form widget', 'boostbot'),
                'free'        => false,
                'fields'      => [],
            ],
            'calendar'      => [
                'name'        => __('Calendar', 'boostbot'),
                'description' => __('Schedule appointments', 'boostbot'),
                'free'        => false,
                'fields'      => ['date', 'time', 'name', 'email'],
            ],
            'product_card'  => [
                'name'        => __('Product Card', 'boostbot'),
                'description' => __('Display product information', 'boostbot'),
                'free'        => false,
                'fields'      => ['product_id'],
            ],
            'bundle_builder' => [
                'name'        => __('Bundle Builder', 'boostbot'),
                'description' => __('Build and submit product bundles', 'boostbot'),
                'free'        => false,
                'fields'      => ['action', 'bundle_id', 'coupon_code'],
            ],
            'survey'        => [
                'name'        => __('Survey', 'boostbot'),
                'description' => __('Quick satisfaction survey', 'boostbot'),
                'free'        => false,
                'fields'      => ['rating', 'feedback'],
            ],
        ];
    }

    /**
     * Get widget configuration.
     *
     * @since 1.0.0
     * @param string $widget_type The widget type.
     * @param array  $custom_config Optional custom configuration.
     * @return array Widget configuration.
     */
    private function get_widget_config($widget_type, $custom_config = null)
    {
        $widgets = $this->get_available_widgets();
        $base_config = $widgets[$widget_type] ?? [];

        // Merge with custom config if provided
        if (!empty($custom_config) && is_array($custom_config)) {
            $base_config = array_merge($base_config, $custom_config);
        }

        // Add common configuration
        $base_config['primary_color'] = BoostBot_Settings::get('primary_color');
        $base_config['accent_color'] = BoostBot_Settings::get('accent_color');
        $base_config['is_rtl'] = is_rtl();

        return $base_config;
    }

    /**
     * Render widget HTML.
     *
     * @since 1.0.0
     * @param string $widget_type The widget type.
     * @param array  $config Widget configuration.
     * @return string Widget HTML.
     */
    private function render_widget($widget_type, $config)
    {
        // This will be expanded in Week 7 (Interactive Widgets)
        // For now, return a placeholder
        return sprintf(
            '<div class="boostbot-widget boostbot-widget--%s" data-type="%s">
                <div class="boostbot-widget__placeholder">
                    %s Widget - Coming in Week 7
                </div>
            </div>',
            esc_attr($widget_type),
            esc_attr($widget_type),
            esc_html($config['name'] ?? $widget_type)
        );
    }

    /**
     * Process widget submission.
     *
     * @since 1.0.0
     * @param string $widget_type The widget type.
     * @param array  $data Submitted data (form fields only).
     * @param array  $context Submission context (widget_id, source_page, etc).
     * @return array|WP_Error Processing result or error.
     */
    private function process_widget_submission($widget_type, $data, $context)
    {
        // Extract context fields
        $conversation_id = $context['conversation_id'] ?? '';
        $visitor_id      = $context['visitor_id'] ?? '';

        // Sanitize all data
        $sanitized_data = [];
        if (is_array($data)) {
            foreach ($data as $key => $value) {
                $sanitized_data[sanitize_key($key)] = $this->sanitize_widget_submission_value( $value );
            }
        }

        switch ($widget_type) {
            case 'contact_form':
            case 'lead_capture':
            case 'lead_form':
            case 'dynamic_form':
            case 'form':
                return $this->process_lead_submission($sanitized_data, $context);

            case 'product_card':
                if (!class_exists('WooCommerce')) {
                    BoostBot_Logger::warning('Widget submit error: WooCommerce unavailable for product card', [
                        'endpoint'        => 'widget/product_card/submit',
                        'conversation_id' => $conversation_id,
                        'widget_id'       => $context['widget_id'] ?? 0,
                        'bot_id'          => $context['bot_id'] ?? 0,
                        'language'        => $context['language'] ?? '',
                    ]);
                    return $this->error(__('WooCommerce is not installed', 'boostbot'), 400);
                }
                // Normalize camelCase from frontend to snake_case expected by PHP widget
                $product_id = $data['product_id'] ?? $data['productId'] ?? null;
                if ($product_id) {
                    $sanitized_data['product_id'] = intval($product_id);
                }
                if ( ! empty( $context['language'] ) && empty( $sanitized_data['language'] ) ) {
                    $sanitized_data['language'] = sanitize_text_field( $context['language'] );
                }
                $widget = new BoostBot_Product_Card_Widget();
                try {
                    return $widget->process($sanitized_data, $context);
                } catch ( \Throwable $e ) {
                    BoostBot_Logger::warning('Widget submit error: product card processing failed', [
                        'endpoint'        => 'widget/product_card/submit',
                        'conversation_id' => $conversation_id,
                        'widget_id'       => $context['widget_id'] ?? 0,
                        'bot_id'          => $context['bot_id'] ?? 0,
                        'language'        => $context['language'] ?? '',
                        'product_id'      => $sanitized_data['product_id'] ?? 0,
                        'action'          => $sanitized_data['action'] ?? '',
                        'error_message'   => $e->getMessage(),
                    ]);
                    return $this->error( $e->getMessage(), 400 );
                }

            case 'coupon':
                $action      = sanitize_text_field( $data['action'] ?? 'copy' );
                $coupon_code = sanitize_text_field( $data['coupon_code'] ?? '' );

                BoostBot_Logger::debug( 'Coupon action received', array(
                    'endpoint'        => 'widget/coupon/submit',
                    'action'          => $action,
                    'coupon_code'     => $coupon_code,
                    'conversation_id' => $conversation_id,
                    'widget_id'       => $context['widget_id'] ?? 0,
                    'bot_id'          => $context['bot_id'] ?? 0,
                    'language'        => $context['language'] ?? '',
                ) );

                if ( $context['bot_id'] > 0 && $context['widget_id'] > 0 && class_exists( 'BoostBot_Widget_Model' ) ) {
                    $widget_model = new BoostBot_Widget_Model();
                    if ( method_exists( $widget_model, 'track_usage' ) ) {
                        $language = sanitize_text_field( $context['language'] ?? BoostBot_Language::get_primary() );
                        $widget_model->track_usage( $context['widget_id'], $context['bot_id'], $language );
                    }
                }

                return array(
                    'success' => true,
                    'action'  => $action,
                );

            case 'bundle_builder':
                if ( $context['bot_id'] > 0 && $context['widget_id'] > 0 && class_exists( 'BoostBot_Widget_Model' ) ) {
                    $widget_model = new BoostBot_Widget_Model();
                    if ( method_exists( $widget_model, 'track_usage' ) ) {
                        $language = sanitize_text_field( $context['language'] ?? BoostBot_Language::get_primary() );
                        $widget_model->track_usage( $context['widget_id'], $context['bot_id'], $language );
                    }
                }

                return array(
                    'success' => true,
                    'action'  => sanitize_text_field( $data['action'] ?? 'submit' ),
                    'data'    => $sanitized_data,
                );

            case 'survey':
                return $this->process_survey_submission($sanitized_data, $conversation_id, $context);

            case 'calendar':
                return $this->process_calendar_submission($sanitized_data, $context);

            default:
                return [
                    'message' => __('Widget submitted successfully', 'boostbot'),
                    'data'    => $sanitized_data,
                ];
        }
    }

    /**
     * Process lead submission from widget.
     *
     * @since 1.0.0
     * @param array $data Lead data (form fields only).
     * @param array $context Submission context (widget_id, source_page, etc).
     * @return array|WP_Error Result or error.
     */
    private function process_lead_submission($data, $context)
    {
        // Extract context fields
        $conversation_id = $context['conversation_id'] ?? '';
        $visitor_id      = $context['visitor_id'] ?? '';
        $widget_id       = $context['widget_id'] ?? 0;
        $widget_type     = $context['widget_type'] ?? '';
        $bot_id          = $context['bot_id'] ?? 0;
        $source_page     = $context['source_page'] ?? '';

        // Resolve language from context or bot config
        $language = sanitize_text_field( $context['language'] ?? '' );
        if ( empty( $language ) && $bot_id > 0 && class_exists( 'BoostBot_Bot_Model' ) ) {
            $bot_obj = ( new BoostBot_Bot_Model() )->get( absint( $bot_id ) );
            if ( $bot_obj && ! empty( $bot_obj->language ) ) {
                $language = $bot_obj->language;
            }
        }
        if ( empty( $language ) ) {
            $language = BoostBot_Language::get_primary();
        }

        // Validate email format if provided (but don't require email/phone)
        // As per plan: always create a lead row per submission, storing all fields
        if (!empty($data['email']) && !is_email($data['email'])) {
            return $this->error(__('Invalid email address', 'boostbot'), 400);
        }

        // Build metadata with complete widget/context information
        $metadata = array(
            'widget_id'       => $widget_id,
            'widget_type'     => $widget_type,
            'bot_id'          => $bot_id,
            'page_url'        => $source_page,
            'conversation_id' => $conversation_id,
            'visitor_id'      => $visitor_id,
            'submitted_at'    => current_time('mysql'),
        );

        // Build conversation summary from chat history (if available)
        $conversation_summary = '';
        if ( ! empty( $conversation_id ) ) {
            $conversation_summary = $this->build_conversation_summary( $conversation_id );
        }

        // Create lead
        $lead_model = new BoostBot_Lead_Model();

        $lead_data = [
            'language'             => $language,
            'conversation_id'      => $conversation_id,
            'visitor_id'           => $visitor_id,
            'name'                 => $data['name'] ?? '',
            'email'                => $data['email'] ?? '',
            'phone'                => $data['phone'] ?? '',
            'company'              => $data['company'] ?? '',
            'lead_status'          => 'new',
            'form_data'            => $data,
            'source_page'          => $source_page,
            'conversation_summary' => $conversation_summary,
            'metadata'             => $metadata,
        ];

        // Calculate lead score
        $lead_data['lead_score'] = $lead_model->calculate_score($lead_data);

        $lead_id = $lead_model->create($lead_data);

        if (!$lead_id) {
            return $this->error(__('Failed to save lead', 'boostbot'), 500);
        }

        BoostBot_Logger::info('Lead created from widget', [
            'lead_id'         => $lead_id,
            'conversation_id' => $conversation_id,
            'widget_id'       => $widget_id,
            'source_page'     => $source_page,
        ]);

        // Fire generic lead-created hook (for integrations/webhooks)
        // Include full context so webhooks get complete data
        do_action( 'boostbot_lead_created', $lead_id, $lead_data, array(
            'source'          => 'widget_endpoint',
            'conversation_id' => $conversation_id,
            'visitor_id'      => $visitor_id,
            'widget_id'       => $widget_id,
            'widget_type'     => $widget_type,
            'bot_id'          => $bot_id,
            'source_page'     => $source_page,
        ) );

        // Fire per-widget webhook if configured (Zapier, Make, n8n, etc.)
        if ( $widget_id > 0 ) {
            $this->fire_widget_webhook( $widget_id, $lead_id, $lead_data, $context );
            $this->send_widget_recipient_emails( $widget_id, $lead_id, $lead_data, $context );
        }

        // Track widget usage for this bot
        if ($bot_id > 0 && $widget_id > 0) {
            if (class_exists('BoostBot_Widget_Model')) {
                $widget_model = new BoostBot_Widget_Model();
                if (method_exists($widget_model, 'track_usage')) {
                    $widget_model->track_usage($widget_id, $bot_id, $language);
                }
            }
        }

        return [
            'message' => __('Thank you! We will contact you soon.', 'boostbot'),
            'lead_id' => $lead_id,
        ];
    }

    /**
     * Fire per-widget webhook if a webhook_url is configured.
     *
     * Sends a POST request with the lead data to the configured URL (Zapier, Make, n8n, etc.).
     * Uses wp_remote_post with a short timeout to avoid blocking the response.
     *
     * @since 1.10.0
     * @param int   $widget_id Widget ID.
     * @param int   $lead_id   Lead ID.
     * @param array $lead_data Lead data array.
     * @param array $context   Submission context.
     * @return void
     */
    private function fire_widget_webhook( int $widget_id, int $lead_id, array $lead_data, array $context ): void {
        if ( $widget_id <= 0 || ! class_exists( 'BoostBot_Widget_Model' ) ) {
            return;
        }

        $widget_model = new BoostBot_Widget_Model();
        $widget       = $widget_model->get( $widget_id );

        if ( ! $widget ) {
            return;
        }

        $config = $widget->config;
        if ( is_string( $config ) ) {
            $config = json_decode( $config, true );
        }

        $webhook_url = isset( $config['webhook_url'] ) ? trim( $config['webhook_url'] ) : '';

        if ( empty( $webhook_url ) || ! filter_var( $webhook_url, FILTER_VALIDATE_URL ) ) {
            return;
        }

        // Build the payload (consistent with global CRM webhook format)
        $payload = array(
            'event'       => 'lead_from_chatbot',
            'lead_id'     => $lead_id,
            'timestamp'   => current_time( 'c' ),
            'widget_id'   => $widget_id,
            'widget_name' => $widget->name ?? '',
            'widget_type' => $widget->type ?? 'form',
            'bot_id'      => $context['bot_id'] ?? 0,
            'source_page' => $context['source_page'] ?? '',
            'data'        => array(
                'name'    => $lead_data['name'] ?? '',
                'email'   => $lead_data['email'] ?? '',
                'phone'   => $lead_data['phone'] ?? '',
                'company' => $lead_data['company'] ?? '',
            ),
            'form_data'            => $lead_data['form_data'] ?? array(),
            'conversation_id'      => $context['conversation_id'] ?? '',
            'conversation_summary' => $lead_data['conversation_summary'] ?? '',
        );

        // Fire asynchronously with a short timeout (non-blocking)
        $result = wp_remote_post( $webhook_url, array(
            'body'      => wp_json_encode( $payload ),
            'headers'   => array(
                'Content-Type' => 'application/json',
            ),
            'timeout'   => 5, // 5 second timeout to not block the user
            'blocking'  => false, // Non-blocking so user gets instant response
            'sslverify' => false,
        ) );

        if ( is_wp_error( $result ) ) {
            BoostBot_Logger::error( sprintf(
                'Widget webhook failed for widget %d: %s',
                $widget_id,
                $result->get_error_message()
            ) );
        } else {
            BoostBot_Logger::info( sprintf(
                'Widget webhook fired for widget %d to %s (lead %d)',
                $widget_id,
                $webhook_url,
                $lead_id
            ) );
        }
    }

    /**
     * Send lead submission emails to per-widget recipients.
     *
     * @since 1.10.0
     * @param int   $widget_id Widget ID.
     * @param int   $lead_id   Lead ID.
     * @param array $lead_data Lead data array.
     * @param array $context   Submission context.
     * @return void
     */
    private function send_widget_recipient_emails( int $widget_id, int $lead_id, array $lead_data, array $context ): void {
        if ( $widget_id <= 0 || ! class_exists( 'BoostBot_Widget_Model' ) ) {
            return;
        }

        $widget_model = new BoostBot_Widget_Model();
        $widget       = $widget_model->get( $widget_id );

        if ( ! $widget ) {
            return;
        }

        $config = $widget->config;
        if ( is_string( $config ) ) {
            $config = json_decode( $config, true );
        }

        if ( ! is_array( $config ) ) {
            return;
        }

        $recipients = $this->extract_widget_notification_recipients( $config );
        if ( empty( $recipients ) ) {
            return;
        }

        $site_name   = wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES );
        $widget_name = ! empty( $widget->name ) ? sanitize_text_field( $widget->name ) : __( 'Lead Form', 'boostbot' );
        $subject     = sprintf(
            /* translators: %1$s: widget name, %2$s: site name */
            __( 'New lead from %1$s (%2$s)', 'boostbot' ),
            $widget_name,
            $site_name
        );

        $body_lines   = array();
        $body_lines[] = sprintf(
            /* translators: %s: widget name */
            __( 'A new lead was submitted from widget "%s".', 'boostbot' ),
            $widget_name
        );
        $body_lines[] = '';
        $body_lines[] = sprintf(
            /* translators: %d: lead ID number */
            __( 'Lead ID: %d', 'boostbot' ),
            $lead_id
        );
        $body_lines[] = sprintf(
            /* translators: %s: submission date and time */
            __( 'Submitted at: %s', 'boostbot' ),
            current_time( 'mysql' )
        );
        $body_lines[] = sprintf(
            /* translators: %s: source page URL */
            __( 'Source page: %s', 'boostbot' ),
            $context['source_page'] ?? ''
        );
        $body_lines[] = sprintf(
            /* translators: %s: conversation ID */
            __( 'Conversation ID: %s', 'boostbot' ),
            $context['conversation_id'] ?? ''
        );
        $body_lines[] = '';
        $body_lines[] = __( 'Primary details:', 'boostbot' );
        $body_lines[] = sprintf(
            /* translators: %s: lead contact name */
            __( 'Name: %s', 'boostbot' ),
            $lead_data['name'] ?? ''
        );
        $body_lines[] = sprintf(
            /* translators: %s: lead email address */
            __( 'Email: %s', 'boostbot' ),
            $lead_data['email'] ?? ''
        );
        $body_lines[] = sprintf(
            /* translators: %s: lead phone number */
            __( 'Phone: %s', 'boostbot' ),
            $lead_data['phone'] ?? ''
        );
        $body_lines[] = sprintf(
            /* translators: %s: lead company name */
            __( 'Company: %s', 'boostbot' ),
            $lead_data['company'] ?? ''
        );

        $form_data = $lead_data['form_data'] ?? array();
        if ( ! empty( $form_data ) && is_array( $form_data ) ) {
            $body_lines[] = '';
            $body_lines[] = __( 'All submitted fields:', 'boostbot' );
            foreach ( $form_data as $key => $value ) {
                $field_key   = sanitize_text_field( (string) $key );
                $field_value = $this->normalize_widget_email_field_value( $value );
                $body_lines[] = sprintf( '%s: %s', $field_key, $field_value );
            }
        }

        $body    = implode( "\n", $body_lines );
        $headers = array( 'Content-Type: text/plain; charset=UTF-8' );

        foreach ( $recipients as $recipient ) {
            $sent = wp_mail( $recipient, $subject, $body, $headers );
            if ( ! $sent ) {
                BoostBot_Logger::error( sprintf(
                    'Widget email notification failed for widget %d to %s (lead %d)',
                    $widget_id,
                    $recipient,
                    $lead_id
                ) );
            }
        }
    }

    /**
     * Extract and validate recipient emails from widget config.
     *
     * @since 1.10.0
     * @param array $config Widget config array.
     * @return array
     */
    private function extract_widget_notification_recipients( array $config ): array {
        if ( ! isset( $config['notification_emails'] ) ) {
            return array();
        }

        $raw_recipients = $config['notification_emails'];

        if ( is_string( $raw_recipients ) ) {
            $raw_recipients = preg_split( '/[\n,;]+/', $raw_recipients );
        }

        if ( ! is_array( $raw_recipients ) ) {
            return array();
        }

        $recipients = array();
        foreach ( $raw_recipients as $email ) {
            $sanitized = sanitize_email( (string) $email );
            if ( ! empty( $sanitized ) && is_email( $sanitized ) ) {
                $recipients[] = $sanitized;
            }
        }

        return array_values( array_unique( $recipients ) );
    }

    /**
     * Normalize form field values for plain-text email output.
     *
     * @since 1.10.0
     * @param mixed $value Field value.
     * @return string
     */
    private function normalize_widget_email_field_value( $value ): string {
        if ( is_scalar( $value ) || null === $value ) {
            return sanitize_text_field( (string) $value );
        }

        $encoded = wp_json_encode( $value );
        return is_string( $encoded ) ? sanitize_text_field( $encoded ) : '';
    }

    /**
     * Recursively sanitize widget submission values while preserving arrays.
     *
     * @since 1.7.0
     * @param mixed $value Raw submitted value.
     * @return mixed
     */
    private function sanitize_widget_submission_value( $value ) {
        if ( is_array( $value ) ) {
            $sanitized = array();
            foreach ( $value as $key => $nested_value ) {
                $sanitized_key               = is_string( $key ) ? sanitize_key( $key ) : $key;
                $sanitized[ $sanitized_key ] = $this->sanitize_widget_submission_value( $nested_value );
            }

            return $sanitized;
        }

        if ( is_email( $value ) ) {
            return sanitize_email( $value );
        }

        return sanitize_text_field( (string) $value );
    }

    /**
     * Build a short summary of the conversation from chat history.
     *
     * Extracts the last few user messages and produces a concise text summary
     * that captures the user's needs and the conversation context.
     *
     * @since 1.9.0
     * @param string $conversation_id Conversation ID.
     * @return string Conversation summary (empty string if unavailable).
     */
    private function build_conversation_summary( string $conversation_id ): string {
        if ( empty( $conversation_id ) ) {
            return '';
        }

        $conversation_model = new BoostBot_Conversation_Model();
        $conversation       = $conversation_model->get_by_conversation_id( $conversation_id );

        if ( ! $conversation || empty( $conversation->session_data ) ) {
            return '';
        }

        $session = json_decode( $conversation->session_data, true );
        $messages = $session['messages'] ?? array();

        if ( empty( $messages ) ) {
            return '';
        }

        // Take the last 10 messages to build context
        $recent = array_slice( $messages, -10 );
        $summary_parts = array();

        foreach ( $recent as $msg ) {
            $role    = $msg['role'] ?? '';
            $content = $msg['content'] ?? '';

            if ( empty( $content ) ) {
                continue;
            }

            // Truncate long messages
            $content = mb_substr( $content, 0, 200 );

            if ( 'user' === $role ) {
                $summary_parts[] = 'לקוח: ' . $content;
            } elseif ( 'assistant' === $role || 'bot' === $role ) {
                $summary_parts[] = 'בוט: ' . $content;
            }
        }

        if ( empty( $summary_parts ) ) {
            return '';
        }

        // Join and truncate total summary to ~500 chars
        $summary = implode( "\n", $summary_parts );
        if ( mb_strlen( $summary ) > 500 ) {
            $summary = mb_substr( $summary, 0, 497 ) . '...';
        }

        return $summary;
    }

    /**
     * Process survey submission.
     *
     * @since 1.0.0
     * @param array  $data Survey data.
     * @param string $conversation_id Conversation ID.
     * @param array  $context Submission context (widget_id, bot_id, etc).
     * @return array Result.
     */
    private function process_survey_submission($data, $conversation_id, $context = [])
    {
        $rating = absint($data['rating'] ?? 0);
        $bot_id = absint($context['bot_id'] ?? 0);

        // Resolve language from context or bot config
        $survey_language = sanitize_text_field( $context['language'] ?? '' );
        if ( empty( $survey_language ) && $bot_id > 0 && class_exists( 'BoostBot_Bot_Model' ) ) {
            $lang_bot = ( new BoostBot_Bot_Model() )->get( $bot_id );
            if ( $lang_bot && ! empty( $lang_bot->language ) ) {
                $survey_language = $lang_bot->language;
            }
        }
        if ( empty( $survey_language ) ) {
            $survey_language = BoostBot_Language::get_primary();
        }

        // Update conversation with satisfaction score
        if ($rating > 0 && !empty($conversation_id)) {
            $conversation_model = new BoostBot_Conversation_Model();
            $conversation = $conversation_model->get_by_conversation_id($conversation_id);

            if ($conversation) {
                $conversation_model->update($conversation->id, [
                    'satisfaction_score' => $rating,
                ]);
            }
        }

        // Track widget usage for this bot
        if ($bot_id > 0 && !empty($context['widget_id'])) {
            $widget_id = absint($context['widget_id']);
            if (class_exists('BoostBot_Widget_Model') && $widget_id > 0) {
                $widget_model = new BoostBot_Widget_Model();
                if (method_exists($widget_model, 'track_usage')) {
                    $widget_model->track_usage($widget_id, $bot_id, $survey_language);
                }
            }
        }

        return [
            'message' => __('Thank you for your feedback!', 'boostbot'),
        ];
    }

    /**
     * Process calendar submission.
     *
     * @since 1.0.0
     * @param array $data Calendar data.
     * @param array $context Submission context (widget_id, source_page, etc).
     * @return array Result.
     */
    private function process_calendar_submission($data, $context)
    {
        // Extract context fields
        $conversation_id = $context['conversation_id'] ?? '';
        $visitor_id      = $context['visitor_id'] ?? '';
        $widget_id       = $context['widget_id'] ?? 0;
        $widget_type     = $context['widget_type'] ?? 'calendar';
        $bot_id          = $context['bot_id'] ?? 0;
        $source_page     = $context['source_page'] ?? '';

        // Resolve language from context or bot config
        $cal_language = sanitize_text_field( $context['language'] ?? '' );
        if ( empty( $cal_language ) && $bot_id > 0 && class_exists( 'BoostBot_Bot_Model' ) ) {
            $lang_bot = ( new BoostBot_Bot_Model() )->get( absint( $bot_id ) );
            if ( $lang_bot && ! empty( $lang_bot->language ) ) {
                $cal_language = $lang_bot->language;
            }
        }
        if ( empty( $cal_language ) ) {
            $cal_language = BoostBot_Language::get_primary();
        }

        // This is the legacy calendar path - save as a lead with appointment info
        // The main calendar booking flow goes through class-meetings-endpoint.php

        // Build metadata with complete widget/context information
        $metadata = array(
            'widget_id'       => $widget_id,
            'widget_type'     => $widget_type,
            'bot_id'          => $bot_id,
            'page_url'        => $source_page,
            'conversation_id' => $conversation_id,
            'visitor_id'      => $visitor_id,
            'submitted_at'    => current_time('mysql'),
        );

        $lead_model = new BoostBot_Lead_Model();

        $lead_data = [
            'language'        => $cal_language,
            'conversation_id' => $conversation_id,
            'visitor_id'      => $visitor_id,
            'name'            => $data['name'] ?? '',
            'email'           => $data['email'] ?? '',
            'lead_status'     => 'new',
            'source_page'     => $source_page,
            'metadata'        => $metadata,
            'form_data'       => [
                'type'        => 'appointment',
                'date'        => $data['date'] ?? '',
                'time'        => $data['time'] ?? '',
            ],
        ];

        $lead_id = $lead_model->create($lead_data);

        if ( $lead_id ) {
            do_action( 'boostbot_lead_created', $lead_id, $lead_data, array(
                'source'          => 'calendar_widget_legacy',
                'conversation_id' => $conversation_id,
                'visitor_id'      => $visitor_id,
                'widget_id'       => $widget_id,
                'widget_type'     => $widget_type,
                'bot_id'          => $bot_id,
                'source_page'     => $source_page,
            ) );
        }

        // Track widget usage for this bot
        if ($bot_id > 0 && $widget_id > 0) {
            if (class_exists('BoostBot_Widget_Model')) {
                $widget_model = new BoostBot_Widget_Model();
                if (method_exists($widget_model, 'track_usage')) {
                    $widget_model->track_usage($widget_id, $bot_id, $cal_language);
                }
            }
        }

        return [
            'message'   => __('Appointment request received! We will confirm shortly.', 'boostbot'),
            'lead_id'   => $lead_id,
            'date'      => $data['date'] ?? '',
            'time'      => $data['time'] ?? '',
        ];
    }

    /**
     * Track widget usage.
     *
     * @since 1.0.0
     * @param string $widget_type Widget type.
     * @param string $conversation_id Conversation ID.
     */
    private function track_widget_usage($widget_type, $conversation_id)
    {
        // Update conversation with widget usage
        if (!empty($conversation_id)) {
            $conversation_model = new BoostBot_Conversation_Model();
            $conversation = $conversation_model->get_by_conversation_id($conversation_id);

            if ($conversation) {
                $widgets_used = json_decode($conversation->widgets_used, true) ?: [];
                $widgets_used[] = [
                    'type'      => $widget_type,
                    'timestamp' => current_time('mysql'),
                ];
                $conversation_model->update($conversation->id, [
                    'widgets_used' => $widgets_used,
                ]);
            }
        }
    }
}



