<?php
if ( ! defined( 'ABSPATH' ) ) { exit; }
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
$active_platform = get_option('yatoon_active_platform', 'local');
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
$is_square_mode  = ($active_platform === 'square');
?>
<div class="wrap sbs-admin-page sbs-staff-page">
    <style>
        .sbs-admin-table-wrap {
            width: 100%;
            overflow-x: auto;
            -webkit-overflow-scrolling: touch;
        }
        .sbs-admin-table-wrap .wp-list-table {
            min-width: 900px;
        }
    </style>
    <h1>
        <?php echo esc_html(get_admin_page_title()); ?>
        <?php if ($is_square_mode) : ?>
        <button type="button" id="sbs-sync-staff" class="page-title-action">
            Sync from Square
        </button>
        <button type="button" id="sbs-rebuild-staff-services" class="page-title-action" style="background:#f59e0b;border-color:#d97706;color:#fff;" title="Re-fetch staff-service assignments from Square booking profiles">
                Rebuild Service Assignments
        </button>
        <?php endif; ?>
        <?php if ( ! empty( $yatoon_staff_at_limit ) ) : ?>
        <button type="button" id="sbs-add-staff-btn" class="page-title-action" disabled style="opacity:.45;cursor:not-allowed;" title="You have reached the 2-staff limit on the free plan.">
            + Add Staff Member
        </button>
        <?php else : ?>
        <button type="button" id="sbs-add-staff-btn" class="page-title-action">
            + Add Staff Member
        </button>
        <?php endif; ?>
    </h1>

    <div id="sbs-rebuild-result" style="display:none;margin:12px 0;padding:12px 16px;border-radius:6px;font-size:14px;"></div>

    <?php if ( ! empty( $yatoon_staff_at_limit ) ) : ?>
    <div class="notice notice-warning" style="margin:12px 0 16px;">
        <p>
            <strong>Staff limit reached.</strong>
            The free plan supports up to <?php echo esc_html( $yatoon_staff_limit ); ?> staff members.
            <a href="<?php echo esc_url( class_exists( 'YATOON_License' ) ? YATOON_License::get_upgrade_url() : YBS_UPGRADE_URL ); ?>" target="_blank" style="font-weight:600;">
                Activate Pro license for unlimited staff &rarr;
            </a>
        </p>
    </div>
    <?php endif; ?>

    <p class="description" style="margin-bottom:4px;">
        Toggle <strong>Show Online</strong> to control which staff appear in the booking form.
        <?php if ($is_square_mode) : ?>
        Sync pulls the latest settings from Square's booking profiles, but you can override here.
        <?php else : ?>
        In Local mode, you can add staff, control who appears online, and assign which services each person can perform.
        <?php endif; ?>
    </p>
    <p class="description" style="margin-bottom:16px;">
        Pro supports <strong>unlimited staff members</strong>.
    </p>

    <?php if (empty($staff)) : ?>
        <div class="notice notice-warning">
            <?php if ($is_square_mode) : ?>
            <p>No staff found. Please sync with Square to import your team members.</p>
            <?php else : ?>
            <p>No staff found yet. Add your first staff member to start taking bookings.</p>
            <?php endif; ?>
        </div>
    <?php else : ?>
        <div class="sbs-table-toolbar">
            <div class="sbs-table-search">
                <input type="search" id="sbs-staff-search" class="regular-text" autocomplete="off" placeholder="Search staff, email, specialty, or ID" autocomplete="off">
                <select id="sbs-staff-status-filter">
                    <option value="">All statuses</option>
                    <option value="active">Active</option>
                    <option value="inactive">Inactive</option>
                </select>
                <select id="sbs-staff-online-filter">
                    <option value="">All visibility</option>
                    <option value="visible">Shown online</option>
                    <option value="hidden">Hidden online</option>
                </select>
                <button type="button" id="sbs-staff-clear-filters" class="button">Clear</button>
            </div>
            <div class="sbs-table-actions">
                <button type="button" id="sbs-delete-selected-staff" class="button" disabled>Delete Selected</button>
            </div>
        </div>
        <div class="sbs-admin-table-wrap">
        <table class="wp-list-table widefat fixed striped" id="sbs-staff-table">
            <thead>
                <tr>
                    <th style="width:36px;"><input type="checkbox" id="sbs-select-all-staff" aria-label="Select all staff"></th>
                    <th style="width:50px;">ID</th>
                    <th style="width:70px;">Photo</th>
                    <th>Name</th>
                    <th>Email</th>
                    <th style="width:90px;">Status</th>
                    <th style="width:130px;">Show Online</th>
                    <th style="width:150px;">Services</th>
                    <th style="width:180px;">Time Off</th>
                    <th style="width:160px;">Portal Access</th>
                    <th style="width:110px;">Portal PIN</th>
                    <th style="width:150px;">Actions</th>
                </tr>
            </thead>
            <tbody>
                <?php // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound ?>
                <?php foreach ($staff as $member) : ?>
                <?php
                global $wpdb;
                // phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
                $time_off_rules = class_exists('YATOON_Business_Hours') ? YATOON_Business_Hours::get_staff_time_off_rules($member->id) : '';
                $time_off_blocks = class_exists('YATOON_Business_Hours') ? YATOON_Business_Hours::get_staff_time_off_blocks($member->id) : array();
                // phpcs:enable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
                ?>
                <tr id="sbs-staff-row-<?php echo esc_html( $member->id ); ?>"
                    data-id="<?php echo esc_attr($member->id); ?>"
                    data-name="<?php echo esc_attr($member->name); ?>"
                    data-email="<?php echo esc_attr($member->email); ?>"
                    data-bio="<?php echo esc_attr($member->bio); ?>"
                    data-image="<?php echo esc_url($member->image_url); ?>"
                    data-color="<?php echo esc_attr($member->calendar_color ?? ''); ?>"
                    data-active="<?php echo esc_attr($member->is_active); ?>"
                    data-bookable="<?php echo esc_attr($member->is_bookable); ?>"
                    data-role="<?php echo esc_attr($member->portal_role ?? 'staff'); ?>"
                    data-permissions="<?php echo esc_attr($member->portal_permissions ?? 'view_schedule'); ?>"
                    data-timeoff="<?php echo esc_attr($time_off_rules); ?>"
                    data-status="<?php echo esc_attr($member->is_active ? 'active' : 'inactive'); ?>"
                    data-online="<?php echo esc_attr($member->is_bookable ? 'visible' : 'hidden'); ?>"
                    data-search="<?php echo esc_attr(strtolower($member->id . ' ' . $member->name . ' ' . $member->email . ' ' . $member->bio)); ?>">
                    <td><input type="checkbox" class="sbs-staff-row-checkbox" value="<?php echo esc_attr($member->id); ?>" aria-label="Select staff <?php echo esc_attr($member->name); ?>"></td>
                    <td><?php echo esc_html($member->id); ?></td>
                    <td>
                        <?php if ($member->image_url) : ?>
                            <button type="button" class="sbs-staff-open-profile sbs-staff-avatar-btn" title="Edit staff profile">
                                <img src="<?php echo esc_url($member->image_url); ?>"
                                     style="width:48px;height:48px;border-radius:50%;object-fit:cover;">
                            </button>
                        <?php else : ?>
                            <button type="button" class="sbs-staff-open-profile sbs-staff-avatar-btn" title="Add staff photo">
                            <div style="width:48px;height:48px;border-radius:50%;background:#e5e7eb;display:flex;align-items:center;justify-content:center;font-weight:700;color:#555;">
                                <?php echo esc_html( strtoupper(substr($member->name, 0, 1)) ); ?>
                            </div>
                            </button>
                        <?php endif; ?>
                    </td>
                    <td><button type="button" class="button-link sbs-staff-open-profile sbs-staff-name-link"><strong><?php echo esc_html($member->name); ?></strong></button></td>
                    <td><?php echo esc_html($member->email ?: '-'); ?></td>
                    <td>
                        <?php if ($member->is_active) : ?>
                                <span style="color:#10B981;font-weight:600;">Active</span>
                        <?php else : ?>
                                <span style="color:#10B981;font-weight:600;">Active</span>
                        <?php endif; ?>
                    </td>
                    <td>
                        <label class="sbs-toggle" title="<?php echo esc_html( $member->is_bookable ? 'Click to hide from booking' : 'Click to show in booking' ); ?>">
                            <input type="checkbox"
                                   class="sbs-bookable-toggle"
                                   data-id="<?php echo esc_html( $member->id ); ?>"
                                   <?php checked($member->is_bookable, 1); ?>>
                            <span class="sbs-toggle-slider"></span>
                            <span class="sbs-toggle-label"><?php echo esc_html( $member->is_bookable ? 'Visible' : 'Hidden' ); ?></span>
                        </label>
                    </td>
                    <td>
                        <?php
                        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
                        $service_count = $wpdb->get_var( $wpdb->prepare(
                            "SELECT COUNT(*) FROM {$wpdb->prefix}yatoon_staff_services WHERE staff_id = %d",
                            $member->id
                        ) );
                        ?>
                        <span style="color:#666;"><?php echo esc_html( $service_count ); ?> assigned</span>
                        <button type="button" class="button button-small sbs-edit-services" data-staff-id="<?php echo esc_html( $member->id ); ?>" data-staff-name="<?php echo esc_attr($member->name); ?>" style="margin-left:8px;">
                            Edit
                        </button>
                    </td>
                    <td>
                        <?php if (!empty($time_off_blocks)) : ?>
                            <span style="display:block;color:#374151;font-weight:600;"><?php echo esc_html( count($time_off_blocks) ); ?> blocked</span>
                            <span style="display:block;color:#6b7280;font-size:12px;"><?php echo esc_html($time_off_blocks[0]['start']->format('M j g:i A')); ?></span>
                        <?php else : ?>
                            <span style="color:#9ca3af;">None</span>
                        <?php endif; ?>
                    </td>
                    <td>
                        <?php
                        $portal_permissions = array_filter(array_map('trim', explode(',', (string) ($member->portal_permissions ?? 'view_schedule'))));
                        $permission_labels  = array();
                        if (in_array('view_all_schedules', $portal_permissions, true)) {
                            $permission_labels[] = 'All schedules';
                        }
                        if (in_array('update_status', $portal_permissions, true)) {
                            $permission_labels[] = 'Status updates';
                        }
                        if (in_array('create_booking', $portal_permissions, true)) {
                            $permission_labels[] = 'Create';
                        }
                        if (in_array('edit_booking', $portal_permissions, true)) {
                            $permission_labels[] = 'Edit';
                        }
                        if (in_array('cancel_booking', $portal_permissions, true)) {
                            $permission_labels[] = 'Cancel';
                        }
                        if (in_array('view_clients', $portal_permissions, true)) {
                            $permission_labels[] = 'Clients';
                        }
                        if (in_array('manage_clients', $portal_permissions, true)) {
                            $permission_labels[] = 'Manage clients';
                        }
                        if (in_array('send_messages', $portal_permissions, true)) {
                            $permission_labels[] = 'Messages';
                        }
                        if (in_array('checkout', $portal_permissions, true)) {
                            $permission_labels[] = 'Checkout';
                        }
                        if (in_array('request_time_off', $portal_permissions, true)) {
                            $permission_labels[] = 'Time off';
                        }
                        if (in_array('approve_time_off', $portal_permissions, true)) {
                            $permission_labels[] = 'Approvals';
                        }
                        ?>
                        <span style="display:block;color:#111827;font-weight:600;"><?php echo esc_html(ucfirst($member->portal_role ?? 'staff')); ?></span>
                        <span style="display:block;color:#6b7280;font-size:12px;">
                            <?php echo esc_html($permission_labels ? implode(', ', $permission_labels) : 'View only'); ?>
                        </span>
                    </td>
                    <td style="white-space:nowrap;">
                        <?php if ( ! empty( $member->portal_pin ) ) : ?>
                                <span style="color:#16a34a;font-weight:600;font-size:13px;">PIN set</span>
                        <?php else : ?>
                        <span style="color:#9ca3af;font-size:13px;">No PIN</span>
                        <?php endif; ?>
                        &nbsp;
                        <button type="button" class="button button-small sbs-set-pin-btn"
                                data-id="<?php echo esc_attr($member->id); ?>"
                                data-name="<?php echo esc_attr($member->name); ?>"
                                style="font-size:11px;">
                            <?php echo empty($member->portal_pin) ? 'Set PIN' : 'Change'; ?>
                        </button>
                    </td>
                    <td>
                        <button type="button"
                                class="button button-small sbs-edit-staff-btn"
                                data-id="<?php echo esc_attr($member->id); ?>"
                                data-name="<?php echo esc_attr($member->name); ?>"
                                data-email="<?php echo esc_attr($member->email); ?>"
                                data-bio="<?php echo esc_attr($member->bio); ?>"
                                data-image="<?php echo esc_url($member->image_url); ?>"
                                data-color="<?php echo esc_attr($member->calendar_color ?? ''); ?>"
                                data-active="<?php echo esc_attr($member->is_active); ?>"
                                data-bookable="<?php echo esc_attr($member->is_bookable); ?>"
                                data-role="<?php echo esc_attr($member->portal_role ?? 'staff'); ?>"
                                data-permissions="<?php echo esc_attr($member->portal_permissions ?? 'view_schedule'); ?>"
                                data-timeoff="<?php echo esc_attr($time_off_rules); ?>">
                            Edit
                        </button>
                        <button type="button"
                                class="button button-small sbs-delete-staff-btn"
                                data-id="<?php echo esc_attr($member->id); ?>"
                                style="color:#dc2626;margin-left:6px;">
                            Delete
                        </button>
                    </td>
                </tr>
                <?php endforeach; ?>
            </tbody>
        </table>
        </div>
    <?php endif; ?>
</div>

<div id="sbs-staff-modal" style="display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.5);z-index:100000;padding:clamp(12px,3vw,40px);overflow:auto;box-sizing:border-box;">
    <div class="sbs-staff-modal-card" style="width:min(960px,100%);margin:0 auto;background:#fff;border-radius:12px;max-height:90vh;overflow:auto;">
        <div style="padding:20px;border-bottom:1px solid #e5e7eb;display:flex;justify-content:space-between;align-items:center;">
            <h2 id="sbs-staff-modal-title" style="margin:0;">Add Staff Member</h2>
            <button id="sbs-staff-modal-close" style="background:none;border:none;font-size:24px;cursor:pointer;color:#999;" type="button">&times;</button>
        </div>
        <div class="sbs-staff-modal-body" style="padding:24px;overflow-x:hidden;">
            <input type="hidden" id="sbs-staff-id" value="0">
            <table class="form-table">
                <tr><th><label for="sbs-staff-name">Name *</label></th><td><input type="text" id="sbs-staff-name" class="regular-text"></td></tr>
                <tr><th><label for="sbs-staff-email">Email</label></th><td><input type="email" id="sbs-staff-email" class="regular-text"></td></tr>
                <tr>
                    <th>Photo</th>
                    <td>
                        <p class="description" style="margin:0 0 8px;">Recommended: a clear square headshot, at least 600px wide. It appears in staff selection, Staff Portal identity, and client-facing booking screens.</p>
                        <input type="hidden" id="sbs-staff-image-url" value="">
                        <div id="sbs-staff-image-preview" class="sbs-staff-photo-preview" style="display:none;">
                            <img src="" alt="" style="width:72px;height:72px;border-radius:50%;object-fit:cover;">
                        </div>
                        <button type="button" class="button" id="sbs-staff-image-upload">Upload / Choose Photo</button>
                        <button type="button" class="button" id="sbs-staff-image-remove" style="display:none;">Remove Photo</button>
                    </td>
                </tr>
                <tr>
                    <th><label for="sbs-staff-calendar-color">Calendar Color</label></th>
                    <td>
                        <input type="color" id="sbs-staff-calendar-color" value="#84cc16" style="width:56px;height:36px;padding:2px;vertical-align:middle;">
                        <span class="description" style="margin-left:8px;">Used for this staff member's appointment blocks in Staff Portal.</span>
                    </td>
                </tr>
                <tr><th><label for="sbs-staff-bio">Bio / Specialty</label></th><td><textarea id="sbs-staff-bio" rows="3" class="large-text"></textarea></td></tr>
                <tr><th>Status</th><td><label><input type="checkbox" id="sbs-staff-active" checked> Active</label> &nbsp; <label><input type="checkbox" id="sbs-staff-bookable" checked> Bookable</label></td></tr>
                <tr>
                    <th>Staff Portal Permissions</th>
                    <td>
                        <label for="sbs-staff-portal-role" style="display:block;font-weight:600;margin-bottom:6px;">Role preset</label>
                        <select id="sbs-staff-portal-role" style="min-width:220px;margin-bottom:12px;">
                            <option value="staff">Staff</option>
                            <option value="manager">Manager</option>
                            <option value="owner">Owner</option>
                        </select>
                        <div class="sbs-permission-list">
                            <label><input type="checkbox" class="sbs-staff-permission" value="view_schedule" checked disabled> View own schedule</label>
                            <label><input type="checkbox" class="sbs-staff-permission" value="view_all_schedules"> View all staff schedules</label>
                            <label><input type="checkbox" class="sbs-staff-permission" value="update_status"> Mark arrived, no show, or completed</label>
                            <label><input type="checkbox" class="sbs-staff-permission" value="create_booking"> Add appointments from Staff Portal</label>
                            <label><input type="checkbox" class="sbs-staff-permission" value="edit_booking"> Edit appointment time, service, staff, and notes</label>
                            <label><input type="checkbox" class="sbs-staff-permission" value="cancel_booking"> Cancel appointments from Staff Portal</label>
                            <label><input type="checkbox" class="sbs-staff-permission" value="view_clients"> View client list and profiles</label>
                            <label><input type="checkbox" class="sbs-staff-permission" value="manage_clients"> Add, edit, and delete clients</label>
                            <label><input type="checkbox" class="sbs-staff-permission" value="send_messages"> Send SMS or WhatsApp messages</label>
                            <label><input type="checkbox" class="sbs-staff-permission" value="checkout"> Checkout, send payment requests, and mark paid</label>
                            <label><input type="checkbox" class="sbs-staff-permission" value="request_time_off"> Request time off</label>
                            <label><input type="checkbox" class="sbs-staff-permission" value="approve_time_off"> Approve or reject staff time off</label>
                        </div>
                        <p class="description">Choose a preset, then fine-tune individual permissions. Staff Portal cancel keeps appointment history; hard delete remains limited to WordPress admins.</p>
                    </td>
                </tr>
                <tr>
                    <th>Blocked Times</th>
                    <td>
                        <input type="hidden" id="sbs-staff-timeoff" value="">
                        <div id="sbs-staff-timeoff-rows" class="sbs-timeoff-editor"></div>
                        <button type="button" class="button" id="sbs-add-timeoff-row">+ Add blocked time</button>
                        <p class="description">Choose a date and time range when this staff member is unavailable. Use All day for vacations or full-day closures.</p>
                    </td>
                </tr>
            </table>
        </div>
        <div style="padding:20px;border-top:1px solid #e5e7eb;text-align:right;">
            <button type="button" class="button" id="sbs-staff-modal-cancel">Cancel</button>
            <button type="button" class="button button-primary" id="sbs-staff-modal-save" style="margin-left:8px;">Save</button>
            <span id="sbs-staff-save-status" style="margin-left:10px;"></span>
        </div>
    </div>
</div>

<div id="sbs-edit-services-modal" style="display:none; position:fixed; top:0; left:0; right:0; bottom:0; background:rgba(0,0,0,0.5); z-index:100000; padding:40px;">
    <div style="max-width:600px; margin:0 auto; background:#fff; border-radius:8px; max-height:90vh; overflow:auto;">
        <div style="padding:20px; border-bottom:1px solid #ddd;">
            <h2 style="margin:0;">Edit Services for <span id="sbs-modal-staff-name"></span></h2>
        </div>
        <div style="padding:20px;">
            <div style="display:flex; align-items:center; justify-content:space-between; margin-bottom:12px;">
                <p style="color:#666; margin:0;">Select which services this staff member can perform:</p>
                <label style="display:flex; align-items:center; gap:6px; cursor:pointer; font-size:13px; font-weight:600; color:#374151; white-space:nowrap; user-select:none;">
                    <input type="checkbox" id="sbs-select-all-services" style="width:16px;height:16px;accent-color:#ec4899;cursor:pointer;">
                    Select All
                </label>
            </div>
            <div id="sbs-services-list"></div>
        </div>
        <div style="padding:20px; border-top:1px solid #ddd; text-align:right;">
            <button type="button" class="button" id="sbs-modal-cancel">Cancel</button>
            <button type="button" class="button button-primary" id="sbs-modal-save" style="margin-left:8px;">Save</button>
        </div>
    </div>
</div>

<script>
jQuery(document).ready(function($) {
    let currentStaffId = null;
    const staffServicesNonce = '<?php echo esc_js(wp_create_nonce('yatoon_staff_services')); ?>';
    const adminNonce = '<?php echo esc_js(wp_create_nonce('yatoon_admin_nonce')); ?>';

    function showStaffServicesNotice(message, isError) {
        const styles = isError
            ? { background: '#fef2f2', border: '1px solid #fecaca', color: '#991b1b' }
            : { background: '#ecfdf5', border: '1px solid #a7f3d0', color: '#065f46' };

        const $notice = $('#sbs-rebuild-result');
        $notice.stop(true, true).text(message).css(styles).show();
    }

    function updateSelectedStaffState() {
        const total = $('.sbs-staff-row-checkbox').length;
        const checked = $('.sbs-staff-row-checkbox:checked').length;
        $('#sbs-delete-selected-staff').prop('disabled', checked === 0);
        $('#sbs-select-all-staff')
            .prop('checked', total > 0 && checked === total)
            .prop('indeterminate', checked > 0 && checked < total);
    }

    $('#sbs-select-all-staff').on('change', function() {
        $('.sbs-staff-row-checkbox').prop('checked', $(this).is(':checked'));
        updateSelectedStaffState();
    });

    $(document).on('change', '.sbs-staff-row-checkbox', updateSelectedStaffState);

    function applyStaffFilters() {
        const q = ($('#sbs-staff-search').val() || '').toLowerCase().trim();
        const status = ($('#sbs-staff-status-filter').val() || '').toLowerCase();
        const online = ($('#sbs-staff-online-filter').val() || '').toLowerCase();

        $('#sbs-staff-table tbody tr').each(function() {
            const $row = $(this);
            const matchesText = !q || String($row.data('search') || '').indexOf(q) !== -1;
            const matchesStatus = !status || String($row.data('status') || '') === status;
            const matchesOnline = !online || String($row.data('online') || '') === online;
            $row.toggle(matchesText && matchesStatus && matchesOnline);
        });
    }

    $('#sbs-staff-search, #sbs-staff-status-filter, #sbs-staff-online-filter').on('input change', applyStaffFilters);
    $('#sbs-staff-clear-filters').on('click', function() {
        $('#sbs-staff-search').val('');
        $('#sbs-staff-status-filter').val('');
        $('#sbs-staff-online-filter').val('');
        applyStaffFilters();
    });

    $('#sbs-delete-selected-staff').on('click', function() {
        const ids = $('.sbs-staff-row-checkbox:checked').map(function() {
            return parseInt($(this).val(), 10);
        }).get().filter(Boolean);

        if (!ids.length) {
            return;
        }

        if (!window.confirm('Delete selected staff members? This cannot be undone.')) {
            return;
        }

        const $btn = $(this).prop('disabled', true).text('Deleting...');

        $.post(ajaxurl, {
            action: 'yatoon_delete_staff',
            nonce: adminNonce,
            staff_ids: ids
        }, function(resp) {
            if (resp.success) {
                ids.forEach(function(id) {
                    $('#sbs-staff-row-' + id).remove();
                });
                updateSelectedStaffState();
                showStaffServicesNotice(resp?.data?.message || 'Staff members deleted.', false);
                if (!$('.sbs-staff-row-checkbox').length) {
                    location.reload();
                }
            } else {
                showStaffServicesNotice(resp?.data?.message || 'Failed to delete selected staff members.', true);
            }
        }).fail(function() {
            showStaffServicesNotice('Could not delete selected staff members. Please try again.', true);
        }).always(function() {
            $btn.text('Delete Selected');
            updateSelectedStaffState();
        });
    });

    // Rebuild Service Assignments button
    $('#sbs-rebuild-staff-services').on('click', function() {
        const $btn = $(this);
        const $notice = $('#sbs-rebuild-result');
        $btn.prop('disabled', true).text('Rebuilding...');
        $notice.hide();

        $.post(ajaxurl, {
            action: 'yatoon_rebuild_staff_services',
            nonce: adminNonce
        }, function(resp) {
            if (resp.success) {
                showStaffServicesNotice('OK ' + (resp.data.message || 'Service assignments rebuilt successfully!'), false);
            } else {
                showStaffServicesNotice('Error: ' + (resp.data && resp.data.message ? resp.data.message : 'Rebuild failed'), true);
            }
        }).fail(function() {
                showStaffServicesNotice('Error: ' + (resp.data && resp.data.message ? resp.data.message : 'Rebuild failed'), true);
        }).always(function() {
            $btn.prop('disabled', false).text('Rebuild Service Assignments');
        });
    });

    let staffImageFrame = null;

    $('<style>')
        .text('.sbs-staff-avatar-btn{border:0;background:transparent;padding:0;margin:0;cursor:pointer;border-radius:50%;display:inline-flex;}'
            + '.sbs-staff-avatar-btn:hover{box-shadow:0 0 0 3px #bfdbfe;}'
            + '.sbs-staff-name-link{font-weight:700;text-decoration:none;}'
            + '.sbs-staff-name-link:hover{text-decoration:underline;}'
            + '#sbs-staff-modal .sbs-staff-modal-card{box-sizing:border-box;}'
            + '#sbs-staff-modal .form-table{width:100%;table-layout:fixed;}'
            + '#sbs-staff-modal .form-table th{width:118px;padding-right:18px;}'
            + '#sbs-staff-modal .form-table td{min-width:0;}'
            + '#sbs-staff-modal input.regular-text,#sbs-staff-modal textarea.large-text{width:100%;max-width:100%;box-sizing:border-box;}'
            + '.sbs-permission-list{display:grid;gap:8px;max-width:420px;}'
            + '.sbs-permission-list label{display:flex;align-items:center;gap:8px;font-weight:500;color:#1f2937;}'
            + '.sbs-staff-photo-preview{margin:0 0 10px;}'
            + '.sbs-timeoff-editor{display:flex;flex-direction:column;gap:10px;margin-bottom:10px;}'
            + '.sbs-timeoff-row{display:grid;grid-template-columns:minmax(160px,1fr) minmax(112px,.7fr) minmax(112px,.7fr) minmax(170px,1fr);gap:8px;align-items:center;padding:10px;border:1px solid #e5e7eb;border-radius:10px;background:#f9fafb;max-width:100%;box-sizing:border-box;}'
            + '.sbs-timeoff-row input[type="date"],.sbs-timeoff-row input[type="time"],.sbs-timeoff-row input[type="text"]{width:100%;min-height:36px;}'
            + '.sbs-timeoff-row label{white-space:nowrap;}'
            + '.sbs-timeoff-row .sbs-remove-timeoff-row{justify-self:start;}'
            + '.sbs-timeoff-row.is-all-day .sbs-timeoff-time{opacity:.45;pointer-events:none;}'
            + '@media(min-width:783px){.sbs-timeoff-row label,.sbs-timeoff-row .sbs-remove-timeoff-row{grid-column:auto;}}'
            + '@media(max-width:1040px){.sbs-timeoff-row{grid-template-columns:1fr 1fr;}.sbs-timeoff-row .sbs-timeoff-note{grid-column:1/-1;}}'
            + '@media(max-width:782px){#sbs-staff-modal{padding:10px !important;}#sbs-staff-modal .form-table,#sbs-staff-modal .form-table tbody,#sbs-staff-modal .form-table tr,#sbs-staff-modal .form-table th,#sbs-staff-modal .form-table td{display:block;width:100%;box-sizing:border-box;}#sbs-staff-modal .form-table th{padding:10px 0 6px;}.sbs-timeoff-row{grid-template-columns:1fr;}.sbs-timeoff-row .sbs-timeoff-note{grid-column:auto;}}')
        .appendTo('head');

    function setStaffImage(url) {
        url = url || '';
        $('#sbs-staff-image-url').val(url);
        if (url) {
            $('#sbs-staff-image-preview').show().find('img').attr('src', url).attr('alt', $('#sbs-staff-name').val() || 'Staff photo');
            $('#sbs-staff-image-remove').show();
        } else {
            $('#sbs-staff-image-preview').hide().find('img').attr('src', '').attr('alt', '');
            $('#sbs-staff-image-remove').hide();
        }
    }

    function addTimeOffRow(block) {
        block = block || {};
        const allDay = !!block.allDay;
        const $row = $('<div class="sbs-timeoff-row">\
            <input type="date" class="sbs-timeoff-date" aria-label="Blocked date">\
            <input type="time" class="sbs-timeoff-start sbs-timeoff-time" aria-label="Start time">\
            <input type="time" class="sbs-timeoff-end sbs-timeoff-time" aria-label="End time">\
            <input type="text" class="sbs-timeoff-note" aria-label="Note" placeholder="Note, e.g. Vacation">\
            <label><input type="checkbox" class="sbs-timeoff-all-day"> All day</label>\
            <button type="button" class="button-link-delete sbs-remove-timeoff-row">Remove</button>\
        </div>');
        $row.find('.sbs-timeoff-date').val(block.date || '');
        $row.find('.sbs-timeoff-start').val(block.start || '');
        $row.find('.sbs-timeoff-end').val(block.end || '');
        $row.find('.sbs-timeoff-note').val(block.note || '');
        $row.find('.sbs-timeoff-all-day').prop('checked', allDay);
        $row.toggleClass('is-all-day', allDay);
        $('#sbs-staff-timeoff-rows').append($row);
    }

    function parseTimeOffRules(raw) {
        const blocks = [];
        (raw || '').split(/\r?\n/).forEach(function(line) {
            line = $.trim(line);
            if (!line) { return; }
            const parts = line.split('|');
            const first = parts[0] || '';
            const second = parts[1] || '';
            const note = parts.slice(2).join('|') || '';
            const date = first.substring(0, 10);
            if (second === 'all_day') {
                blocks.push({ date: date, allDay: true, note: note });
                return;
            }
            blocks.push({
                date: date,
                start: first.length > 10 ? first.substring(11, 16) : '',
                end: second.length > 10 ? second.substring(11, 16) : '',
                note: note
            });
        });
        return blocks;
    }

    function renderTimeOffEditor(raw) {
        const blocks = parseTimeOffRules(raw);
        $('#sbs-staff-timeoff-rows').empty();
        if (!blocks.length) {
            addTimeOffRow();
            return;
        }
        blocks.forEach(addTimeOffRow);
    }

    function serializeTimeOffEditor() {
        const lines = [];
        $('#sbs-staff-timeoff-rows .sbs-timeoff-row').each(function() {
            const $row = $(this);
            const date = $row.find('.sbs-timeoff-date').val();
            const note = $row.find('.sbs-timeoff-note').val().trim();
            const allDay = $row.find('.sbs-timeoff-all-day').is(':checked');
            if (!date) { return; }
            if (allDay) {
                lines.push(date + '|all_day|' + note);
                return;
            }
            const start = $row.find('.sbs-timeoff-start').val();
            const end = $row.find('.sbs-timeoff-end').val();
            if (!start || !end) { return; }
            lines.push(date + ' ' + start + '|' + date + ' ' + end + '|' + note);
        });
        return lines.join('\n');
    }

    function setPortalPermissions(raw) {
        const selected = String(raw || 'view_schedule').split(',').map(v => v.trim()).filter(Boolean);
        $('.sbs-staff-permission').each(function() {
            const value = $(this).val();
            $(this).prop('checked', value === 'view_schedule' || selected.includes(value));
        });
    }

    function serializePortalPermissions() {
        const values = ['view_schedule'];
        $('.sbs-staff-permission:checked').each(function() {
            const value = $(this).val();
            if (value && !values.includes(value)) {
                values.push(value);
            }
        });
        return values.join(',');
    }

    const portalRolePermissions = {
        staff: ['view_schedule', 'update_status', 'view_clients', 'send_messages', 'request_time_off'],
        manager: ['view_schedule', 'update_status', 'view_clients', 'send_messages', 'request_time_off', 'view_all_schedules', 'create_booking', 'edit_booking', 'cancel_booking', 'manage_clients', 'checkout', 'approve_time_off'],
        owner: ['view_schedule', 'view_all_schedules', 'update_status', 'create_booking', 'edit_booking', 'cancel_booking', 'view_clients', 'manage_clients', 'send_messages', 'checkout', 'request_time_off', 'approve_time_off']
    };

    function applyPortalRole(role) {
        const selected = portalRolePermissions[role] || portalRolePermissions.staff;
        $('.sbs-staff-permission').each(function() {
            $(this).prop('checked', selected.includes($(this).val()));
        });
    }

    function openStaffModal(id, name, email, bio, active, bookable, timeoff, imageUrl, permissions, calendarColor, role) {
        $('#sbs-staff-id').val(id || 0);
        $('#sbs-staff-name').val(name || '');
        $('#sbs-staff-email').val(email || '');
        $('#sbs-staff-bio').val(bio || '');
        setStaffImage(imageUrl || '');
        $('#sbs-staff-calendar-color').val(/^#[0-9a-f]{6}$/i.test(calendarColor || '') ? calendarColor : '#84cc16');
        $('#sbs-staff-active').prop('checked', parseInt(active, 10) !== 0);
        $('#sbs-staff-bookable').prop('checked', parseInt(bookable, 10) !== 0);
        $('#sbs-staff-portal-role').val(role || 'staff');
        if (id) {
            setPortalPermissions(permissions || 'view_schedule');
        } else {
            applyPortalRole(role || 'staff');
        }
        renderTimeOffEditor(timeoff || '');
        $('#sbs-staff-modal-title').text(id ? 'Edit Staff Member' : 'Add Staff Member');
        $('#sbs-staff-save-status').empty();
        $('#sbs-staff-modal').fadeIn(150);
    }

    $('#sbs-add-staff-btn').on('click', function() {
        if ( $(this).prop('disabled') ) { return; }
        openStaffModal(0);
    });

    $(document).on('click', '.sbs-edit-staff-btn', function() {
        const d = $(this).data();
        openStaffModal(d.id, d.name, d.email, d.bio, d.active, d.bookable, d.timeoff, d.image, d.permissions, d.color, d.role);
    });

    $(document).on('click', '.sbs-staff-open-profile', function() {
        const d = $(this).closest('tr').data();
        openStaffModal(d.id, d.name, d.email, d.bio, d.active, d.bookable, d.timeoff, d.image, d.permissions, d.color, d.role);
    });

    $('#sbs-staff-portal-role').on('change', function() {
        applyPortalRole($(this).val());
    });

    $('#sbs-staff-image-upload').on('click', function(e) {
        e.preventDefault();
        if (staffImageFrame) {
            staffImageFrame.open();
            return;
        }
        staffImageFrame = wp.media({
            title: 'Choose Staff Photo',
            button: { text: 'Use this photo' },
            library: { type: 'image' },
            multiple: false
        });
        staffImageFrame.on('select', function() {
            const attachment = staffImageFrame.state().get('selection').first().toJSON();
            const url = attachment.sizes && attachment.sizes.thumbnail ? attachment.sizes.thumbnail.url : attachment.url;
            setStaffImage(url);
        });
        staffImageFrame.open();
    });

    $('#sbs-staff-image-remove').on('click', function(e) {
        e.preventDefault();
        setStaffImage('');
    });

    $('#sbs-add-timeoff-row').on('click', function() {
        addTimeOffRow();
    });

    $(document).on('click', '.sbs-remove-timeoff-row', function() {
        $(this).closest('.sbs-timeoff-row').remove();
        if (!$('#sbs-staff-timeoff-rows .sbs-timeoff-row').length) {
            addTimeOffRow();
        }
    });

    $(document).on('change', '.sbs-timeoff-all-day', function() {
        $(this).closest('.sbs-timeoff-row').toggleClass('is-all-day', $(this).is(':checked'));
    });

    $('#sbs-staff-modal-close, #sbs-staff-modal-cancel').on('click', function() {
        $('#sbs-staff-modal').fadeOut(150);
    });

    $('#sbs-staff-modal').on('click', function(e) {
        if (e.target === this) {
            $('#sbs-staff-modal').fadeOut(150);
        }
    });

    $('#sbs-staff-modal-save').on('click', function() {
        const $btn = $(this).prop('disabled', true).text('Saving...');
        $.post(ajaxurl, {
            action: 'yatoon_save_staff',
            nonce: adminNonce,
            staff_id: $('#sbs-staff-id').val(),
            name: $('#sbs-staff-name').val().trim(),
            email: $('#sbs-staff-email').val().trim(),
            bio: $('#sbs-staff-bio').val().trim(),
            image_url: $('#sbs-staff-image-url').val(),
            calendar_color: $('#sbs-staff-calendar-color').val(),
            is_active: $('#sbs-staff-active').is(':checked') ? 1 : 0,
            is_bookable: $('#sbs-staff-bookable').is(':checked') ? 1 : 0,
            portal_role: $('#sbs-staff-portal-role').val(),
            portal_permissions: serializePortalPermissions(),
            time_off_rules: serializeTimeOffEditor()
        }, function(resp) {
            $btn.prop('disabled', false).text('Save');
            if (resp.success) {
                $('#sbs-staff-save-status').html('<span style="color:#10B981;font-weight:600;">Saved.</span>');
                setTimeout(function() { location.reload(); }, 600);
            } else {
                $('#sbs-staff-save-status').html('<span style="color:#dc2626;">' + (resp.data && resp.data.message ? resp.data.message : 'Error') + '</span>');
            }
        }).fail(function() {
            $btn.prop('disabled', false).text('Save');
            $('#sbs-staff-save-status').html('<span style="color:#dc2626;">Network error.</span>');
        });
    });

    $(document).on('click', '.sbs-delete-staff-btn', function() {
        const staffId = $(this).data('id');
        if (!window.confirm('Delete this staff member? This cannot be undone.')) {
            return;
        }

        $.post(ajaxurl, {
            action: 'yatoon_delete_staff',
            nonce: adminNonce,
            staff_id: staffId
        }, function(resp) {
            if (resp.success) {
                location.reload();
            } else {
                showStaffServicesNotice(resp?.data?.message || 'Failed to delete staff member.', true);
            }
        }).fail(function() {
            showStaffServicesNotice('Could not delete staff member. Please try again.', true);
        });
    });

    $(document).on('change', '#sbs-select-all-services', function() {
        const checked = $(this).is(':checked');
        $('.sbs-service-checkbox').prop('checked', checked);
        $('.sbs-service-checkbox').each(function() {
            updateServiceLabelStyle($(this));
        });
    });

    $(document).on('change', '.sbs-service-checkbox', function() {
        updateServiceLabelStyle($(this));
        const total   = $('.sbs-service-checkbox').length;
        const checked = $('.sbs-service-checkbox:checked').length;
        $('#sbs-select-all-services').prop('indeterminate', checked > 0 && checked < total);
        $('#sbs-select-all-services').prop('checked', checked === total);
    });

    function updateServiceLabelStyle($cb) {
        const $label = $cb.closest('label');
        if ($cb.is(':checked')) {
            $label.css({ 'border-color': '#ec4899', 'background': '#fdf2f8' });
        } else {
            $label.css({ 'border-color': '#ddd', 'background': '' });
        }
    }

    $('.sbs-edit-services').on('click', function() {
        currentStaffId = $(this).data('staff-id');
        const staffName = $(this).data('staff-name');
        $('#sbs-select-all-services').prop('checked', false).prop('indeterminate', false);
        $('#sbs-modal-staff-name').text(staffName);
        $('#sbs-edit-services-modal').fadeIn(200);

        $.ajax({
            url: ajaxurl,
            type: 'POST',
            data: {
                action: 'yatoon_get_staff_services',
                staff_id: currentStaffId,
                nonce: staffServicesNonce
            },
            success: function(response) {
                if (response.success) {
                    let html = '';
                    response.data.services.forEach(function(service) {
                        const borderColor = service.assigned ? '#ec4899' : '#ddd';
                        const bgColor     = service.assigned ? '#fdf2f8' : '';
                        html += `
                            <label style="display:flex; align-items:center; gap:10px; padding:10px 14px; border:1.5px solid ${borderColor}; margin-bottom:8px; border-radius:8px; cursor:pointer; background:${bgColor}; transition:all .15s;">
                                <input type="checkbox"
                                       class="sbs-service-checkbox"
                                       value="${service.id}"
                                       style="width:16px;height:16px;accent-color:#ec4899;flex-shrink:0;"
                                       ${service.assigned ? 'checked' : ''}>
                                <span style="flex:1;"><strong>${service.name}</strong></span>
                                ${service.price > 0 ? '<span style="font-size:12px;color:#6b7280;">$' + service.price + '</span>' : ''}
                            </label>
                        `;
                    });
                    $('#sbs-services-list').html(html);
                    const total = response.data.services.length;
                    const assigned = response.data.services.filter(s => s.assigned).length;
                    $('#sbs-select-all-services')
                        .prop('checked', assigned === total && total > 0)
                        .prop('indeterminate', assigned > 0 && assigned < total);
                } else {
                    showStaffServicesNotice(response?.data?.message || 'Failed to load services.', true);
                    $('#sbs-edit-services-modal').fadeOut(200);
                }
            },
            error: function(xhr) {
                let msg = 'Could not load staff services. Please try again.';
                if (xhr && xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message) {
                    msg = xhr.responseJSON.data.message;
                } else if (xhr && xhr.responseText) {
                    msg += ' Server said: ' + xhr.responseText.substring(0, 180);
                }
                showStaffServicesNotice(msg, true);
                $('#sbs-edit-services-modal').fadeOut(200);
            }
        });
    });

    $('#sbs-modal-cancel, #sbs-edit-services-modal').on('click', function(e) {
        if (e.target === this) {
            $('#sbs-edit-services-modal').fadeOut(200);
        }
    });

    $('#sbs-modal-save').on('click', function() {
        const $saveButton = $(this);
        const selectedServices = [];
        $('.sbs-service-checkbox:checked').each(function() {
            selectedServices.push($(this).val());
        });

        $saveButton.prop('disabled', true).text('Saving...');

        $.ajax({
            url: ajaxurl,
            type: 'POST',
            data: {
                action: 'yatoon_update_staff_services',
                staff_id: currentStaffId,
                service_ids: selectedServices,
                nonce: staffServicesNonce
            },
            success: function(response) {
                if (response.success) {
                    showStaffServicesNotice(response?.data?.message || 'Services updated successfully.', false);
                    $('#sbs-edit-services-modal').fadeOut(200);
                    location.reload();
                } else {
                    showStaffServicesNotice(response?.data?.message || 'Failed to save services.', true);
                }
            },
            error: function() {
                showStaffServicesNotice('Could not save staff services. Please try again.', true);
            },
            complete: function() {
                $saveButton.prop('disabled', false).text('Save');
            }
        });
    });
});
</script>

<style>
.sbs-toggle {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    user-select: none;
}
.sbs-toggle input { display: none; }
.sbs-toggle-slider {
    position: relative;
    width: 42px;
    height: 24px;
    background: #ccc;
    border-radius: 12px;
    transition: background .2s;
    flex-shrink: 0;
}
.sbs-toggle-slider::after {
    content: '';
    position: absolute;
    top: 3px;
    left: 3px;
    width: 18px;
    height: 18px;
    background: #fff;
    border-radius: 50%;
    transition: left .2s;
    box-shadow: 0 1px 3px rgba(0,0,0,.3);
}
.sbs-toggle input:checked + .sbs-toggle-slider { background: #10B981; }
.sbs-toggle input:checked + .sbs-toggle-slider::after { left: 21px; }
.sbs-toggle-label { font-size: 13px; color: #555; min-width: 42px; }
.sbs-toggle input:checked ~ .sbs-toggle-label { color: #10B981; font-weight: 600; }
.sbs-saving { opacity: .5; pointer-events: none; }
</style>

<script>
jQuery(function($){
    $(document).on('change', '.sbs-bookable-toggle', function(){
        const $cb = $(this);
        const $row = $cb.closest('tr');
        const $label = $cb.siblings('.sbs-toggle-slider').next('.sbs-toggle-label');
        const staffId = $cb.data('id');
        const val = $cb.is(':checked') ? 1 : 0;

        $row.addClass('sbs-saving');

        $.post(ajaxurl, {
            action: 'yatoon_toggle_staff_bookable',
            nonce: '<?php echo esc_html( wp_create_nonce("yatoon_toggle_staff") ); ?>',
            staff_id: staffId,
            bookable: val
        }, function(resp){
            $row.removeClass('sbs-saving');
            if (resp.success) {
                $label.text(val ? 'Visible' : 'Hidden');
                $row.attr('data-online', val ? 'visible' : 'hidden').data('online', val ? 'visible' : 'hidden');
            } else {
                $cb.prop('checked', !val);
                $label.text(!val ? 'Visible' : 'Hidden');
                alert('Failed to save. Please try again.');
            }
        }).fail(function(){
            $row.removeClass('sbs-saving');
            $cb.prop('checked', !val);
            $label.text(!val ? 'Visible' : 'Hidden');
        });
    });

    // -- Set PIN modal ------------------------------------------------------
    // Inject modal HTML once
    const yspPinLength = <?php echo (int) ( in_array( (int) get_option( 'yatoon_staff_pin_length', 4 ), array( 4, 6 ), true ) ? (int) get_option( 'yatoon_staff_pin_length', 4 ) : 4 ); ?>;
    if (!$('#ysp-pin-modal').length) {
        $('body').append(`
            <div id="ysp-pin-modal" style="display:none;position:fixed;inset:0;z-index:999999;background:rgba(0,0,0,.5);align-items:center;justify-content:center;">
                <div style="background:#fff;border-radius:8px;padding:24px;width:320px;box-shadow:0 8px 32px rgba(0,0,0,.2);">
                    <h3 id="ysp-pin-title" style="margin:0 0 16px;font-size:16px;">Set Portal PIN</h3>
                    <label style="display:block;font-size:13px;font-weight:600;margin-bottom:6px;">${yspPinLength}-digit PIN <span style="font-weight:400;color:#6b7280;">(leave blank to remove)</span></label>
                    <input type="password" id="ysp-pin-input" maxlength="${yspPinLength}" inputmode="numeric" pattern="[0-9]*"
                        style="width:100%;height:42px;border:1.5px solid #d1d5db;border-radius:6px;padding:0 12px;font-size:20px;letter-spacing:.2em;text-align:center;box-sizing:border-box;">
                    <p id="ysp-pin-error" style="color:#dc2626;font-size:13px;min-height:20px;margin:6px 0 0;"></p>
                    <div style="display:flex;gap:8px;margin-top:16px;">
                        <button id="ysp-pin-save" class="button button-primary" style="flex:1;">Save PIN</button>
                        <button id="ysp-pin-cancel" class="button" style="flex:1;">Cancel</button>
                    </div>
                </div>
            </div>
        `);
    }

    let _pinStaffId = null;

    $(document).on('click', '.sbs-set-pin-btn', function() {
        _pinStaffId = $(this).data('id');
        const staffName = $(this).data('name');
        $('#ysp-pin-title').text('Set Portal PIN - ' + staffName);
        $('#ysp-pin-input').val('');
        $('#ysp-pin-error').text('');
        $('#ysp-pin-modal').css('display','flex');
        setTimeout(() => $('#ysp-pin-input').focus(), 100);
    });

    $('#ysp-pin-cancel, #ysp-pin-modal').on('click', function(e) {
        if (e.target === this) $('#ysp-pin-modal').hide();
    });

    // Save PIN
    $(document).on('click', '#ysp-pin-save', function() {
        const pin = $('#ysp-pin-input').val().trim();
        const pinPattern = new RegExp('^\\d{' + yspPinLength + '}$');
        if (pin !== '' && !pinPattern.test(pin)) {
            $('#ysp-pin-error').text('PIN must be exactly ' + yspPinLength + ' digits.');
            return;
        }
        const $btn = $(this).prop('disabled', true).text('Saving...');
        $.post(ajaxurl, {
            action:   'yatoon_set_staff_pin',
            nonce:    '<?php echo esc_js( wp_create_nonce( "yatoon_set_staff_pin" ) ); ?>',
            staff_id: _pinStaffId,
            pin:      pin,
        }, function(resp) {
            $btn.prop('disabled', false).text('Save PIN');
            if (resp.success) {
                $('#ysp-pin-modal').hide();
                location.reload();
            } else {
                $('#ysp-pin-error').text(resp.data?.message || 'Failed to save PIN.');
            }
        }).fail(function() {
            $btn.prop('disabled', false).text('Save PIN');
            $('#ysp-pin-error').text('Network error. Please try again.');
        });
    });

    // Allow Enter key to submit
    $(document).on('keydown', '#ysp-pin-input', function(e) {
        if (e.key === 'Enter') $('#ysp-pin-save').trigger('click');
    });

});
</script>
