<?php
/**
 * Plugin Name: ZingTime Booking
 * Plugin URI: https://zingtime.ir/
 * Description: افزونه رسمی اتصال وردپرس به سیستم نوبت‌دهی آنلاین زینگ‌تایم. دارای داشبورد اختصاصی، فرم ۵ مرحله‌ای رزرو، صدور فاکتور و دانلود PDF.
 * Version: 4.0.2
 * Author: ZingTime
 * License: GPLv2 or later
 * Text Domain: zingtime-booking
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit; // جلوگیری از دسترسی مستقیم به فایل برای امنیت
}

define('ZINGTIME_VERSION', '4.0.2');
define('ZINGTIME_API_BASE_URL', 'https://zingtime.ir/api/v1/wp');

class Zingtime_Booking {

    public function __construct() {
        add_action('admin_menu', [$this, 'zingtime_register_admin_menu']);
        add_action('admin_init', [$this, 'zingtime_handle_form_submissions']);
        add_action('admin_enqueue_scripts', [$this, 'zingtime_enqueue_admin_assets']);
        add_action('wp_enqueue_scripts', [$this, 'zingtime_enqueue_frontend_assets']);
        
        add_shortcode('zingtime_booking', [$this, 'zingtime_render_booking_shortcode']);
        
        add_action('wp_ajax_zingtime_api_proxy', [$this, 'zingtime_api_proxy']);
        add_action('wp_ajax_nopriv_zingtime_api_proxy', [$this, 'zingtime_api_proxy']);
    }

    public function zingtime_register_admin_menu() {
        add_menu_page(
            __('تنظیمات زینگ‌تایم', 'zingtime-booking'),
            __('زینگ‌تایم', 'zingtime-booking'),
            'manage_options',
            'zingtime-settings',
            [$this, 'zingtime_render_admin_page'],
            'dashicons-calendar-alt',
            80
        );
    }

    public function zingtime_enqueue_admin_assets($hook) {
        if ($hook !== 'toplevel_page_zingtime-settings') {
            return;
        }
        
        wp_register_style('zingtime-admin-style', false, array(), ZINGTIME_VERSION);
        wp_enqueue_style('zingtime-admin-style');
        
        ob_start();
        ?>
        .zingtime-wrap { font-family: Tahoma, sans-serif; direction: rtl; padding: 20px 20px 20px 0; max-width: 1200px; margin: auto; }
        .zingtime-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 30px; flex-wrap: wrap; gap: 15px; }
        .zingtime-title { color: #0f172a; font-weight: 900; font-size: 28px; margin: 0; }
        .zingtime-card { background: #fff; border-radius: 16px; box-shadow: 0 4px 20px rgba(0,0,0,0.04); border: 1px solid #f1f5f9; padding: 24px; transition: all 0.3s; }
        .zingtime-card:hover { box-shadow: 0 10px 25px rgba(0,0,0,0.08); transform: translateY(-2px); }
        .zingtime-btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; padding: 10px 24px; border-radius: 10px; font-weight: bold; text-decoration: none; font-size: 14px; transition: all 0.3s; border: none; cursor: pointer; }
        .zingtime-btn-primary { background: #4f46e5; color: #fff; box-shadow: 0 4px 12px rgba(79,70,229,0.2); }
        .zingtime-btn-primary:hover { background: #4338ca; color: #fff; transform: translateY(-2px); box-shadow: 0 6px 15px rgba(79,70,229,0.3); }
        .zingtime-btn-danger-outline { background: transparent; border: 1px solid #ef4444; color: #ef4444; }
        .zingtime-btn-danger-outline:hover { background: #fef2f2; color: #dc2626; }
        .zingtime-btn-confirm { background: #ef4444; color: #fff; }
        .zingtime-grid-3 { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 24px; margin-bottom: 30px; }
        .zingtime-grid-2 { display: grid; grid-template-columns: 2fr 1fr; gap: 24px; }
        @media (max-width: 900px) { .zingtime-grid-2 { grid-template-columns: 1fr; } }
        .zingtime-stat-title { color: #64748b; font-size: 14px; font-weight: 600; margin-bottom: 8px; }
        .zingtime-stat-value { font-size: 36px; font-weight: 900; color: #0f172a; line-height: 1; }
        .zingtime-shortcode-box { background: linear-gradient(135deg, #eff6ff, #dbeafe); border: 1px solid #bfdbfe; padding: 20px 24px; border-radius: 16px; display: flex; justify-content: space-between; align-items: center; margin-bottom: 30px; flex-wrap: wrap; gap: 15px; }
        .zingtime-shortcode-code { background: #fff; padding: 10px 20px; border-radius: 10px; font-size: 18px; font-weight: 900; color: #1e40af; border: 2px dashed #93c5fd; user-select: all; letter-spacing: 1px; }
        .zingtime-table { width: 100%; border-collapse: collapse; text-align: right; }
        .zingtime-table th { padding: 16px; border-bottom: 2px solid #f1f5f9; color: #64748b; font-size: 13px; font-weight: bold; }
        .zingtime-table td { padding: 16px; border-bottom: 1px solid #f8fafc; color: #334155; font-size: 14px; }
        .zingtime-table tr:hover td { background: #f8fafc; }
        .zingtime-badge { display: inline-block; padding: 4px 10px; border-radius: 8px; font-size: 11px; font-weight: bold; }
        .zingtime-timeline { position: relative; padding-right: 24px; border-right: 2px solid #e2e8f0; margin-top: 20px; }
        .zingtime-timeline-item { position: relative; margin-bottom: 24px; }
        .zingtime-timeline-dot { position: absolute; right: -31px; top: 0; width: 14px; height: 14px; border-radius: 50%; background: #10b981; border: 3px solid #fff; box-shadow: 0 0 0 1px #10b981; }
        .zingtime-timeline-time { font-size: 13px; color: #64748b; font-weight: 900; margin-bottom: 6px; display: inline-block; background: #f1f5f9; padding: 2px 8px; border-radius: 6px; }
        .zingtime-timeline-content { background: #fff; padding: 16px; border-radius: 12px; border: 1px solid #f1f5f9; box-shadow: 0 2px 8px rgba(0,0,0,0.02); }
        .zingtime-empty-state { text-align: center; padding: 50px 20px; color: #94a3b8; }
        <?php
        $custom_css = ob_get_clean();
        wp_add_inline_style('zingtime-admin-style', wp_strip_all_tags($custom_css));

        wp_register_script('zingtime-admin-logic', false, array(), ZINGTIME_VERSION, true);
        wp_enqueue_script('zingtime-admin-logic');
        ob_start();
        ?>
        function zingtime_confirm_disconnect(btn) {
            if(btn.dataset.confirmed) { btn.form.submit(); return; }
            btn.innerText = '<?php echo esc_js(__('برای تایید قطع اتصال، مجدداً کلیک کنید', 'zingtime-booking')); ?>';
            btn.classList.add('zingtime-btn-confirm');
            btn.dataset.confirmed = 'true';
        }
        <?php
        $admin_js = ob_get_clean();
        wp_add_inline_script('zingtime-admin-logic', $admin_js);
    }

    public function zingtime_enqueue_frontend_assets() {
        wp_register_style('zingtime-vazirmatn', plugin_dir_url(__FILE__) . 'assets/css/Vazirmatn-font-face.css', array(), ZINGTIME_VERSION);
        wp_register_script('zingtime-tailwindcss', plugin_dir_url(__FILE__) . 'assets/js/tailwindcss.js', array(), '3.4.17', true);
        wp_register_script('zingtime-html2canvas', plugin_dir_url(__FILE__) . 'assets/js/html2canvas.min.js', array(), '1.4.1', true);
        wp_register_script('zingtime-jspdf', plugin_dir_url(__FILE__) . 'assets/js/jspdf.umd.min.js', array(), '2.5.2', true);
        
        $tailwind_config = "var tailwind = { config: { theme: { extend: { fontFamily: { sans: ['Vazir', 'tahoma', 'sans-serif'] } } } } };";
        wp_add_inline_script('zingtime-tailwindcss', $tailwind_config, 'before');
    }

    public function zingtime_api_proxy() {
        check_ajax_referer('zingtime_frontend_nonce', 'nonce');

        $action_type = isset($_POST['action_type']) ? sanitize_text_field(wp_unslash($_POST['action_type'])) : '';
        if (empty($action_type)) {
            wp_send_json_error(['message' => __('درخواست نامعتبر است.', 'zingtime-booking')]);
        }

        $api_key = get_option('zingtime_api_key');
        if (!$api_key) {
            wp_send_json_error(['message' => __('افزونه به سرور متصل نیست.', 'zingtime-booking')]);
        }

        // phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        $raw_payload = isset($_POST['payload']) ? wp_unslash($_POST['payload']) : [];
        // phpcs:enable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        
        if (!is_array($raw_payload)) {
            $raw_payload = [];
        }
        $payload = map_deep($raw_payload, 'sanitize_text_field');
        $payload['api_key'] = sanitize_text_field($api_key);
        
        $url = ZINGTIME_API_BASE_URL . '/' . $action_type;
        $response = wp_remote_post($url, [
            'body' => $payload,
            'timeout' => 25,
            'sslverify' => false 
        ]);
        
        if (is_wp_error($response)) {
            wp_send_json_error(['message' => __('ارتباط با سرور زینگ‌تایم برقرار نشد.', 'zingtime-booking')]);
        }
        
        $body = wp_remote_retrieve_body($response);
        $http_code = wp_remote_retrieve_response_code($response);
        
        if ($http_code != 200) {
            $error = json_decode($body, true);
            wp_send_json_error(['message' => esc_html($error['error'] ?? __('خطای سیستمی رخ داد.', 'zingtime-booking'))]);
        }

        wp_send_json(json_decode($body, true));
    }

    public function zingtime_handle_form_submissions() {
        if (!isset($_SERVER['REQUEST_METHOD']) || $_SERVER['REQUEST_METHOD'] !== 'POST' || !isset($_POST['zingtime_action'])) {
            return;
        }

        if (!current_user_can('manage_options')) {
            return;
        }

        if (!isset($_POST['zingtime_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['zingtime_nonce'])), 'zingtime_nonce_action')) {
            return;
        }

        $action = sanitize_text_field(wp_unslash($_POST['zingtime_action']));

        if ($action === 'verify_api_key') {
            $api_key = isset($_POST['api_key']) ? sanitize_text_field(wp_unslash($_POST['api_key'])) : '';
            if (empty($api_key)) return;

            $response = wp_remote_post(ZINGTIME_API_BASE_URL . '/verify-key', [
                'body' => ['api_key' => $api_key],
                'timeout' => 15, 'sslverify' => false
            ]);

            if (is_wp_error($response)) {
                add_settings_error('zingtime_messages', 'zingtime_error', __('خطا در ارتباط شبکه با سرور زینگ تایم.', 'zingtime-booking'), 'error');
                return;
            }

            $body = json_decode(wp_remote_retrieve_body($response), true);
            $http_code = wp_remote_retrieve_response_code($response);

            if ($http_code == 200 && isset($body['status']) && $body['status'] == 'success') {
                update_option('zingtime_api_key', $api_key);
                add_settings_error('zingtime_messages', 'zingtime_success', __('اتصال موفقیت‌آمیز بود.', 'zingtime-booking'), 'updated');
            } else {
                add_settings_error('zingtime_messages', 'zingtime_error', esc_html($body['message'] ?? __('کلید نامعتبر است.', 'zingtime-booking')), 'error');
            }
        } elseif ($action === 'disconnect') {
            delete_option('zingtime_api_key');
            add_settings_error('zingtime_messages', 'zingtime_success', __('اتصال با موفقیت قطع شد.', 'zingtime-booking'), 'updated');
        }
    }

    public function zingtime_render_admin_page() {
        if (!current_user_can('manage_options')) return;

        $api_key = get_option('zingtime_api_key');
        
        echo '<div class="zingtime-wrap">';
        settings_errors('zingtime_messages');

        if (!$api_key) {
            ?>
            <div style="display: flex; justify-content: center; align-items: center; min-height: 70vh;">
                <div style="background: #fff; padding: 40px; border-radius: 24px; max-width:500px; width:100%; box-shadow: 0 20px 40px rgba(0,0,0,0.08); border: 1px solid #e2e8f0; text-align: center;">
                    <div style="width: 80px; height: 80px; background: #eff6ff; border-radius: 20px; margin: 0 auto 20px; display: flex; align-items: center; justify-content: center;">
                        <svg style="width:40px; color:#3b82f6;" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1" /></svg>
                    </div>
                    <h2 style="font-size: 24px; font-weight: 900; color: #0f172a; margin: 0 0 10px 0;"><?php esc_html_e('اتصال به زینگ‌تایم', 'zingtime-booking'); ?></h2>
                    <p style="color: #64748b; margin-bottom: 30px; line-height:1.6; font-size: 14px;">
                        <?php esc_html_e('برای شروع، کلید API خود را از تنظیمات پنل کپی کرده و وارد کنید.', 'zingtime-booking'); ?>
                    </p>
                    <div style="margin-bottom:30px;">
    <a href="https://zingtime.ir/register"
       target="_blank"
       rel="noopener noreferrer"
       style="display:inline-block;background:#2563eb;color:#fff;padding:10px 18px;border-radius:8px;text-decoration:none;font-size:14px;font-weight:700;">
        <?php esc_html_e('ثبت‌نام و دریافت کد فعال‌سازی', 'zingtime-booking'); ?>
    </a>
</div>
                    <form method="post" action="">
                        <?php wp_nonce_field('zingtime_nonce_action', 'zingtime_nonce'); ?>
                        <input type="hidden" name="zingtime_action" value="verify_api_key">
                        <input type="text" name="api_key" placeholder="zn_*****************" required style="width: 100%; padding: 16px; margin-bottom: 20px; border-radius: 12px; border:2px solid #e2e8f0; direction:ltr; font-family:monospace; text-align:center; font-size:16px; background:#f8fafc; outline:none;">
                        <button type="submit" class="zingtime-btn zingtime-btn-primary" style="width: 100%; padding: 16px; font-size: 16px;"><?php esc_html_e('اتصال و راه‌اندازی سیستم 🚀', 'zingtime-booking'); ?></button>
                    </form>
                </div>
            </div>
            </div>
            <?php
            return;
        }

        $response = wp_remote_post(ZINGTIME_API_BASE_URL . '/dashboard', ['body' => ['api_key' => $api_key], 'sslverify' => false]);
        $http_code = wp_remote_retrieve_response_code($response);
        $data = is_wp_error($response) ? null : json_decode(wp_remote_retrieve_body($response), true);

        if ($http_code == 403 || (isset($data['is_basic']) && $data['is_basic'])) {
            ?>
            <div style="display: flex; justify-content: center; align-items: center; min-height: 70vh;">
                <div style="background: #fff; padding: 40px; border-radius: 24px; max-width:550px; width:100%; box-shadow: 0 20px 40px rgba(0,0,0,0.08); border: 1px solid #fecaca; text-align: center; position:relative; overflow:hidden;">
                    <div style="position:absolute; top:0; left:0; right:0; height:6px; background: linear-gradient(90deg, #e11d48, #f43f5e);"></div>
                    <h2 style="font-size: 24px; font-weight: 900; color: #be123c; margin: 0 0 10px 0;"><?php esc_html_e('نیاز به ارتقا به پکیج حرفه‌ای (Pro)', 'zingtime-booking'); ?></h2>
                    <p style="color: #881337; margin-bottom: 30px; line-height:1.8; font-size: 15px;">
                        <?php esc_html_e('پکیج شما پایه یا منقضی است. لطفاً آن را ارتقا دهید.', 'zingtime-booking'); ?>
                    </p>
                    <a href="https://zingtime.ir/panel/packages" target="_blank" class="zingtime-btn" style="background:#e11d48; color:#fff; width:100%; padding:16px; font-size:16px; box-shadow:0 4px 15px rgba(225,29,72,0.3);"><?php esc_html_e('ارتقا پکیج اکنون ⚡', 'zingtime-booking'); ?></a>
                    
                    <form method="post" style="margin-top:20px;">
                        <input type="hidden" name="zingtime_action" value="disconnect">
                        <?php wp_nonce_field('zingtime_nonce_action', 'zingtime_nonce'); ?>
                        <button type="button" onclick="zingtime_confirm_disconnect(this)" style="background:transparent; color:#94a3b8; border:none; text-decoration:underline; cursor:pointer; font-size:13px;"><?php esc_html_e('تغییر کلید API / قطع اتصال', 'zingtime-booking'); ?></button>
                    </form>
                </div>
            </div>
            </div>
            <?php
            return;
        }

        if (!$data || isset($data['error'])) {
            ?>
            <div style="background:#fee2e2; padding:20px; color:#991b1b; border-radius:12px; font-weight:bold; text-align:center;">
                <?php esc_html_e('خطا در دریافت اطلاعات از سرور.', 'zingtime-booking'); ?>
            </div>
            <form method="post" style="text-align:center; margin-top:20px;">
                <input type="hidden" name="zingtime_action" value="disconnect">
                <?php wp_nonce_field('zingtime_nonce_action', 'zingtime_nonce'); ?>
                <button type="button" onclick="zingtime_confirm_disconnect(this)" class="zingtime-btn zingtime-btn-danger-outline"><?php esc_html_e('قطع اتصال', 'zingtime-booking'); ?></button>
            </form>
            </div>
            <?php
            return;
        }

        $stats = $data['stats'];
        $upcoming = $data['upcoming'];
        $todayList = isset($data['today_list']) ? $data['today_list'] : [];

        ?>
        <div class="zingtime-header">
            <h1 class="zingtime-title"><?php esc_html_e('داشبورد نوبت‌دهی', 'zingtime-booking'); ?></h1>
            <div style="display:flex; gap: 10px;">
                <a href="https://zingtime.ir/panel/dashboard" target="_blank" class="zingtime-btn zingtime-btn-primary"><?php esc_html_e('رفتن به پنل مدیریت سایت 🚀', 'zingtime-booking'); ?></a>
                <form method="post" style="margin:0;">
                    <?php wp_nonce_field('zingtime_nonce_action', 'zingtime_nonce'); ?>
                    <input type="hidden" name="zingtime_action" value="disconnect">
                    <button type="button" onclick="zingtime_confirm_disconnect(this)" class="zingtime-btn zingtime-btn-danger-outline"><?php esc_html_e('قطع اتصال', 'zingtime-booking'); ?></button>
                </form>
            </div>
        </div>

        <div class="zingtime-shortcode-box zingtime-card">
            <div>
                <h3 style="margin:0 0 8px 0; color:#1e40af; font-size:18px; font-weight:900;"><?php esc_html_e('کد نمایش فرم رزرو', 'zingtime-booking'); ?></h3>
                <p style="margin:0; color:#3b82f6; font-size:14px; font-weight:600;"><?php esc_html_e('کد کوتاه مقابل را کپی کرده و در هر برگه یا نوشته‌ای که می‌خواهید، پیست کنید:', 'zingtime-booking'); ?></p>
            </div>
            <code class="zingtime-shortcode-code">[zingtime_booking]</code>
        </div>

        <div class="zingtime-grid-3">
            <div class="zingtime-card" style="border-right: 5px solid #3b82f6;">
                <div class="zingtime-stat-title"><?php esc_html_e('کل نوبت‌های ثبت شده', 'zingtime-booking'); ?></div>
                <div class="zingtime-stat-value"><?php echo esc_html($stats['total_bookings']); ?></div>
            </div>
            <div class="zingtime-card" style="border-right: 5px solid #10b981;">
                <div class="zingtime-stat-title"><?php esc_html_e('نوبت‌های امروز', 'zingtime-booking'); ?></div>
                <div class="zingtime-stat-value"><?php echo esc_html($stats['today_bookings']); ?></div>
            </div>
            <div class="zingtime-card" style="border-right: 5px solid #8b5cf6;">
                <div class="zingtime-stat-title"><?php esc_html_e('مجموع درآمد قطعی (ریال)', 'zingtime-booking'); ?></div>
                <div class="zingtime-stat-value"><?php echo esc_html($stats['total_revenue']); ?></div>
            </div>
        </div>

        <div class="zingtime-grid-2">
            <div class="zingtime-card">
                <h2 style="margin:0 0 20px 0; font-size:18px; font-weight:900; color:#0f172a; display:flex; align-items:center; gap:8px;">
                    <span style="display:inline-block; width:8px; height:8px; background:#3b82f6; border-radius:50%;"></span>
                    <?php esc_html_e('برنامه ۸ نوبت آینده شما', 'zingtime-booking'); ?>
                </h2>
                <div style="overflow-x:auto;">
                    <table class="zingtime-table">
                        <thead>
                            <tr>
                                <th><?php esc_html_e('مشتری', 'zingtime-booking'); ?></th>
                                <th><?php esc_html_e('موبایل', 'zingtime-booking'); ?></th>
                                <th><?php esc_html_e('سرویس / همکار', 'zingtime-booking'); ?></th>
                                <th><?php esc_html_e('زمان مراجعه', 'zingtime-booking'); ?></th>
                                <th><?php esc_html_e('وضعیت', 'zingtime-booking'); ?></th>
                            </tr>
                        </thead>
                        <tbody>
                            <?php if(empty($upcoming)): ?>
                                <tr><td colspan="5" class="zingtime-empty-state">
                                    <svg fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" /></svg>
                                    <br><?php esc_html_e('هیچ نوبت آینده‌ای در سیستم یافت نشد.', 'zingtime-booking'); ?>
                                </td></tr>
                            <?php else: ?>
                                <?php foreach($upcoming as $b): ?>
                                <tr>
                                    <td>
                                        <div style="font-weight:bold; color:#0f172a;"><?php echo esc_html($b['customer']); ?></div>
                                    </td>
                                    <td style="color:#64748b;" dir="ltr"><?php echo esc_html($b['phone']); ?></td>
                                    <td>
                                        <div style="font-weight:bold; color:#334155;"><?php echo esc_html($b['service']); ?></div>
                                        <div style="font-size:11px; color:#94a3b8; margin-top:4px;"><?php echo esc_html($b['provider']); ?></div>
                                    </td>
                                    <td style="font-weight:bold; color:#0f172a;" dir="ltr"><?php echo esc_html($b['date']); ?></td>
                                    <td>
                                        <?php
                                            $statusColors = [
                                                'pending' => 'background:#fffbeb; color:#b45309;',
                                                'confirmed' => 'background:#f0fdf4; color:#166534;',
                                                'completed' => 'background:#eff6ff; color:#1d4ed8;',
                                                'cancelled' => 'background:#fef2f2; color:#be123c;',
                                            ];
                                            $st_color = isset($statusColors[$b['status_en']]) ? $statusColors[$b['status_en']] : 'background:#f1f5f9; color:#475569;';
                                        ?>
                                        <span class="zingtime-badge" style="<?php echo esc_attr($st_color); ?>">
                                            <?php echo esc_html($b['status_fa']); ?>
                                        </span>
                                    </td>
                                </tr>
                                <?php endforeach; ?>
                            <?php endif; ?>
                        </tbody>
                    </table>
                </div>
            </div>

            <div class="zingtime-card" style="background: #fafaf9; border: 1px solid #e7e5e4;">
                <h2 style="margin:0 0 10px 0; font-size:18px; font-weight:900; color:#0f172a; display:flex; align-items:center; gap:8px;">
                    <span style="display:inline-block; width:8px; height:8px; background:#10b981; border-radius:50%; box-shadow:0 0 0 3px #d1fae5;"></span>
                    <?php esc_html_e('برنامه کاری امروز', 'zingtime-booking'); ?>
                </h2>
                <p style="font-size:13px; color:#64748b; margin:0 0 20px 0;"><?php esc_html_e('نوبت‌های رزرو شده برای امروز', 'zingtime-booking'); ?></p>
                
                <?php if(empty($todayList)): ?>
                    <div class="zingtime-empty-state" style="padding: 30px 10px;">
                        <svg fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M14.828 14.828a4 4 0 01-5.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
                        <br><?php esc_html_e('امروز برنامه‌ای ثبت نشده است!', 'zingtime-booking'); ?>
                    </div>
                <?php else: ?>
                    <div class="zingtime-timeline">
                        <?php foreach($todayList as $tb): ?>
                        <div class="zingtime-timeline-item">
                            <div class="zingtime-timeline-dot"></div>
                            <div class="zingtime-timeline-time" dir="ltr"><?php echo esc_html($tb['time']); ?></div>
                            <div class="zingtime-timeline-content">
                                <div style="font-weight:bold; color:#0f172a; font-size:15px; margin-bottom:4px;"><?php echo esc_html($tb['customer']); ?></div>
                                <div style="font-size:12px; color:#64748b;"><?php echo esc_html($tb['status_fa']); ?></div>
                            </div>
                        </div>
                        <?php endforeach; ?>
                    </div>
                <?php endif; ?>
            </div>
        </div>
        </div>
        <?php
    }

    public function zingtime_render_booking_shortcode($atts) {
        $api_key = get_option('zingtime_api_key');
        
        if (!$api_key) {
            return '<div style="padding:20px; background:#fef2f2; color:#be123c; border-radius:12px; text-align:center; font-family:tahoma, sans-serif; font-weight:bold;">' . esc_html__('سیستم نوبت‌دهی موقتاً غیرفعال است.', 'zingtime-booking') . '</div>';
        }

        wp_enqueue_style('zingtime-vazirmatn');
        wp_enqueue_script('zingtime-tailwindcss');
        wp_enqueue_script('zingtime-html2canvas');
        wp_enqueue_script('zingtime-jspdf');

        wp_register_script('zingtime-frontend-logic', false, array(), ZINGTIME_VERSION, true);
        wp_enqueue_script('zingtime-frontend-logic');

        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        $status_raw = isset($_GET['status']) ? sanitize_text_field(wp_unslash($_GET['status'])) : '';
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        $booking_id_raw = isset($_GET['booking_id']) ? sanitize_text_field(wp_unslash($_GET['booking_id'])) : '';
        
        $ajaxurl_raw = admin_url('admin-ajax.php');
        $nonce_raw = wp_create_nonce('zingtime_frontend_nonce');
        
        // Outputting HTML structure along with heavily enforced CSS to block theme font overrides
        $html_output = '<style>
            #zingtime-booking-app, 
            #zingtime-booking-app *, 
            #zingtime-booking-app *:before, 
            #zingtime-booking-app *:after,
            #zingtime-toast-container,
            #zingtime-toast-container * {
                font-family: "Vazir", Tahoma, Arial, sans-serif !important;
                box-sizing: border-box !important;
            }
            #zingtime-booking-app input,
            #zingtime-booking-app button {
                line-height: normal !important;
            }
            #zingtime-booking-app .hide-scrollbar::-webkit-scrollbar { display: none; }
            #zingtime-booking-app .hide-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
            #zingtime-booking-app .zingtime-blur { filter: blur(6px); opacity: 0.6; pointer-events: none; user-select: none; }
        </style>
        
        <div id="zingtime-booking-app" class="font-sans antialiased text-slate-800" dir="rtl" style="min-height: 500px; padding:20px 0; position:relative;">
            <div id="zingtime-toast-container" class="fixed top-5 left-1/2 transform -translate-x-1/2 z-[9999] flex flex-col gap-2 pointer-events-none"></div>
            
            <div id="zingtime-content" class="max-w-3xl mx-auto bg-white rounded-[2rem] shadow-2xl shadow-indigo-100/50 border border-slate-100 overflow-hidden relative transition-all duration-300 min-h-[400px]">
                
                <!-- Loading Overlay -->
                <div id="zingtime-loader-overlay" class="absolute inset-0 z-50 flex items-center justify-center bg-white/50 backdrop-blur-[2px] transition-all duration-300 rounded-[2rem]">
                    <div class="flex flex-col items-center gap-3 bg-white px-8 py-6 rounded-2xl shadow-xl shadow-indigo-100/50 border border-indigo-50">
                        <svg class="animate-spin h-10 w-10 text-indigo-600" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
                            <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
                            <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
                        </svg>
                        <span class="text-indigo-600 font-black text-sm">' . esc_html__('در حال بارگذاری...', 'zingtime-booking') . '</span>
                    </div>
                </div>
                
                <!-- Dynamic Content Viewport -->
                <div id="zingtime-dynamic-container" class="transition-all duration-300 h-full w-full"></div>
            </div>
        </div>';

        ob_start();
        ?>
        document.addEventListener('DOMContentLoaded', function() {
            const ajaxurl = "<?php echo esc_url($ajaxurl_raw); ?>";
            const wpNonce = "<?php echo esc_js($nonce_raw); ?>";
            const paymentStatus = "<?php echo esc_js($status_raw); ?>";
            const bookingId = "<?php echo esc_js($booking_id_raw); ?>";
            
            const app = document.getElementById('zingtime-dynamic-container');
            const loaderOverlay = document.getElementById('zingtime-loader-overlay');
            const toastContainer = document.getElementById('zingtime-toast-container');
            const pageUrl = window.location.href.split('?')[0]; 

            let state = {
                currentStep: 1, service: null, provider: null, date: null, time: null,
                duration: 0, checkoutInfo: null, discountCode: null, discountAmount: 0, referralCode: null
            };

            function showLoader() { 
                loaderOverlay.classList.remove('hidden', 'opacity-0'); 
                loaderOverlay.classList.add('flex', 'opacity-100');
                app.classList.add('zingtime-blur');
            }
            
            function hideLoader() { 
                loaderOverlay.classList.remove('opacity-100');
                loaderOverlay.classList.add('opacity-0');
                setTimeout(() => { 
                    loaderOverlay.classList.remove('flex');
                    loaderOverlay.classList.add('hidden'); 
                }, 300);
                app.classList.remove('zingtime-blur');
            }

            window.zingtime_show_toast = function(message, type = 'error') {
                const toast = document.createElement('div');
                const bgColor = type === 'error' ? 'bg-rose-500' : (type === 'success' ? 'bg-emerald-500' : 'bg-indigo-500');
                toast.className = `${bgColor} text-white px-6 py-3 rounded-2xl shadow-xl font-bold text-sm transform transition-all duration-300 translate-y-[-100%] opacity-0 pointer-events-auto flex items-center gap-2`;
                toast.innerHTML = `<span>${message}</span> <button type="button" onclick="this.parentElement.remove()" class="opacity-70 hover:opacity-100 text-lg leading-none">&times;</button>`;
                
                toastContainer.appendChild(toast);
                setTimeout(() => { toast.classList.remove('translate-y-[-100%]', 'opacity-0'); toast.classList.add('translate-y-0', 'opacity-100'); }, 10);
                setTimeout(() => { toast.classList.remove('translate-y-0', 'opacity-100'); toast.classList.add('translate-y-[-100%]', 'opacity-0'); setTimeout(() => toast.remove(), 300); }, 5000);
            };

            function apiCall(action, payload = {}) {
                const params = new URLSearchParams();
                params.append('action', 'zingtime_api_proxy');
                params.append('action_type', action);
                params.append('nonce', wpNonce); 
                Object.entries(payload).forEach(([k, v]) => params.append(`payload[${k}]`, v));

                return fetch(ajaxurl, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                    body: params
                }).then(res => res.json()).then(res => {
                    if(!res.success && res.error) throw new Error(res.error);
                    if(!res.success && res.data && res.data.message) throw new Error(res.data.message);
                    return res;
                });
            }

            function renderStepper(step) {
                const steps = ['خدمات', 'همکار', 'زمان', 'تایید'];
                let html = '<div class="px-2 md:px-10 pt-8 pb-6 bg-slate-50/80 border-b border-slate-100"><div class="flex items-start justify-between relative max-w-md mx-auto z-10">';
                
                // Track Connector backgrounds and active fill
                html += '<div class="absolute left-6 right-6 md:left-8 md:right-8 top-4 md:top-5 h-1 md:h-1.5 z-0 bg-slate-200 rounded-full overflow-hidden">';
                html += '<div class="absolute right-0 top-0 bottom-0 bg-indigo-500 transition-all duration-700 ease-in-out" style="width: '+ ((step-1)/3)*100 +'%;"></div>';
                html += '</div>';

                steps.forEach((s, i) => {
                    let sNum = i + 1;
                    let active = sNum === step;
                    let passed = sNum < step;
                    let circleClass = active ? 'bg-indigo-600 text-white shadow-lg shadow-indigo-300 ring-4 ring-indigo-50 scale-110' : (passed ? 'bg-indigo-500 text-white' : 'bg-white text-slate-400 border-2 border-slate-200');
                    
                    html += `<div class="flex flex-col items-center gap-2 z-10 relative w-12 md:w-16">
                                <div class="w-8 h-8 md:w-10 md:h-10 rounded-full flex items-center justify-center font-black text-sm md:text-base transition-all duration-300 ${circleClass} relative z-10">
                                    ${passed ? '<svg class="w-4 h-4 md:w-5 md:h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M5 13l4 4L19 7"/></svg>' : sNum}
                                </div>
                                <span class="text-[10px] md:text-xs font-bold whitespace-nowrap ${active ? 'text-indigo-700' : (passed ? 'text-slate-700' : 'text-slate-400')}">${s}</span>
                            </div>`;
                });
                html += '</div></div>';
                return html;
            }

            function renderHeader(title, subtitle, backStep) {
                let backBtn = backStep ? `<button type="button" onclick="window.goBack(${backStep})" class="inline-flex items-center gap-1.5 text-slate-500 hover:text-indigo-600 font-bold text-xs md:text-sm bg-slate-100 hover:bg-indigo-50 px-4 py-2 rounded-xl transition-all shadow-sm">بازگشت</button>` : '';
                return `<div class="px-6 md:px-10 py-6 flex items-start justify-between">
                            <div>
                                <h2 class="text-xl md:text-2xl font-black text-slate-800">${title}</h2>
                                <p class="text-xs md:text-sm font-medium text-slate-500 mt-1">${subtitle}</p>
                            </div>
                            ${backBtn}
                        </div>`;
            }

            window.goBack = function(step) {
                if (step === 2 && window.servicesData) {
                    const selectedService = window.servicesData.find(s => s.id == state.service.id);
                    if (selectedService && selectedService.providers.length === 1) step = 1;
                }
                
                if (step === 1) { state.provider = null; state.date = null; state.time = null; window.loadServices(); } 
                else if (step === 2) { state.date = null; state.time = null; const selectedService = window.servicesData.find(s => s.id == state.service.id); window.loadProviders(selectedService.providers); } 
                else if (step === 3) { window.loadTimes(); }
            };

            window.downloadPDF = function(id) {
                const btn = document.getElementById('zingtime-download-btn');
                const progressBar = document.getElementById('zingtime-progress-bar');
                const btnText = document.getElementById('zingtime-btn-text');
                if (btn.disabled) return;
                
                btn.disabled = true; btn.classList.add('cursor-not-allowed'); btn.classList.remove('hover:bg-slate-700');
                
                let progress = 0;
                btnText.innerHTML = `در حال پردازش... ${progress}٪`;
                
                const interval = setInterval(() => {
                    progress += Math.floor(Math.random() * 20) + 10; 
                    if (progress >= 85) {
                        progress = 85; clearInterval(interval);
                        setTimeout(() => { generatePDF(id, btn, progressBar, btnText); }, 50);
                    }
                    progressBar.style.width = progress + '%';
                    btnText.innerHTML = `در حال پردازش... ${progress}٪`;
                }, 100);
            };

            function generatePDF(id, btn, progressBar, btnText) {
                const element = document.getElementById('invoice-card');
                html2canvas(element, { 
                    scale: 2, useCORS: false, allowTaint: false, logging: false, imageTimeout: 1500,
                    ignoreElements: function(node) { const tag = node.tagName ? node.tagName.toUpperCase() : ''; return (tag === 'IMG' || tag === 'IFRAME'); }
                }).then(canvas => {
                    progressBar.style.width = '100%';
                    btnText.innerHTML = `دریافت فایل... 100٪`;

                    const imgData = canvas.toDataURL('image/jpeg', 0.8);
                    const { jsPDF } = window.jspdf;
                    const pdf = new jsPDF('p', 'mm', 'a4');
                    const pdfWidth = pdf.internal.pageSize.getWidth();
                    const pdfHeight = (canvas.height * pdfWidth) / canvas.width;
                    
                    pdf.addImage(imgData, 'JPEG', 0, 10, pdfWidth, pdfHeight);
                    pdf.save('ZingTime_Invoice_' + id + '.pdf');
                    
                    setTimeout(() => {
                        progressBar.style.width = '0%';
                        btnText.innerHTML = `دانلود فاکتور (PDF)`;
                        btn.disabled = false; btn.classList.remove('cursor-not-allowed'); btn.classList.add('hover:bg-slate-700');
                    }, 2000);

                }).catch(err => {
                    window.zingtime_show_toast('خطا در تولید فایل فاکتور.', 'error');
                    progressBar.style.width = '0%';
                    btnText.innerHTML = `دانلود فاکتور مجدد`;
                    btn.disabled = false; btn.classList.remove('cursor-not-allowed'); btn.classList.add('hover:bg-slate-700');
                });
            }

            window.applyDiscount = function() {
                const code = document.getElementById('zingtime_discount_input').value.trim();
                if(!code) return;
                
                const msgEl = document.getElementById('zingtime_discount_msg');
                msgEl.className = 'mt-2 text-xs font-bold text-indigo-500 block';
                msgEl.innerText = 'در حال بررسی...';

                apiCall('check-discount', { code: code, service_id: state.service.id }).then(res => {
                    msgEl.className = 'mt-2 text-xs font-bold text-emerald-600 block';
                    msgEl.innerText = '✅ ' + res.message;
                    state.discountCode = code;
                    
                    let factorDiv = document.getElementById('zingtime_factor_container');
                    let discountRow = document.getElementById('zingtime_factor_discount');
                    if(!discountRow) {
                        discountRow = document.createElement('div');
                        discountRow.id = 'zingtime_factor_discount';
                        discountRow.className = 'flex justify-between text-emerald-600 font-medium';
                        factorDiv.insertBefore(discountRow, document.getElementById('zingtime_factor_fee'));
                    }
                    discountRow.innerHTML = `<span>تخفیف اعمال شده:</span> <span>${Number(res.discount_amount).toLocaleString()} ریال</span>`;
                    
                    const feeRow = document.getElementById('zingtime_factor_fee');
                    if (feeRow) {
                        if (res.platform_fee > 0) {
                            feeRow.innerHTML = `<span>خدمات سیستم آنلاین:</span> <span>${Number(res.platform_fee).toLocaleString()} ریال</span>`;
                            feeRow.classList.remove('hidden');
                        } else {
                            feeRow.classList.add('hidden');
                        }
                    }
                    document.getElementById('zingtime_factor_final').innerText = Number(res.final_price).toLocaleString() + ' ریال';
                    document.getElementById('zingtime_pay_text').innerText = Number(res.final_price) === 0 ? 'تایید و ثبت نهایی (رایگان)' : 'اتصال به درگاه و پرداخت';
                }).catch(err => {
                    msgEl.className = 'mt-2 text-xs font-bold text-rose-500 block';
                    msgEl.innerText = '❌ ' + err.message;
                    state.discountCode = null;
                });
            };

            window.applyReferral = function() {
                const code = document.getElementById('zingtime_referral_input').value.trim();
                const phone = document.getElementById('zingtime_phone').value.trim();
                const msgEl = document.getElementById('zingtime_referral_msg');
                
                if(!code) return;
                if(!phone) { msgEl.className = 'mt-2 text-xs font-bold text-rose-500 block'; msgEl.innerText = '❌ لطفا ابتدا شماره موبایل خود را در فرم بالا وارد کنید.'; return; }

                msgEl.className = 'mt-2 text-xs font-bold text-indigo-500 block';
                msgEl.innerText = 'در حال بررسی...';

                apiCall('check-referral', { code: code, customer_phone: phone }).then(res => {
                    msgEl.className = 'mt-2 text-xs font-bold text-emerald-600 block';
                    msgEl.innerText = '✅ ' + res.message;
                    state.referralCode = code;
                }).catch(err => {
                    msgEl.className = 'mt-2 text-xs font-bold text-rose-500 block';
                    msgEl.innerText = '❌ ' + err.message;
                    state.referralCode = null;
                });
            };

            window.selectService = function(id, name) {
                state.service = { id, name };
                const selected = window.servicesData.find(s => s.id == id);
                if (!selected.providers || selected.providers.length === 0) { window.zingtime_show_toast('پرسنلی برای این سرویس یافت نشد.', 'error'); return; }
                if (selected.providers.length === 1) { window.selectProvider(selected.providers[0].id, selected.providers[0].name); } else { window.loadProviders(selected.providers); }
            };

            window.selectProvider = function(id, name) { state.provider = { id, name }; window.loadTimes(); };

            window.showSlots = function(dateStr, btnElement) {
                document.querySelectorAll('.date-btn').forEach(b => {
                    b.className = "date-btn flex-shrink-0 w-[115px] md:w-[130px] overflow-hidden border border-slate-200 rounded-[1.25rem] px-2 py-3 flex flex-col items-center justify-center hover:bg-indigo-50/50 hover:border-indigo-300 focus:outline-none transition-all bg-white text-slate-600";
                    b.querySelector('span:first-child').classList.replace('opacity-90', 'text-slate-400');
                });
                btnElement.className = "date-btn flex-shrink-0 w-[115px] md:w-[130px] overflow-hidden border-2 border-indigo-500 rounded-[1.25rem] px-2 py-3 flex flex-col items-center justify-center transition-all bg-indigo-50/50 text-indigo-800 shadow-sm";
                btnElement.querySelector('span:first-child').classList.replace('text-slate-400', 'opacity-90');

                const config = window.calendarConfig;
                let slotsHtml = '';
                const parseTime = t => { let p = t.split(':'); return parseInt(p[0])*60 + parseInt(p[1]); };
                let startMin = parseTime(config.work_start); let endMin = parseTime(config.work_end);
                
                let todayFa = new Intl.DateTimeFormat('fa-IR', { year:'numeric', month:'2-digit', day:'2-digit'}).format(new Date()).replace(/[۰-۹]/g, d => '۰۱۲۳۴۵۶۷۸۹'.indexOf(d));
                if (dateStr === todayFa) {
                    let nowMin = new Date().getHours() * 60 + new Date().getMinutes();
                    if (startMin < nowMin) startMin = nowMin + (15 - (nowMin % 15)); 
                }

                let unavails = config.unavailableTimes[dateStr] || [];
                let duration = parseInt(config.duration);
                let curr = startMin; let hasSlots = false;

                while (curr + duration <= endMin) {
                    let slotStartFormat = `${Math.floor(curr/60).toString().padStart(2,'0')}:${(curr%60).toString().padStart(2,'0')}`;
                    let slotEndMin = curr + duration;
                    let isBlocked = false;
                    for (let u of unavails) {
                        let uS = parseTime(u.start); let uE = parseTime(u.end);
                        if (curr < uE && slotEndMin > uS && u.is_full) { isBlocked = true; break; }
                    }
                    if (!isBlocked) {
                        hasSlots = true;
                        // تغییرات برای هایلایت و دیده شدن بیشتر باکس زمان
                        slotsHtml += `<button type="button" onclick="window.selectTime('${dateStr}', '${slotStartFormat}')" class="py-3 px-2 rounded-2xl border-2 border-indigo-200 bg-indigo-50 text-indigo-800 font-black hover:bg-indigo-600 hover:text-white hover:border-indigo-600 shadow-sm hover:shadow-md transition-all text-sm md:text-base">${slotStartFormat}</button>`;
                    }
                    curr += duration;
                }
                const container = document.getElementById('time-slots');
                if(hasSlots) container.innerHTML = slotsHtml;
                else container.innerHTML = `<div class="col-span-full text-center py-10 bg-slate-50 rounded-xl text-slate-500 font-bold border border-dashed border-slate-200">هیچ ظرفیت خالی برای این روز وجود ندارد.</div>`;
            };

            window.selectTime = function(date, time) { state.date = date; state.time = time; window.loadCheckout(); };

            window.loadServices = function() {
                showLoader();
                state.currentStep = 1;
                apiCall('services').then(data => {
                    hideLoader();
                    let html = renderStepper(1) + renderHeader('انتخاب خدمات', 'لطفا سرویس مورد نظر خود را انتخاب کنید', null) + `<div class="px-6 md:px-10 pb-10 grid grid-cols-1 sm:grid-cols-2 gap-4">`;
                    
                    if(data.services.length === 0) {
                        html += `<div class="col-span-full text-center py-10 text-slate-400 font-bold border-2 border-dashed border-slate-200 rounded-3xl">هیچ سرویس فعالی یافت نشد.</div>`;
                    }

                    data.services.forEach(s => {
                        html += `
                        <div onclick="window.selectService(${s.id}, '${s.name}')" class="cursor-pointer bg-white border border-slate-200 hover:border-indigo-400 hover:shadow-xl rounded-[2rem] p-6 transition-all group overflow-hidden relative">
                            <div class="absolute -right-4 -top-4 w-20 h-20 bg-indigo-50/50 rounded-full group-hover:scale-150 transition-transform duration-500 z-0"></div>
                            <div class="relative z-10">
                                <h3 class="font-black text-lg text-slate-800 group-hover:text-indigo-700 mb-4">${s.name}</h3>
                                <div class="flex items-center gap-3 text-xs font-bold text-slate-600">
                                    <span class="bg-slate-50 px-3 py-2 rounded-xl flex items-center gap-1.5 border border-slate-100 group-hover:border-indigo-100 group-hover:bg-white"><svg class="w-4 h-4 text-slate-500 opacity-70" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" /></svg> ${s.duration_minutes} دقیقه</span>
                                    <span class="bg-slate-50 px-3 py-2 rounded-xl flex items-center gap-1.5 border border-slate-100 group-hover:border-indigo-100 group-hover:bg-white"><svg class="w-4 h-4 text-slate-500 opacity-70" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h18M7 15h1m4 0h1m-7 4h12a3 3 0 003-3V8a3 3 0 00-3-3H6a3 3 0 00-3 3v8a3 3 0 003 3z" /></svg> ${Number(s.price).toLocaleString()} ریال</span>
                                </div>
                            </div>
                        </div>`;
                    });
                    html += `</div>`;
                    app.innerHTML = html;
                    window.servicesData = data.services;
                }).catch(err => {
                    hideLoader(); app.innerHTML = `<div class="p-10 text-center text-rose-500 font-bold bg-rose-50 rounded-[2rem] m-6">امکان ثبت نوبت وجود ندارد: ${err.message}</div>`;
                });
            };

            window.loadProviders = function(providers) {
                state.currentStep = 2;
                let html = renderStepper(2) + renderHeader('انتخاب همکار', `سرویس: <b class="text-indigo-600">${state.service.name}</b>`, 1) + `<div class="px-6 md:px-10 pb-10 grid grid-cols-2 sm:grid-cols-3 gap-4">`;
                
                providers.forEach(p => {
                    let avatarHtml = '';
                    if(p.image_url) {
                        avatarHtml = `<img src="${p.image_url}" class="w-20 h-20 rounded-full mx-auto object-cover border-4 border-white shadow-md mb-4 group-hover:scale-105 transition-transform duration-300 relative z-10">`;
                    } else {
                        avatarHtml = `<div class="w-20 h-20 bg-indigo-100 text-indigo-600 rounded-full mx-auto flex items-center justify-center text-3xl font-black mb-4 border-4 border-white shadow-md group-hover:scale-105 transition-transform duration-300 relative z-10">${p.name.charAt(0)}</div>`;
                    }

                    html += `<div onclick="window.selectProvider(${p.id}, '${p.name}')" class="cursor-pointer bg-slate-50 border border-slate-100 hover:border-indigo-300 hover:bg-white hover:shadow-xl rounded-[2rem] p-6 text-center transition-all group relative overflow-hidden">
                        <div class="absolute inset-0 bg-gradient-to-b from-indigo-50/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity z-0"></div>
                        ${avatarHtml}
                        <h3 class="font-black text-slate-800 text-sm relative z-10 group-hover:text-indigo-700">${p.name}</h3>
                    </div>`;
                });
                html += `</div>`;
                app.innerHTML = html;
            };

            window.loadTimes = function() {
                showLoader();
                state.currentStep = 3;
                apiCall('times', { service_id: state.service.id, provider_id: state.provider.id }).then(data => {
                    hideLoader();
                    state.duration = data.duration;
                    window.renderCalendar(data);
                }).catch(err => {
                    hideLoader(); window.zingtime_show_toast(err.message, 'error'); window.location.reload();
                });
            };

            window.renderCalendar = function(data) {
                let html = renderStepper(3) + renderHeader('انتخاب زمان', `سرویس: <b class="text-indigo-600 ml-2">${state.service.name}</b> | <span class="mr-2">همکار: <b class="text-indigo-600">${state.provider.name}</b></span>`, 2) + `
                <div class="px-6 md:px-10 pb-10">
                    <div class="relative group">
                        
                        <!-- فلش سمت راست (رفتن به قبل) -->
                        <div id="slider-right-wrap" class="absolute right-0 top-0 bottom-6 w-16 bg-gradient-to-l from-white via-white to-transparent flex items-center justify-start z-10 pointer-events-none transition-opacity duration-300 opacity-0">
                            <button type="button" onclick="document.getElementById('date-slider').scrollBy({left: 150, behavior: 'smooth'})" class="pointer-events-auto mr-1 w-8 h-8 flex items-center justify-center rounded-full bg-white border border-slate-200 shadow-sm text-slate-600 hover:text-indigo-600 hover:border-indigo-300 hover:bg-indigo-50 transition-all">
                                <svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/></svg>
                            </button>
                        </div>
                        
                        <!-- فلش سمت چپ (رفتن به جلو) -->
                        <div id="slider-left-wrap" class="absolute left-0 top-0 bottom-6 w-16 bg-gradient-to-r from-white via-white to-transparent flex items-center justify-end z-10 pointer-events-none transition-opacity duration-300 opacity-0">
                            <button type="button" onclick="document.getElementById('date-slider').scrollBy({left: -150, behavior: 'smooth'})" class="pointer-events-auto ml-1 w-8 h-8 flex items-center justify-center rounded-full bg-white border border-slate-200 shadow-sm text-slate-600 hover:text-indigo-600 hover:border-indigo-300 hover:bg-indigo-50 transition-all">
                                <svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/></svg>
                            </button>
                        </div>

                        <div class="flex overflow-x-auto gap-3 pb-6 hide-scrollbar scroll-smooth relative z-0" id="date-slider" onscroll="window.updateSliderArrows()">`;
                
                const dates = []; let currDate = new Date(); let validDaysFound = 0;
                while(validDaysFound < Math.min(14, data.maxBookingDays)) {
                    let faDate = new Intl.DateTimeFormat('fa-IR', { year:'numeric', month:'2-digit', day:'2-digit'}).format(currDate).replace(/[۰-۹]/g, d => '۰۱۲۳۴۵۶۷۸۹'.indexOf(d));
                    let dayOfWeek = currDate.getDay(); let mappedDay = dayOfWeek === 6 ? 1 : dayOfWeek + 2; 
                    let isBlocked = data.fullDayBlocks.includes(faDate);
                    let isWorkDay = data.allowedDaysOfWeek.length === 0 || data.allowedDaysOfWeek.includes(mappedDay.toString()) || data.allowedDaysOfWeek.includes(mappedDay);

                    if (!isBlocked && isWorkDay) {
                        let dayName = new Intl.DateTimeFormat('fa-IR', { weekday: 'long' }).format(currDate);
                        let shortDate = new Intl.DateTimeFormat('fa-IR', { month:'long', day:'numeric'}).format(currDate);
                        dates.push({ full: faDate, label: dayName, short: shortDate });
                        validDaysFound++;
                    }
                    currDate.setDate(currDate.getDate() + 1);
                }

                dates.forEach((d, idx) => {
                    html += `<button type="button" onclick="window.showSlots('${d.full}', this)" class="date-btn flex-shrink-0 w-[115px] md:w-[130px] overflow-hidden border border-slate-200 rounded-[1.25rem] px-2 py-3 flex flex-col items-center justify-center hover:bg-indigo-50/50 hover:border-indigo-300 focus:outline-none transition-all ${idx===0 ? 'bg-indigo-50/50 border-2 border-indigo-500 text-indigo-800 shadow-sm' : 'bg-white text-slate-600'}">
                        <span class="block w-full text-center text-[11px] md:text-xs font-bold mb-1.5 whitespace-nowrap overflow-hidden text-ellipsis leading-none ${idx===0 ? 'opacity-90' : 'text-slate-400'}">${d.label}</span>
                        <span class="block w-full text-center font-black text-sm md:text-base whitespace-nowrap overflow-hidden text-ellipsis leading-none" style="line-height:1.2;">${d.short}</span>
                    </button>`;
                });
                
                html += `</div>
                    </div>
                    <div class="mt-2 pt-6 border-t border-slate-100">
                        <h4 class="font-bold text-slate-800 text-sm mb-4">ساعت‌های آزاد</h4>
                        <div id="time-slots" class="grid grid-cols-3 sm:grid-cols-4 md:grid-cols-5 gap-3"></div>
                    </div>
                </div>`;
                app.innerHTML = html;
                window.calendarConfig = data;
                if(dates.length > 0) window.showSlots(dates[0].full, document.querySelector('.date-btn'));
                
                // بررسی نمایش فلش‌ها با تاخیر کوتاه برای رندر شدن DOM
                setTimeout(() => window.updateSliderArrows(), 100);
            };

            window.updateSliderArrows = function() {
                const slider = document.getElementById('date-slider');
                const rightWrap = document.getElementById('slider-right-wrap');
                const leftWrap = document.getElementById('slider-left-wrap');
                if (!slider) return;
                
                // اگر محتوا بیشتر از کادر باشد یعنی اسکرول لازم دارد
                if (slider.scrollWidth > slider.clientWidth) {
                    if(rightWrap) rightWrap.classList.replace('opacity-0', 'opacity-100');
                    if(leftWrap) leftWrap.classList.replace('opacity-0', 'opacity-100');
                } else {
                    if(rightWrap) rightWrap.classList.replace('opacity-100', 'opacity-0');
                    if(leftWrap) leftWrap.classList.replace('opacity-100', 'opacity-0');
                }
            };

            window.loadCheckout = function() {
                showLoader();
                state.currentStep = 4;
                apiCall('checkout', { service_id: state.service.id }).then(data => {
                    hideLoader();
                    state.checkoutInfo = data;
                    
                    let html = renderStepper(4) + renderHeader('تکمیل اطلاعات', 'لطفاً مشخصات خود را جهت ثبت نهایی وارد نمایید', 3) + `
                    <form id="zingtime-checkout-form" class="px-6 md:px-10 pb-10 flex flex-col md:flex-row gap-8">
                        <div class="flex-1 space-y-6">
                            <div class="bg-slate-50 p-5 rounded-[1.5rem] border border-slate-100 space-y-3 text-sm">
                                <div class="flex justify-between items-center pb-3 border-b border-slate-200/60"><span class="text-slate-500">سرویس انتخابی:</span> <span class="font-bold text-slate-800">${state.service.name}</span></div>
                                <div class="flex justify-between items-center pb-3 border-b border-slate-200/60"><span class="text-slate-500">همکار (پرسنل):</span> <span class="font-bold text-slate-800">${state.provider.name}</span></div>
                                <div class="flex justify-between items-center"><span class="text-slate-500">زمان مراجعه:</span> <span class="font-black text-indigo-700 bg-indigo-100/50 px-3 py-1 rounded-xl" dir="ltr">${state.date} - ${state.time}</span></div>
                            </div>
                            
                            <div class="space-y-4">
                                <div>
                                    <label class="block text-sm font-bold text-slate-700 mb-2">نام و نام خانوادگی <span class="text-rose-500">*</span></label>
                                    <input type="text" id="zingtime_name" required maxlength="150" class="w-full px-5 py-3.5 bg-slate-50 border border-slate-200 rounded-[1.5rem] focus:bg-white focus:ring-2 focus:ring-indigo-500 outline-none transition-all" placeholder="مثال: علی محمدی">
                                </div>
                                <div>
                                    <label class="block text-sm font-bold text-slate-700 mb-2">شماره موبایل <span class="text-rose-500">*</span></label>
                                    <input type="tel" id="zingtime_phone" required pattern="^09[0-9]{9}$" maxlength="11" minlength="11" oninput="this.value = this.value.replace(/[^0-9]/g, '')" placeholder="0912..." dir="ltr" class="w-full px-5 py-3.5 bg-slate-50 border border-slate-200 rounded-[1.5rem] focus:bg-white focus:ring-2 focus:ring-indigo-500 outline-none transition-all text-left font-mono font-bold tracking-widest text-lg">
                                </div>
                            </div>

                            ${(data.has_discounts === true || data.is_referral_active === true) ? `
                            <div class="flex flex-col gap-4 pt-6 border-t border-slate-100 mt-6">
                                <h4 class="font-bold text-slate-800 text-sm">تخفیف و باشگاه مشتریان</h4>
                                
                                ${data.has_discounts === true ? `
                                <div>
                                    <div class="flex flex-col sm:flex-row gap-2">
                                        <input type="text" id="zingtime_discount_input" maxlength="150" placeholder="کد تخفیف خود را وارد کنید" class="flex-1 px-5 py-3.5 bg-white border border-slate-200 rounded-[1.5rem] focus:ring-2 focus:ring-indigo-500 outline-none transition-all text-sm uppercase text-center sm:text-right" dir="ltr">
                                        <button type="button" onclick="window.applyDiscount()" class="w-full sm:w-auto bg-slate-800 hover:bg-slate-700 text-white px-8 py-3.5 rounded-[1.5rem] font-bold text-sm transition-colors whitespace-nowrap">اعمال تخفیف</button>
                                    </div>
                                    <div id="zingtime_discount_msg" class="hidden mt-2 text-xs font-bold px-2"></div>
                                </div>` : ''}

                                ${data.is_referral_active === true ? `
                                <div>
                                    <div class="flex flex-col sm:flex-row gap-2">
                                        <input type="text" id="zingtime_referral_input" maxlength="100" placeholder="کد معرف (اختیاری)" class="flex-1 px-5 py-3.5 bg-white border border-slate-200 rounded-[1.5rem] focus:ring-2 focus:ring-indigo-500 outline-none transition-all text-sm uppercase text-center sm:text-right" dir="ltr">
                                        <button type="button" onclick="window.applyReferral()" class="w-full sm:w-auto bg-slate-800 hover:bg-slate-700 text-white px-8 py-3.5 rounded-[1.5rem] font-bold text-sm transition-colors whitespace-nowrap">بررسی معرف</button>
                                    </div>
                                    <div id="zingtime_referral_msg" class="hidden mt-2 text-xs font-bold px-2"></div>
                                </div>` : ''}
                            </div>
                            ` : ''}
                        </div>

                        <div class="w-full md:w-5/12 bg-slate-50/80 rounded-[2rem] p-6 border border-slate-100 h-fit">
                            <h3 class="font-black text-slate-800 mb-5 pb-4 border-b border-slate-200 flex items-center gap-2">
                                <svg class="w-5 h-5 text-indigo-500" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/></svg>
                                فاکتور نهایی
                            </h3>
                            
                            <div class="space-y-4 mb-8 text-sm" id="zingtime_factor_container">
                                <div class="flex justify-between text-slate-600 font-medium"><span>هزینه پایه سرویس:</span> <span id="zingtime_factor_base">${Number(data.base_price).toLocaleString()} ریال</span></div>
                                <div id="zingtime_factor_fee" class="flex justify-between text-slate-600 font-medium ${data.platform_fee > 0 ? '' : 'hidden'}"><span>خدمات سیستم آنلاین:</span> <span>${Number(data.platform_fee).toLocaleString()} ریال</span></div>
                                
                                <div class="flex justify-between items-center font-black text-lg text-slate-900 pt-5 border-t border-slate-200 mt-5">
                                    <span style=" font-size: 12px; font-weight: bolder; ">مبلغ قابل پرداخت:</span> 
                                    <span id="zingtime_factor_final" class="text-indigo-700 bg-white border border-indigo-100 shadow-sm px-4 py-1.5 rounded-xl">${Number(data.final_price).toLocaleString()} ریال</span>
                                </div>
                            </div>

                            <button type="submit" id="zingtime-pay-btn" class="w-full bg-emerald-500 hover:bg-emerald-600 text-white py-4 rounded-[1.5rem] font-black text-lg transition-all shadow-xl shadow-emerald-500/30 flex justify-center items-center gap-2 transform hover:-translate-y-1">
                                <svg class="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 9V7a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2m2 4h10a2 2 0 002-2v-6a2 2 0 00-2-2H9a2 2 0 00-2 2v6a2 2 0 002 2zm7-5a2 2 0 11-4 0 2 2 0 014 0z" /></svg>
                                <span id="zingtime_pay_text">${Number(data.final_price) === 0 ? 'تایید و ثبت نهایی (رایگان)' : 'اتصال به درگاه'}</span>
                            </button>
                        </div>
                    </form>`;
                    app.innerHTML = html;

                    document.getElementById('zingtime-checkout-form').addEventListener('submit', function(e) {
                        e.preventDefault();
                        const btn = document.getElementById('zingtime-pay-btn');
                        btn.querySelector('#zingtime_pay_text').innerText = 'در حال ارتباط امن...'; 
                        btn.disabled = true; btn.classList.add('opacity-70', 'cursor-not-allowed');

                        let payload = {
                            service_id: state.service.id,
                            provider_id: state.provider.id,
                            date: state.date,
                            time: state.time,
                            customer_name: document.getElementById('zingtime_name').value,
                            customer_phone: document.getElementById('zingtime_phone').value,
                            callback_url: pageUrl 
                        };

                        if (state.discountCode) payload.discount_code = state.discountCode;
                        if (state.referralCode) payload.referral_code = state.referralCode;

                        apiCall('book', payload).then(res => {
                            if(res.redirect_url) { window.location.href = res.redirect_url; }
                        }).catch(err => {
                            window.zingtime_show_toast(err.message, 'error');
                            btn.querySelector('#zingtime_pay_text').innerText = 'تلاش مجدد'; 
                            btn.disabled = false; btn.classList.remove('opacity-70', 'cursor-not-allowed');
                        });
                    });
                }).catch(err => {
                    hideLoader(); window.zingtime_show_toast(err.message, 'error'); window.location.reload();
                });
            };

            if (paymentStatus === 'success' && bookingId) {
                // مخفی کردن لودینگ ابتدایی و نمایش وضعیت دریافت فاکتور
                hideLoader();
                app.innerHTML = `<div class="p-12 text-center text-indigo-500 font-bold animate-pulse">در حال دریافت و ساخت فاکتور نهایی...</div>`;

                apiCall('booking-details', { booking_id: bookingId }).then(data => {
                    app.innerHTML = `
                    <div class="p-8 md:p-12 bg-slate-50/50 h-full">
                        <div id="invoice-card" class="bg-white p-8 rounded-[2rem] shadow-sm border border-slate-200 max-w-lg mx-auto relative overflow-hidden">
                            <div class="absolute top-0 left-0 w-full h-2 bg-emerald-500"></div>
                            <div class="text-center mb-6 mt-4">
                                <div class="w-16 h-16 bg-emerald-50 border border-emerald-100 rounded-full flex items-center justify-center mx-auto mb-4">
                                    <svg class="w-8 h-8 text-emerald-500" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M5 13l4 4L19 7" /></svg>
                                </div>
                                <h2 class="text-2xl font-black text-slate-800">نوبت با موفقیت ثبت شد</h2>
                                <p class="text-slate-500 text-sm mt-1 font-mono">شناسه: ${data.id}</p>
                            </div>
                            
                            <div class="space-y-4 mb-8 bg-slate-50/50 p-6 rounded-3xl border border-slate-100">
                                <div class="flex justify-between pb-3 border-b border-slate-200/60"><span class="text-slate-500 font-medium">مجموعه:</span> <span class="font-bold text-slate-800">${data.business_name}</span></div>
                                <div class="flex justify-between pb-3 border-b border-slate-200/60"><span class="text-slate-500 font-medium">نام شما:</span> <span class="font-bold text-slate-800">${data.customer_name}</span></div>
                                <div class="flex justify-between pb-3 border-b border-slate-200/60"><span class="text-slate-500 font-medium">سرویس:</span> <span class="font-bold text-slate-800">${data.service}</span></div>
                                <div class="flex justify-between pb-3 border-b border-slate-200/60"><span class="text-slate-500 font-medium">همکار:</span> <span class="font-bold text-slate-800">${data.provider}</span></div>
                                <div class="flex justify-between pb-3 border-b border-slate-200/60"><span class="text-slate-500 font-medium">زمان مراجعه:</span> <span class="font-black text-indigo-600 bg-indigo-50 px-2 py-0.5 rounded" dir="ltr">${data.date} - ${data.time}</span></div>
                                <div class="flex justify-between pb-3 border-b border-slate-200/60"><span class="text-slate-500 font-medium">وضعیت پرداخت:</span> <span class="font-bold text-emerald-600">${data.status}</span></div>
                                <div class="flex justify-between pt-2"><span class="font-bold text-slate-800">مبلغ نهایی:</span> <span class="font-black text-xl text-emerald-600">${data.price}</span></div>
                            </div>
                            
                            <p class="text-xs text-center text-slate-400 font-medium">پیامک تایید به همراه جزئیات برای شما ارسال شد.</p>
                        </div>
                        
                        <div class="mt-8 flex flex-col sm:flex-row justify-center gap-4 max-w-lg mx-auto">
                            <button id="zingtime-download-btn" type="button" onclick="window.downloadPDF('${data.id}')" class="relative overflow-hidden flex-1 bg-slate-900 text-white px-6 py-4 rounded-2xl font-bold flex justify-center items-center transition-all hover:bg-slate-800 shadow-xl shadow-slate-900/20 transform hover:-translate-y-1">
                                <div id="zingtime-progress-bar" class="absolute left-0 top-0 bottom-0 bg-emerald-500 transition-all duration-300 z-0" style="width: 0%;"></div>
                                <span id="zingtime-btn-text" class="relative z-10 flex items-center gap-2">
                                    <svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" /></svg>
                                    دانلود فاکتور (PDF)
                                </span>
                            </button>
                            <button type="button" onclick="window.location.href='${pageUrl}'" class="flex-1 bg-white border-2 border-slate-200 text-slate-700 px-6 py-4 rounded-2xl font-bold hover:bg-slate-50 transition-all text-center hover:border-slate-300">ثبت نوبت جدید</button>
                        </div>
                    </div>`;
                }).catch(err => {
                    app.innerHTML = `<div class="p-12 text-center text-rose-500 font-bold bg-rose-50 rounded-[2rem] m-6">خطا در دریافت اطلاعات نوبت. ${err.message}</div>`;
                });
            } else if (paymentStatus === 'failed') {
                hideLoader();
                app.innerHTML = `
                    <div class="p-16 text-center">
                        <div class="w-20 h-20 bg-rose-50 border-4 border-rose-100 text-rose-500 rounded-full flex items-center justify-center text-4xl mx-auto mb-6 shadow-sm">✕</div>
                        <h2 class="text-2xl font-black text-slate-800 mb-2">پرداخت ناموفق بود!</h2>
                        <p class="text-slate-500 mb-8 font-medium">تراکنش شما انجام نشد یا توسط شما لغو گردید. لطفاً مجدداً تلاش کنید.</p>
                        <button type="button" onclick="window.location.href='${pageUrl}'" class="bg-indigo-600 text-white px-8 py-4 rounded-2xl font-bold shadow-xl shadow-indigo-200 hover:bg-indigo-700 transition-all transform hover:-translate-y-1">تلاش مجدد</button>
                    </div>`;
            } else {
                window.loadServices();
            }
        });
        <?php
        $app_js = ob_get_clean();
        wp_add_inline_script('zingtime-frontend-logic', $app_js);

        return $html_output;
    }
}
new Zingtime_Booking();