<?php
// phpcs:disable WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.InputNotValidated
// phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
if ( ! defined( 'ABSPATH' ) ) { exit; }
// Display booking times in the WordPress site timezone.
$_sbs_tz_string = wp_timezone_string() ?: 'UTC';
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
$_sbs_local_tz = new DateTimeZone($_sbs_tz_string);
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
$_sbs_utc_tz   = new DateTimeZone('UTC');
if ( ! function_exists('yatoon_booking_display_dt') ) {
    function yatoon_booking_display_dt($booking, $field, $local_tz, $utc_tz) {
        $db_time = isset($booking->{$field}) ? $booking->{$field} : '';
        if (empty($db_time) || $db_time === '0000-00-00 00:00:00') return null;
        $is_square = !empty($booking->square_synced) && !empty($booking->square_booking_id);
        $source_tz = $is_square ? $utc_tz : $local_tz;
        $dt = new DateTime($db_time, $source_tz);
        if ($is_square) $dt->setTimezone($local_tz);
        return $dt;
    }
}
?>
<div class="wrap sbs-admin-page sbs-bookings-page">
    <h1><?php echo esc_html(get_admin_page_title()); ?></h1>
    <style>
        .sbs-admin-table-wrap {
            width: 100%;
            overflow-x: auto;
            -webkit-overflow-scrolling: touch;
        }
        .sbs-admin-table-wrap .wp-list-table {
            min-width: 1280px;
            table-layout: auto;
        }
        #sbs-bookings-table th:nth-child(5),
        #sbs-bookings-table td:nth-child(5) {
            min-width: 90px;
            white-space: nowrap;
            word-break: normal;
        }
        #sbs-bookings-table th:nth-child(6),
        #sbs-bookings-table td:nth-child(6) {
            min-width: 130px;
            white-space: nowrap;
        }
        /* Highlight rows for bookings that include a customer design/photo upload */
        #sbs-bookings-table tr[data-design-upload="1"] {
            background: #fef3c7 !important;
            box-shadow: inset 5px 0 0 #f59e0b;
        }
        #sbs-bookings-table tr[data-design-upload="1"]:hover {
            background: #fde68a !important;
        }
    </style>
    
    <?php if (empty($bookings)) : ?>
        <div class="notice notice-info">
            <p><?php esc_html_e('No bookings found yet.', 'yatoon-booking-system'); ?></p>
        </div>
    <?php else : ?>
        <div class="sbs-table-toolbar">
            <div class="sbs-table-search">
                <input type="search" id="sbs-booking-search" class="regular-text" value="<?php echo esc_attr(isset($_GET['s']) ? sanitize_text_field(wp_unslash($_GET['s'])) : ''); ?>" autocomplete="off" placeholder="Search customer, phone, service, staff, or ID">
                <select id="sbs-booking-status-filter">
                    <option value="">All statuses</option>
                    <option value="pending">Pending</option>
                    <option value="confirmed">Confirmed</option>
                    <option value="completed">Completed</option>
                    <option value="no_show">No-show</option>
                    <option value="cancelled">Cancelled</option>
                </select>
                <select id="sbs-booking-design-filter">
                    <option value="">All image statuses</option>
                    <option value="1">Has design image</option>
                    <option value="0">No design image</option>
                </select>
                <button type="button" id="sbs-booking-clear-filters" class="button">Clear</button>
            </div>
            <div class="sbs-table-actions">
                <button type="button" id="sbs-view-design-gallery" class="button action">
                    <?php esc_html_e('View Design Images', 'yatoon-booking-system'); ?>
                </button>
                <button type="button" id="sbs-delete-selected-bookings" class="button action" disabled>
                    <?php esc_html_e('Delete Selected', 'yatoon-booking-system'); ?>
                </button>
                <button type="button" id="sbs-export-bookings" class="button action">
                    <?php esc_html_e('Export CSV', 'yatoon-booking-system'); ?>
                </button>
                <button type="button" id="sbs-sync-from-square" class="button action" style="background:#0073aa;color:#fff;border-color:#006799;margin-left:6px;">
                    <?php esc_html_e('Sync from Square', 'yatoon-booking-system'); ?>
                </button>
                <span id="sbs-sync-status" style="margin-left:10px;font-size:13px;color:#555;line-height:28px;"></span>
            </div>
        </div>

        <?php
        // -- Group bookings by group_booking_id --------------------------------
        // Bookings without a group_booking_id are shown individually.
        // Bookings sharing a group_booking_id are rendered as a single expandable group row.
        // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
        $groups      = [];   // group_id => [bookings...]
        // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
        $solo        = [];   // bookings without a group

        // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
        foreach ($bookings as $bk) {
            if (!empty($yatoon_booking_row->group_booking_id)) {
                // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
                $groups[$yatoon_booking_row->group_booking_id][] = $bk;
            } else {
                // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
                $solo[] = $bk;
            }
        }
        // Sort within each group by service_order
        // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
        foreach ($groups as $gid => &$gbks) {
            usort($gbks, fn($a,$b) => intval($a->service_order) - intval($b->service_order));
        }
        unset($gbks);

        // -- Flatten into render items -----------------------------------------
        // Each render item is either:
        //   type=solo  -> single booking row
        //   type=group -> array of bookings shown as one unit with sub-rows
        // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
        $render_items = [];
        // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
        foreach ($solo  as $bk) { $render_items[] = ['type'=>'solo',  'data'=>$bk]; }
        // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
        foreach ($groups as $gid=>$gbks) { $render_items[] = ['type'=>'group', 'gid'=>$gid, 'data'=>$gbks]; }

        // Sort render items by the first booking's start_time desc
        usort($render_items, function($x, $y) {
            $tx = $x['type']==='solo' ? $x['data']->start_time : $x['data'][0]->start_time;
            $ty = $y['type']==='solo' ? $y['data']->start_time : $y['data'][0]->start_time;
            return strcmp($ty, $tx); // desc
        });
        ?>

        <div class="sbs-admin-table-wrap">
        <table class="wp-list-table widefat fixed striped" id="sbs-bookings-table">
            <thead>
                <tr>
                    <td class="manage-column check-column">
                        <input type="checkbox" id="sbs-select-all-bookings">
                    </td>
                    <th class="manage-column" style="width:50px;"><?php esc_html_e('ID', 'yatoon-booking-system'); ?></th>
                    <th class="manage-column"><?php esc_html_e('Customer', 'yatoon-booking-system'); ?></th>
                    <th class="manage-column"><?php esc_html_e('Service', 'yatoon-booking-system'); ?></th>
                    <th class="manage-column"><?php esc_html_e('Staff', 'yatoon-booking-system'); ?></th>
                    <th class="manage-column"><?php esc_html_e('Date & Time', 'yatoon-booking-system'); ?></th>
                    <th class="manage-column"><?php esc_html_e('Price', 'yatoon-booking-system'); ?></th>
                    <th class="manage-column"><?php esc_html_e('Status', 'yatoon-booking-system'); ?></th>
                    <th class="manage-column"><?php esc_html_e('Payment', 'yatoon-booking-system'); ?></th>
                    <th class="manage-column"><?php esc_html_e('Square Sync', 'yatoon-booking-system'); ?></th>
                    <th class="manage-column"><?php esc_html_e('Actions', 'yatoon-booking-system'); ?></th>
                </tr>
            </thead>
            <tbody>
            <?php // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound ?>
            <?php foreach ($render_items as $item) :

                // -- Helper to render status badge -----------------------------
                // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
                $status_badge = function($status) {
                    switch ($status) {
                        case 'confirmed': return '<span class="sbs-status-confirmed">Confirmed</span>';
                        case 'pending':   return '<span class="sbs-status-pending">Pending</span>';
                        case 'completed': return '<span class="sbs-status-completed">Completed</span>';
                        case 'no_show':   return '<span class="sbs-status-noshow">No-show</span>';
                        case 'cancelled': return '<span class="sbs-status-cancelled">Cancelled</span>';
                        default:          return '<span>'.esc_html(ucfirst($status)).'</span>';
                    }
                };
                // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
                $payment_labels = array(
                    'unpaid'          => 'Unpaid',
                    'paid_square_pos' => 'Paid in Square POS',
                    'deposit_paid'    => 'Deposit paid',
                    'no_show_fee_charged' => 'No-show fee charged',
                    'no_show_fee_waived'  => 'No-show fee waived',
                    'refunded'        => 'Refunded',
                    'waived'          => 'Waived',
                );
                // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
                $payment_badge = function($status) use ($payment_labels) {
                    $status = $status ?: 'unpaid';
                    $label = $payment_labels[$status] ?? ucfirst(str_replace('_', ' ', $status));
                    return '<span class="sbs-payment-badge sbs-payment-' . esc_attr($status) . '">' . esc_html($yatoon_status_label) . '</span>';
                };

                if ($item['type'] === 'solo') :
                    // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
                    $b = $item['data'];
                    // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
                    $st = yatoon_booking_display_dt($b, 'start_time', $_sbs_local_tz, $_sbs_utc_tz);
                    // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
                    $et = yatoon_booking_display_dt($b, 'end_time', $_sbs_local_tz, $_sbs_utc_tz);
                    // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
                    $created_dt = null;
                    if (!empty($b->created_at) && $b->created_at !== '0000-00-00 00:00:00') {
                        $created_dt = new DateTime($b->created_at, new DateTimeZone('UTC'));
                        $created_dt->setTimezone($_sbs_local_tz);
                    }
                    // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
                    $client_url = !empty($b->client_id) ? add_query_arg(array(
                        'page'      => 'yatoon-clients',
                        'client_id' => intval($b->client_id),
                        's'         => $b->customer_phone ?: $b->customer_email,
                    ), admin_url('admin.php')) : '';
            ?>
                <tr data-booking-id="<?php echo esc_html( $b->id ); ?>"
                    data-status="<?php echo esc_attr($b->status); ?>"
                    data-design-upload="<?php echo esc_attr(!empty($b->design_image_url) ? '1' : '0'); ?>"
                    data-design-url="<?php echo esc_url($b->design_image_url ?? ''); ?>"
                    data-design-label="<?php echo esc_attr('#' . $b->id . ' - ' . $b->customer_name . ' - ' . ($b->service_name ?: 'Appointment')); ?>"
                    data-search="<?php echo esc_attr(strtolower($b->id . ' ' . $b->customer_name . ' ' . $b->customer_email . ' ' . $b->customer_phone . ' ' . $b->service_name . ' ' . $b->staff_name . ' ' . $b->status)); ?>">
                    <th class="check-column">
                        <input type="checkbox" class="sbs-booking-checkbox" value="<?php echo esc_html( $b->id ); ?>" data-design-url="<?php echo esc_url($b->design_image_url ?? ''); ?>" data-design-label="<?php echo esc_attr('#' . $b->id . ' - ' . $b->customer_name . ' - ' . ($b->service_name ?: 'Appointment')); ?>">
                    </th>
                    <td><?php echo esc_html($b->id); ?></td>
                    <td>
                        <?php if ($client_url) : ?>
                            <a href="<?php echo esc_url($client_url); ?>" style="font-weight:700;text-decoration:none;"><?php echo esc_html($b->customer_name); ?></a><br>
                        <?php else : ?>
                            <strong><?php echo esc_html($b->customer_name); ?></strong><br>
                        <?php endif; ?>
                        <small><?php echo esc_html($b->customer_email); ?></small><br>
                        <?php if ($b->customer_phone) echo '<small>'.esc_html($b->customer_phone).'</small>'; ?>
                        <?php if (!empty($b->consent_accepted)) : ?>
                            <br><small title="<?php echo esc_attr($b->consent_signature ?: 'Signed'); ?>" style="color:#4f46e5;">Yes Consent signed</small>
                        <?php endif; ?>
                        <?php if (!empty($b->policy_acknowledged)) : ?>
                            <br><small style="color:#b45309;">Yes Policy acknowledged</small>
                        <?php endif; ?>
                        <?php if (!empty($b->design_image_url)) : ?>
                            <br><a href="<?php echo esc_url($b->design_image_url); ?>" target="_blank" rel="noopener" class="yatoon-booking-design-thumb">
                                <img src="<?php echo esc_url($b->design_image_url); ?>" alt="">
                                <span>Design image</span>
                            </a>
                        <?php endif; ?>
                    </td>
                    <td><?php echo esc_html($b->service_name ?: 'N/A'); ?></td>
                    <td>
                        <?php 
                        echo esc_html($b->staff_name ?: 'N/A');
                        if (!empty($b->is_any_staff)) {
                            echo '<br><span style="font-size:10px;color:#718096;font-style:italic;">(Booked with any available)</span>';
                        }
                        ?></td>
                    <td>
                        <strong><?php echo esc_html( $st->format('M j, Y') ); ?></strong><br>
                        <small><?php echo esc_html( $st->format('g:i A') ); ?> - <?php echo esc_html( $et->format('g:i A') ); ?></small>
                    </td>
                    <td>$<?php echo number_format($b->total_price, 2); ?></td>
                    <td>
                        <select class="sbs-booking-status-select" data-id="<?php echo esc_attr($b->id); ?>" style="max-width:120px;">
                            <?php // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound ?>
                            <?php foreach (array('pending'=>'Pending','confirmed'=>'Confirmed','completed'=>'Completed','no_show'=>'No-show','cancelled'=>'Cancelled') as $yatoon_status_value => $yatoon_status_label) : ?>
                                <option value="<?php echo esc_attr($yatoon_status_value); ?>" <?php selected($b->status, $value); ?>><?php echo esc_html($yatoon_status_label); ?></option>
                            <?php endforeach; ?>
                        </select>
                    </td>
                    <td>
                        <?php echo wp_kses_post( $payment_badge($b->payment_status ?? 'unpaid') ); ?><br>
                        <select class="sbs-payment-status-select" data-id="<?php echo esc_attr($b->id); ?>" data-note="<?php echo esc_attr($b->payment_note ?? ''); ?>" style="max-width:150px;margin-top:4px;">
                            <?php // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound ?>
                            <?php foreach ($payment_labels as $yatoon_status_value => $yatoon_status_label) : ?>
                                <option value="<?php echo esc_attr($yatoon_status_value); ?>" <?php selected(($b->payment_status ?? 'unpaid'), $value); ?>><?php echo esc_html($yatoon_status_label); ?></option>
                            <?php endforeach; ?>
                        </select>
                    </td>
                    <td>
                        <?php if ($b->square_synced && $b->square_booking_id) : ?>
                            <span style="color:#10B981;font-size:12px;">Sent to Square</span><br>
                            <small style="color:#666;"><?php echo esc_html(substr($b->square_booking_id,0,8)); ?>...</small>
                        <?php else : ?>
                            <span style="color:#6b7280;font-size:12px;">Local</span>
                        <?php endif; ?>
                    </td>
                    <td>
                        <button type="button"
                                class="button button-small sbs-view-booking"
                                data-id="<?php echo esc_attr($b->id); ?>"
                                data-customer="<?php echo esc_attr($b->customer_name); ?>"
                                data-email="<?php echo esc_attr($b->customer_email); ?>"
                                data-phone="<?php echo esc_attr($b->customer_phone ?: ''); ?>"
                                data-service="<?php echo esc_attr($b->service_name ?: 'N/A'); ?>"
                                data-staff="<?php echo esc_attr($b->staff_name ?: 'N/A'); ?>"
                                data-date="<?php echo esc_attr($st->format('M j, Y')); ?>"
                                data-time="<?php echo esc_attr($st->format('g:i A') . ' - ' . $et->format('g:i A')); ?>"
                                data-status="<?php echo esc_attr(ucfirst(str_replace('_', ' ', $b->status))); ?>"
                                data-payment="<?php echo esc_attr($payment_labels[$b->payment_status ?? 'unpaid'] ?? ucfirst(str_replace('_', ' ', $b->payment_status ?? 'unpaid'))); ?>"
                                data-total="<?php echo esc_attr(number_format((float) $b->total_price, 2)); ?>"
                                data-booked-at="<?php echo esc_attr($created_dt ? $created_dt->format('M j, Y g:i A') : ''); ?>"
                                data-client-url="<?php echo esc_url($client_url); ?>"
                                data-design-url="<?php echo esc_url($b->design_image_url ?? ''); ?>"
                                data-note="<?php echo esc_attr($b->payment_note ?? ''); ?>">View</button>
                        <?php if ($b->status !== 'cancelled') : ?>
                            <button type="button" class="button button-small button-link-delete sbs-cancel-booking" data-id="<?php echo esc_html( $b->id ); ?>">Cancel</button>
                        <?php endif; ?>
                        <?php if (($b->payment_status ?? 'unpaid') === 'unpaid') : ?>
                            <button type="button" class="button button-small yatoon-send-payment-request" data-id="<?php echo esc_attr($b->id); ?>" style="margin-top:4px;">Payment Request</button>
                        <?php endif; ?>
                        <button type="button" class="button button-small sbs-delete-booking" data-id="<?php echo esc_attr($b->id); ?>" style="color:#999;margin-left:2px;" title="Permanently delete from local DB">Delete</button>
                    </td>
                </tr>

                <?php elseif ($item['type'] === 'group') :
                    // phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
                    $gbks     = $item['data'];
                    $gid      = $item['gid'];
                    $first    = $gbks[0];
                    $gst      = yatoon_booking_display_dt($first, 'start_time', $_sbs_local_tz, $_sbs_utc_tz);
                    $gcreated = null;
                    if (!empty($first->created_at) && $first->created_at !== '0000-00-00 00:00:00') {
                        $gcreated = new DateTime($first->created_at, new DateTimeZone('UTC'));
                        $gcreated->setTimezone($_sbs_local_tz);
                    }
                    $group_client_url = !empty($first->client_id) ? add_query_arg(array(
                        'page'      => 'yatoon-clients',
                        'client_id' => intval($first->client_id),
                        's'         => $first->customer_phone ?: $first->customer_email,
                    ), admin_url('admin.php')) : '';
                    $last     = end($gbks);
                    $get      = yatoon_booking_display_dt($last, 'end_time', $_sbs_local_tz, $_sbs_utc_tz);
                    $total_price = array_sum(array_column($gbks, 'total_price'));
                    $all_confirmed = array_reduce($gbks, fn($c,$b) => $c && $b->status==='confirmed', true);
                    $any_synced    = array_reduce($gbks, fn($c,$b) => $c || ($b->square_synced && $b->square_booking_id), false);
                    $group_design_url = '';
                    foreach ($gbks as $gb_design) {
                        if (!empty($gb_design->design_image_url)) {
                            $group_design_url = $gb_design->design_image_url;
                            break;
                        }
                    }
                    $svc_names = implode(' -> ', array_map(fn($b) => esc_html($b->service_name ?: 'N/A'), $gbks));
                    $staff_names = implode(', ', array_unique(array_map(fn($b) => esc_html($b->staff_name ?: 'Any') . (!empty($b->is_any_staff) ? ' <span style="font-size:10px;color:#718096;font-style:italic;">(any)</span>' : ''), $gbks)));
                    // phpcs:enable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
                ?>

                <!-- GROUP ROW: summary line with toggle -->
                <tr class="sbs-group-header" data-gid="<?php echo esc_attr($gid); ?>"
                    data-status="<?php echo esc_attr($first->status); ?>"
                    data-design-upload="<?php echo esc_attr($group_design_url ? '1' : '0'); ?>"
                    data-design-url="<?php echo esc_url($group_design_url); ?>"
                    data-design-label="<?php echo esc_attr('#' . $first->id . ' group - ' . $first->customer_name); ?>"
                    data-search="<?php echo esc_attr(strtolower($gid . ' ' . $first->id . ' ' . $first->customer_name . ' ' . $first->customer_email . ' ' . $first->customer_phone . ' ' . wp_strip_all_tags($svc_names) . ' ' . wp_strip_all_tags($staff_names) . ' ' . $first->status)); ?>"
                    style="background:#f0f9ff;border-left:4px solid #0ea5e9;cursor:pointer;"
                    title="Click to expand/collapse this multi-service appointment">
                    <th class="check-column">
                        <?php // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound ?>
                        <?php foreach ($gbks as $yatoon_group_booking) : ?>
                            <input type="checkbox" class="sbs-booking-checkbox" value="<?php echo esc_html( $yatoon_group_booking->id ); ?>" data-design-url="<?php echo esc_url($yatoon_group_booking->design_image_url ?? ''); ?>" data-design-label="<?php echo esc_attr('#' . $yatoon_group_booking->id . ' - ' . $first->customer_name . ' - ' . ($yatoon_group_booking->service_name ?: 'Appointment')); ?>" style="display:none;">
                        <?php endforeach; ?>
                        <input type="checkbox" class="sbs-group-checkbox" data-gid="<?php echo esc_attr($gid); ?>" title="Select all services in this group">
                    </th>
                    <td>
                        <strong style="color:#0369a1;">#<?php echo esc_html( $first->id ); ?>...</strong><br>
                        <span style="font-size:10px;color:#64748b;white-space:nowrap;">
                            <?php echo esc_html( count($gbks) ); ?> services
                        </span>
                    </td>
                    <td>
                        <?php if ($group_client_url) : ?>
                            <a href="<?php echo esc_url($group_client_url); ?>" style="font-weight:700;text-decoration:none;"><?php echo esc_html($first->customer_name); ?></a><br>
                        <?php else : ?>
                            <strong><?php echo esc_html($first->customer_name); ?></strong><br>
                        <?php endif; ?>
                        <small><?php echo esc_html($first->customer_email); ?></small>
                        <?php if (!empty($first->consent_accepted)) : ?>
                            <br><small title="<?php echo esc_attr($first->consent_signature ?: 'Signed'); ?>" style="color:#4f46e5;">Yes Consent signed</small>
                        <?php endif; ?>
                        <?php if (!empty($first->policy_acknowledged)) : ?>
                            <br><small style="color:#b45309;">Yes Policy acknowledged</small>
                        <?php endif; ?>
                        <?php if (!empty($group_design_url)) : ?>
                            <br><a href="<?php echo esc_url($group_design_url); ?>" target="_blank" rel="noopener" class="yatoon-booking-design-thumb">
                                <img src="<?php echo esc_url($group_design_url); ?>" alt="">
                                <span>Design image</span>
                            </a>
                        <?php endif; ?>
                    </td>
                    <td>
                        <span style="font-size:12px;line-height:1.4;"><?php echo esc_html( $svc_names ); ?></span>
                    </td>
                    <td><span style="font-size:12px;"><?php echo esc_html( $staff_names ); ?></span></td>
                    <td>
                        <strong><?php echo esc_html( $gst->format('M j, Y') ); ?></strong><br>
                        <small><?php echo esc_html( $gst->format('g:i A') ); ?> - <?php echo esc_html( $get->format('g:i A') ); ?></small>
                    </td>
                    <td>$<?php echo number_format($total_price, 2); ?></td>
                    <td><?php echo wp_kses_post( $status_badge($all_confirmed ? 'confirmed' : $first->status) ); ?></td>
                    <td><?php echo wp_kses_post( $payment_badge($first->payment_status ?? 'unpaid') ); ?></td>
                    <td>
                        <?php if ($any_synced) : ?>
                            <span style="color:#10B981;font-size:12px;">Sent to Square</span>
                        <?php else : ?>
                            <span style="color:#6b7280;font-size:12px;">Local</span>
                        <?php endif; ?>
                    </td>
                    <td>
                        <button type="button" class="button button-small sbs-toggle-group"
                            data-gid="<?php echo esc_attr($gid); ?>"
                            style="background:#0ea5e9;color:#fff;border-color:#0284c7;">
                            Expand
                        </button>
                    </td>
                </tr>

                <!-- GROUP SUB-ROWS: individual services (hidden by default) -->
                <?php // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound ?>
                <?php foreach ($gbks as $yatoon_booking_index => $yatoon_booking_row) :
                    // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
                    $yatoon_booking_start_time = yatoon_booking_display_dt($yatoon_booking_row, 'start_time', $_sbs_local_tz, $_sbs_utc_tz);
                    // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
                    $yatoon_booking_end_time = yatoon_booking_display_dt($yatoon_booking_row, 'end_time', $_sbs_local_tz, $_sbs_utc_tz);
                    // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
                    $yatoon_is_first = ($yatoon_booking_index === 0);
                    // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
                    $yatoon_is_last  = ($yatoon_booking_index === count($gbks) - 1);
                ?>
                <tr class="sbs-group-row sbs-group-<?php echo esc_attr($gid); ?>"
                    data-booking-id="<?php echo esc_html( $yatoon_booking_row->id ); ?>"
                    data-gid="<?php echo esc_attr($gid); ?>"
                    data-status="<?php echo esc_attr($yatoon_booking_row->status); ?>"
                    data-design-upload="<?php echo esc_attr(!empty($yatoon_booking_row->design_image_url) ? '1' : '0'); ?>"
                    data-design-url="<?php echo esc_url($yatoon_booking_row->design_image_url ?? ''); ?>"
                    data-design-label="<?php echo esc_attr('#' . $yatoon_booking_row->id . ' - ' . $first->customer_name . ' - ' . ($yatoon_booking_row->service_name ?: 'Appointment')); ?>"
                    data-search="<?php echo esc_attr(strtolower($yatoon_booking_row->id . ' ' . $first->customer_name . ' ' . $first->customer_email . ' ' . $first->customer_phone . ' ' . $yatoon_booking_row->service_name . ' ' . $yatoon_booking_row->staff_name . ' ' . $yatoon_booking_row->status)); ?>"
                    data-service-order="<?php echo intval($yatoon_booking_row->service_order); ?>"
                    style="display:none;background:#f8fbff;border-left:4px solid #7dd3fc;">
                    <th class="check-column">
                        <span style="color:#94a3b8;padding-left:8px;"><?php echo esc_html( $yatoon_booking_index+1 ); ?>.</span>
                    </th>
                    <td style="padding-left:20px;">
                        <small style="color:#64748b;">#<?php echo esc_html( $yatoon_booking_row->id ); ?></small>
                    </td>
                    <td style="color:#64748b;font-size:12px;">same customer</td>
                    <td>
                        <?php echo esc_html($yatoon_booking_row->service_name ?: 'N/A'); ?>
                    </td>
                    <td><?php echo esc_html($yatoon_booking_row->staff_name ?: 'N/A'); ?></td>
                    <td>
                        <small style="color:#0369a1;font-weight:600;"><?php echo esc_html( $yatoon_booking_start_time->format('g:i A') ); ?></small>
                        <small> - <?php echo esc_html( $yatoon_booking_end_time->format('g:i A') ); ?></small>
                    </td>
                    <td>$<?php echo number_format($yatoon_booking_row->total_price, 2); ?></td>
                    <td>
                        <select class="sbs-booking-status-select" data-id="<?php echo esc_attr($yatoon_booking_row->id); ?>" style="max-width:110px;">
                            <?php // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound ?>
                            <?php foreach (array('pending'=>'Pending','confirmed'=>'Confirmed','completed'=>'Completed','no_show'=>'No-show','cancelled'=>'Cancelled') as $yatoon_status_value => $yatoon_status_label) : ?>
                                <option value="<?php echo esc_attr($yatoon_status_value); ?>" <?php selected($yatoon_booking_row->status, $yatoon_status_value); ?>><?php echo esc_html($yatoon_status_label); ?></option>
                            <?php endforeach; ?>
                        </select>
                    </td>
                    <td>
                        <select class="sbs-payment-status-select" data-id="<?php echo esc_attr($yatoon_booking_row->id); ?>" data-note="<?php echo esc_attr($yatoon_booking_row->payment_note ?? ''); ?>" style="max-width:135px;">
                            <?php // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound ?>
                            <?php foreach ($payment_labels as $yatoon_status_value => $yatoon_status_label) : ?>
                                <option value="<?php echo esc_attr($yatoon_status_value); ?>" <?php selected(($yatoon_booking_row->payment_status ?? 'unpaid'), $yatoon_status_value); ?>><?php echo esc_html($yatoon_status_label); ?></option>
                            <?php endforeach; ?>
                        </select>
                    </td>
                    <td>
                        <?php if ($yatoon_booking_row->square_synced && $yatoon_booking_row->square_booking_id) : ?>
                            <span style="color:#10B981;font-size:11px;">Yes <?php echo esc_html(substr($yatoon_booking_row->square_booking_id,0,8)); ?>...</span>
                        <?php else : ?>
                            <span style="color:#6b7280;font-size:11px;">Local</span>
                        <?php endif; ?>
                    </td>
                    <td>
                        <!-- Move Up / Move Down buttons for reordering within group -->
                        <?php if (!$yatoon_is_first) : ?>
                            <button type="button" class="button button-small sbs-move-service-up"
                                data-id="<?php echo esc_html( $yatoon_booking_row->id ); ?>"
                                data-gid="<?php echo esc_attr($gid); ?>"
                                title="Move this service earlier (swap with previous)"
                                style="padding:2px 6px;">Up</button>
                        <?php endif; ?>
                        <?php if (!$yatoon_is_last) : ?>
                            <button type="button" class="button button-small sbs-move-service-down"
                                data-id="<?php echo esc_html( $yatoon_booking_row->id ); ?>"
                                data-gid="<?php echo esc_attr($gid); ?>"
                                title="Move this service later (swap with next)"
                                style="padding:2px 6px;">Down</button>
                        <?php endif; ?>
                        <?php if ($yatoon_booking_row->status !== 'cancelled') : ?>
                            <button type="button" class="button button-small button-link-delete sbs-cancel-booking"
                                data-id="<?php echo esc_html( $yatoon_booking_row->id ); ?>" style="margin-left:4px;">Cancel</button>
                        <?php endif; ?>
                        <button type="button" class="button button-small sbs-delete-booking" data-id="<?php echo esc_attr($yatoon_booking_row->id); ?>" style="color:#999;margin-left:2px;" title="Permanently delete from local DB">Delete</button>
                    </td>
                </tr>
                <?php endforeach; ?>
                <!-- end group -->

                <?php endif; // end if solo/group ?>
            <?php endforeach; ?>
            </tbody>
        </table>
        </div>
    <?php endif; ?>
</div>

<style>
.sbs-status-confirmed { color:#10B981; font-weight:600; }
.sbs-status-pending   { color:#F59E0B; font-weight:600; }
.sbs-status-completed { color:#2563eb; font-weight:600; }
.sbs-status-noshow    { color:#7c2d12; font-weight:600; }
.sbs-status-cancelled { color:#EF4444; font-weight:600; }
.sbs-payment-badge{display:inline-block;border-radius:999px;padding:2px 8px;font-size:11px;font-weight:700;background:#f3f4f6;color:#374151;}
.sbs-payment-paid_square_pos{background:#dcfce7;color:#166534;}
.sbs-payment-deposit_paid{background:#dbeafe;color:#1d4ed8;}
.sbs-payment-no_show_fee_charged{background:#fee2e2;color:#991b1b;}
.sbs-payment-no_show_fee_waived{background:#f3f4f6;color:#4b5563;}
.sbs-payment-refunded{background:#fef3c7;color:#92400e;}
.sbs-payment-waived{background:#ede9fe;color:#5b21b6;}
.sbs-payment-unpaid{background:#fee2e2;color:#991b1b;}
.yatoon-booking-design-thumb{display:inline-flex;align-items:center;gap:6px;margin-top:5px;text-decoration:none;font-size:11px;color:#2563eb;}
.yatoon-booking-design-thumb img{width:34px;height:34px;border-radius:6px;object-fit:cover;border:1px solid #cbd5e1;background:#fff;}
.yatoon-booking-design-thumb:hover span{text-decoration:underline;}
.yatoon-design-gallery-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:14px;}
.yatoon-design-gallery-card{border:1px solid #e5e7eb;border-radius:8px;background:#fff;overflow:hidden;}
.yatoon-design-gallery-card a{display:block;text-decoration:none;color:#111827;}
.yatoon-design-gallery-card img{display:block;width:100%;aspect-ratio:1/1;object-fit:cover;background:#f8fafc;}
.yatoon-design-gallery-card span{display:block;padding:9px 10px;font-size:12px;line-height:1.35;font-weight:700;}
.sbs-group-header:hover { background:#e0f2fe !important; }
.sbs-group-row td, .sbs-group-row th { font-size:12px; }
</style>

<script>
jQuery(document).ready(function($) {

    // -- Checkbox helpers -------------------------------------------------------
    $('#sbs-select-all-bookings').on('change', function() {
        $('.sbs-booking-checkbox').prop('checked', $(this).prop('checked'));
        $('.sbs-group-checkbox').prop('checked', $(this).prop('checked'));
        updateDeleteButton();
    });
    $(document).on('change', '.sbs-booking-checkbox', function() {
        updateDeleteButton();
        const total   = $('.sbs-booking-checkbox').length;
        const checked = $('.sbs-booking-checkbox:checked').length;
        $('#sbs-select-all-bookings').prop('checked', total === checked);
    });
    // Group checkbox: toggle all hidden sub-checkboxes for the group
    $(document).on('change', '.sbs-group-checkbox', function() {
        const gid = $(this).data('gid');
        const checked = $(this).prop('checked');
        $(this).closest('tr').find('.sbs-booking-checkbox').prop('checked', checked);
        updateDeleteButton();
    });
    function updateDeleteButton() {
        const checked = $('.sbs-booking-checkbox:checked').length;
        $('#sbs-delete-selected-bookings')
            .prop('disabled', checked === 0)
            .text(checked > 0 ? 'Delete (' + checked + ')' : 'Delete Selected');
    }

    function applyBookingFilters() {
        const q = ($('#sbs-booking-search').val() || '').toLowerCase().trim();
        const status = ($('#sbs-booking-status-filter').val() || '').toLowerCase();
        const design = ($('#sbs-booking-design-filter').val() || '');

        $('#sbs-bookings-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') || '').toLowerCase() === status;
            const matchesDesign = !design || String($row.data('design-upload') || '0') === design;
            const visible = matchesText && matchesStatus && matchesDesign;
            if ($row.hasClass('sbs-group-row')) {
                if (!visible) {
                    $row.hide();
                }
                return;
            }
            $row.toggle(visible);
            if ($row.hasClass('sbs-group-header') && !visible) {
                const gid = $row.data('gid');
                $('.sbs-group-' + gid).hide();
            }
        });
    }

    $('#sbs-booking-search, #sbs-booking-status-filter, #sbs-booking-design-filter').on('input change', applyBookingFilters);
    applyBookingFilters();
    $('#sbs-booking-clear-filters').on('click', function() {
        $('#sbs-booking-search').val('');
        $('#sbs-booking-status-filter').val('');
        $('#sbs-booking-design-filter').val('');
        applyBookingFilters();
    });

    function openDesignGallery(images) {
        const unique = [];
        const seen = {};
        images.forEach(function(item) {
            if (!item.url || seen[item.url]) return;
            seen[item.url] = true;
            unique.push(item);
        });
        let html = '<div id="sbs-design-gallery-modal" style="position:fixed;inset:0;background:rgba(15,23,42,.72);z-index:99999;display:flex;align-items:center;justify-content:center;padding:20px;">';
        html += '<div style="background:#fff;border-radius:10px;max-width:860px;width:100%;max-height:86vh;display:flex;flex-direction:column;box-shadow:0 18px 50px rgba(0,0,0,.35);overflow:hidden;">';
        html += '<div style="padding:18px 22px;border-bottom:1px solid #e5e7eb;display:flex;align-items:center;justify-content:space-between;gap:12px;"><h3 style="margin:0;font-size:20px;">Design Images</h3><button type="button" id="sbs-design-gallery-close" class="button">Close</button></div>';
        html += '<div style="padding:18px 22px;overflow:auto;">';
        if (!unique.length) {
            html += '<p style="margin:0;color:#6b7280;">No design images found for the selected or visible bookings.</p>';
        } else {
            html += '<div class="yatoon-design-gallery-grid">';
            unique.forEach(function(item) {
                const safeUrl = $('<div>').text(item.url).html();
                const safeLabel = $('<div>').text(item.label || 'Design image').html();
                html += '<div class="yatoon-design-gallery-card"><a href="' + safeUrl + '" target="_blank" rel="noopener"><img src="' + safeUrl + '" alt=""><span>' + safeLabel + '</span></a></div>';
            });
            html += '</div>';
        }
        html += '</div></div></div>';
        const modal = $(html);
        $('body').append(modal);
        modal.on('click', function(ev) { if ($(ev.target).is(modal)) modal.remove(); });
        modal.find('#sbs-design-gallery-close').on('click', function() { modal.remove(); });
    }

    $('#sbs-view-design-gallery').on('click', function() {
        let images = $('.sbs-booking-checkbox:checked').map(function() {
            return { url: $(this).data('design-url') || '', label: $(this).data('design-label') || '' };
        }).get();
        if (!images.some(function(item) { return item.url; })) {
            images = $('#sbs-bookings-table tbody tr:visible').map(function() {
                return { url: $(this).data('design-url') || '', label: $(this).data('design-label') || '' };
            }).get();
        }
        openDesignGallery(images);
    });

    $(document).on('click', '.yatoon-booking-design-thumb', function(e) {
        e.preventDefault();
        openDesignGallery([{ url: $(this).attr('href'), label: $(this).closest('tr').data('design-label') || 'Design image' }]);
    });

    // -- Expand / Collapse group rows ------------------------------------------
    $(document).on('click', '.sbs-toggle-group, .sbs-group-header', function(e) {
        if ($(e.target).is('.sbs-cancel-booking')) return; // don't expand on cancel click
        const gid = $(this).data('gid') || $(this).closest('tr').data('gid');
        const $rows = $('.sbs-group-' + gid);
        const $btn  = $('.sbs-toggle-group[data-gid="' + gid + '"]');
        const isOpen = $rows.first().is(':visible');
        $rows.toggle(!isOpen);
        $btn.text(isOpen ? 'Expand' : 'Collapse');
    });

    // -- Move service UP (swap with previous in group) -------------------------
    $(document).on('click', '.sbs-move-service-up', function() {
        const gid     = $(this).data('gid');
        const id_b    = $(this).data('id'); // booking to move up
        const $rows   = $('.sbs-group-' + gid + '[data-booking-id]');
        const rowsArr = $rows.toArray();
        const idx     = rowsArr.findIndex(r => parseInt($(r).data('booking-id')) === parseInt(id_b));
        if (idx <= 0) return;
        const id_a = $(rowsArr[idx - 1]).data('booking-id');
        reorderGroup(gid, id_a, id_b);
    });

    // -- Move service DOWN (swap with next in group) ---------------------------
    $(document).on('click', '.sbs-move-service-down', function() {
        const gid   = $(this).data('gid');
        const id_a  = $(this).data('id'); // booking to move down
        const $rows = $('.sbs-group-' + gid + '[data-booking-id]');
        const rowsArr = $rows.toArray();
        const idx   = rowsArr.findIndex(r => parseInt($(r).data('booking-id')) === parseInt(id_a));
        if (idx < 0 || idx >= rowsArr.length - 1) return;
        const id_b  = $(rowsArr[idx + 1]).data('booking-id');
        reorderGroup(gid, id_a, id_b);
    });

    function reorderGroup(gid, id_a, id_b) {
        const btn = $('.sbs-move-service-up[data-gid="'+gid+'"], .sbs-move-service-down[data-gid="'+gid+'"]');
        btn.prop('disabled', true);

        $.post(ajaxurl, {
            action: 'yatoon_reorder_booking_group',
            nonce:         '<?php echo esc_html( wp_create_nonce("yatoon_admin_nonce") ); ?>',
            booking_id_a:  id_a,
            booking_id_b:  id_b
        }, function(resp) {
            if (resp.success) {
                // Reload the page to reflect new order + new times
                location.reload();
            } else {
                alert('Reorder failed: ' + (resp.data && resp.data.message ? resp.data.message : 'Unknown error'));
                btn.prop('disabled', false);
            }
        }).fail(function() {
            alert('Network error - could not reorder services.');
            btn.prop('disabled', false);
        });
    }

    $(document).on('change', '.sbs-booking-status-select', function(e) {
        e.stopPropagation();
        const $sel = $(this);
        const previous = $sel.data('previous') || $sel.find('option[selected]').val() || '';
        $sel.prop('disabled', true);
        $.post(ajaxurl, {
            action: 'yatoon_update_booking_status',
            nonce: '<?php echo esc_html( wp_create_nonce("yatoon_admin_nonce") ); ?>',
            booking_id: $sel.data('id'),
            status: $sel.val()
        }, function(resp) {
            if (resp.success) {
                location.reload();
            } else {
                alert('Failed: ' + (resp.data || 'Could not update status'));
                if (previous) $sel.val(previous);
                $sel.prop('disabled', false);
            }
        }).fail(function() {
            alert('Network error while updating booking status.');
            if (previous) $sel.val(previous);
            $sel.prop('disabled', false);
        });
    }).on('focus', '.sbs-booking-status-select', function() {
        $(this).data('previous', $(this).val());
    });

    $(document).on('change', '.sbs-payment-status-select', function(e) {
        e.stopPropagation();
        const $sel = $(this);
        const previous = $sel.data('previous') || $sel.find('option[selected]').val() || '';
        const nextStatus = $sel.val();
        const currentNote = $sel.data('note') || '';

        let html = '<div id="sbs-payment-note-modal" style="position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:99999;display:flex;align-items:center;justify-content:center;padding:20px;">';
        html += '<div style="background:#fff;border-radius:10px;max-width:420px;width:100%;box-shadow:0 12px 30px rgba(0,0,0,.25);overflow:hidden;">';
        html += '<div style="padding:20px 22px;border-bottom:1px solid #e5e7eb;"><h3 style="margin:0;font-size:20px;">Update Payment Status</h3></div>';
        html += '<div style="padding:18px 22px;">';
        html += '<p style="margin:0 0 12px;color:#4b5563;font-size:14px;">Optional note for booking #' + $sel.data('id') + ':</p>';
        html += '<textarea id="sbs-payment-note-input" style="width:100%;min-height:100px;border:1px solid #d1d5db;border-radius:8px;padding:10px;font-size:14px;box-sizing:border-box;">' + currentNote + '</textarea>';
        html += '</div>';
        html += '<div style="padding:16px 22px;text-align:right;border-top:1px solid #e5e7eb;display:flex;gap:10px;justify-content:flex-end;">';
        html += '<button type="button" id="sbs-payment-note-cancel" class="button">Cancel</button>';
        html += '<button type="button" id="sbs-payment-note-save" class="button button-primary">Save</button>';
        html += '</div></div></div>';

        const modal = $(html);
        $('body').append(modal);

        const closeModal = function() {
            modal.remove();
        };

        modal.on('click', function(ev) {
            if ($(ev.target).is(modal)) {
                if (previous) $sel.val(previous);
                closeModal();
            }
        });

        modal.find('#sbs-payment-note-cancel').on('click', function() {
            if (previous) $sel.val(previous);
            closeModal();
        });

        modal.find('#sbs-payment-note-save').on('click', function() {
            const note = modal.find('#sbs-payment-note-input').val();
            closeModal();
            $sel.prop('disabled', true);
            $.post(ajaxurl, {
                action: 'yatoon_update_payment_status',
                nonce: '<?php echo esc_html( wp_create_nonce("yatoon_admin_nonce") ); ?>',
                booking_id: $sel.data('id'),
                payment_status: nextStatus,
                payment_note: note
            }, function(resp) {
                if (resp.success) {
                    location.reload();
                } else {
                    alert('Failed: ' + (resp.data || 'Could not update payment status'));
                    if (previous) $sel.val(previous);
                    $sel.prop('disabled', false);
                }
            }).fail(function() {
                alert('Network error while updating payment status.');
                if (previous) $sel.val(previous);
                $sel.prop('disabled', false);
            });
        });
    }).on('focus', '.sbs-payment-status-select', function() {
        $(this).data('previous', $(this).val());
    });

    // -- Bulk delete ----------------------------------------------------------
    $('#sbs-delete-selected-bookings').on('click', function() {
        const selected = [];
        $('.sbs-booking-checkbox:checked').each(function() { selected.push($(this).val()); });
        if (!selected.length) return;
        if (!confirm('Delete ' + selected.length + ' booking(s)? This cannot be undone.')) return;
        const btn = $(this).prop('disabled', true).text('Deleting...');
        $.post(ajaxurl, {
            action:      'yatoon_delete_bookings',
            nonce:       '<?php echo esc_html( wp_create_nonce("yatoon_delete_bookings") ); ?>',
            booking_ids: selected
        }, function(resp) {
            if (resp.success) {
                selected.forEach(id => {
                    $('[data-booking-id="'+id+'"]').fadeOut(300, function(){ $(this).remove(); });
                });
                btn.text('Delete Selected').prop('disabled', true);
                $('#sbs-select-all-bookings').prop('checked', false);
                if (!$('.sbs-booking-checkbox').length) location.reload();
            } else {
                alert('Failed: ' + (resp.data || 'Unknown error'));
                btn.text('Delete Selected').prop('disabled', false);
            }
        });
    });

    // -- Export CSV ------------------------------------------------------------
    $('#sbs-export-bookings').on('click', function() {
        window.location.href = ajaxurl + '?action=yatoon_export_bookings&nonce=<?php echo esc_html( wp_create_nonce("yatoon_export_bookings") ); ?>';
    });

    // -- Sync from Square ---------------------------------------------------------
    $('#sbs-sync-from-square').on('click', function(){
        if (!confirm('Sync bookings from Square?\n\nThis will update existing statuses, insert missing Square bookings, and mark removed bookings as cancelled.\n\nContinue?')) return;
        const btn = $(this).prop('disabled', true).text('Syncing...');
        $('#sbs-sync-status').text('');
        $.post(ajaxurl, {
            action: 'yatoon_sync_bookings_from_square',
            nonce: '<?php echo esc_js(wp_create_nonce('yatoon_admin_nonce')); ?>'
        }, function(resp) {
            btn.prop('disabled', false).text('Sync from Square');
            if (resp.success) {
                const d = resp.data;
                $('#sbs-sync-status').html('<span style="color:#276749;">OK ' + d.message + '</span>');
                setTimeout(function(){ location.reload(); }, 2000);
            } else {
                $('#sbs-sync-status').html('<span style="color:#c53030;">Error: ' + (resp.data && resp.data.message ? resp.data.message : 'Sync failed') + '</span>');
            }
        }).fail(function(){
            btn.prop('disabled', false).text('Sync from Square');
            $('#sbs-sync-status').html('<span style="color:#c53030;">Error: Request failed</span>');
        });
    });

    // -- Delete booking (permanent local DB removal) ------------------------------
    $(document).on('click', '.sbs-view-booking', function(e) {
        e.stopPropagation();
        const btn = $(this);
        const escapeHtml = function(value) {
            return $('<div>').text(value == null ? '' : String(value)).html();
        };
        const designUrl = btn.attr('data-design-url') || '';
        const clientUrl = btn.attr('data-client-url') || '';
        const rows = [
            ['Booking ID', '#' + btn.data('id')],
            ['Customer', btn.data('customer'), clientUrl],
            ['Email', btn.data('email')],
            ['Phone', btn.data('phone') || '-'],
            ['Service', btn.data('service')],
            ['Staff', btn.data('staff')],
            ['Date', btn.data('date')],
            ['Time', btn.data('time')],
            ['Status', btn.data('status')],
            ['Payment', btn.data('payment')],
            ['Total', '$' + btn.data('total')],
            ['Booked on', btn.data('booked-at') || '-'],
        ];

        if (btn.data('note')) {
            rows.push(['Payment Note', btn.data('note')]);
        }

        let html = '<div id="sbs-booking-view-modal" style="position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:99999;display:flex;align-items:center;justify-content:center;padding:20px;">';
        html += '<div style="background:#fff;border-radius:10px;max-width:420px;width:100%;box-shadow:0 12px 30px rgba(0,0,0,.25);overflow:hidden;">';
        html += '<div style="padding:20px 22px;border-bottom:1px solid #e5e7eb;"><h3 style="margin:0;font-size:20px;">Booking Details</h3></div>';
        html += '<div style="padding:18px 22px;max-height:70vh;overflow:auto;">';
        rows.forEach(function(row) {
            html += '<div style="display:flex;gap:14px;padding:9px 0;border-bottom:1px solid #f3f4f6;">';
            html += '<div style="width:110px;flex-shrink:0;color:#6b7280;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;">' + escapeHtml(row[0]) + '</div>';
            if (row[2]) {
                html += '<div style="flex:1;color:#111827;font-size:14px;line-height:1.5;"><a href="' + escapeHtml(row[2]) + '" style="font-weight:700;text-decoration:none;">' + escapeHtml(row[1]) + '</a></div>';
            } else {
                html += '<div style="flex:1;color:#111827;font-size:14px;line-height:1.5;">' + escapeHtml(row[1]) + '</div>';
            }
            html += '</div>';
        });
        if (designUrl) {
            html += '<div style="padding:14px 0 2px;">';
            html += '<div style="color:#6b7280;font-size:12px;font-weight:700;text-transform:uppercase;margin-bottom:8px;">Design Reference</div>';
            html += '<a href="' + escapeHtml(designUrl) + '" target="_blank" rel="noopener" style="display:inline-block;text-decoration:none;">';
            html += '<img src="' + escapeHtml(designUrl) + '" alt="" style="display:block;max-width:240px;max-height:240px;object-fit:contain;border:1px solid #e5e7eb;border-radius:8px;background:#f8fafc;">';
            html += '<span style="display:block;margin-top:7px;">Open image</span></a></div>';
        }
        html += '</div>';
        html += '<div style="padding:16px 22px;text-align:right;border-top:1px solid #e5e7eb;">';
        html += '<button type="button" id="sbs-booking-view-close" class="button button-primary">Close</button>';
        html += '</div></div></div>';

        const modal = $(html);
        $('body').append(modal);
        modal.on('click', function(ev) {
            if ($(ev.target).is(modal)) modal.remove();
        });
        modal.find('#sbs-booking-view-close').on('click', function() {
            modal.remove();
        });
    });

    // -- Delete booking (permanent local DB removal) ------------------------------
    $(document).on('click', '.sbs-delete-booking', function(e) {
        e.stopPropagation();
        const id = $(this).data('id');
        if (!confirm('Permanently DELETE booking #' + id + ' from local database?\nThis does NOT cancel it in Square - use Cancel first if still active in Square.')) return;
        const btn = $(this).prop('disabled', true).text('...');
        $.post(ajaxurl, {
            action: 'yatoon_delete_single_booking',
            nonce:  '<?php echo esc_html( wp_create_nonce("yatoon_delete_bookings") ); ?>',
            id:     id
        }, function(resp) {
            if (resp.success) {
                // Fade out the booking row(s) immediately, then reload for a clean state
                const $rows = $('[data-booking-id="' + id + '"], .sbs-group-row[data-gid]').filter(function() {
                    return $(this).find('[data-id="' + id + '"]').length > 0;
                });
                const $direct = $('tr[data-booking-id="' + id + '"]');
                const $target = $direct.length ? $direct : $('tr').filter(function(){ return $(this).find('.sbs-delete-booking[data-id="'+id+'"]').length; });
                if ($target.length) {
                    $target.fadeOut(250, function(){ location.reload(); });
                } else {
                    location.reload();
                }
            } else {
                alert('Failed: ' + (resp.data && resp.data.message ? resp.data.message : 'Error'));
                btn.prop('disabled', false).text('Delete');
            }
        });
    });

    // -- Cancel booking --------------------------------------------------------
    $(document).on('click', '.sbs-cancel-booking', function(e) {
        e.stopPropagation();
        const id  = $(this).data('id');
        const btn = $(this);
        const smsEnabled = !!(window.sbsAdmin && sbsAdmin.sms_enabled);
        const html = '<div id="yn-cm" style="position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:99999;display:flex;align-items:center;justify-content:center;">' +
            '<div style="background:#fff;border-radius:8px;padding:28px 32px;max-width:360px;width:90%;box-shadow:0 8px 24px rgba(0,0,0,.25);">' +
            '<h3 style="margin:0 0 10px;">Cancel Booking #' + id + '</h3>' +
            '<p style="margin:0 0 14px;color:#555;font-size:14px;">This will cancel the appointment and update its status.</p>' +
            '<div style="margin-bottom:18px;">' +
            '<div style="font-size:13px;font-weight:600;color:#374151;margin-bottom:8px;">Notify the customer?</div>' +
            '<label style="display:flex;align-items:center;gap:8px;font-size:14px;margin-bottom:6px;cursor:pointer;">' +
            '<input type="radio" name="yn-notify-method" value="none" style="width:16px;height:16px;"> Don&rsquo;t notify' +
            '</label>' +
            '<label style="display:flex;align-items:center;gap:8px;font-size:14px;margin-bottom:6px;cursor:pointer;">' +
            '<input type="radio" name="yn-notify-method" value="email" checked style="width:16px;height:16px;"> Email' +
            '</label>' +
            (smsEnabled ? (
            '<label style="display:flex;align-items:center;gap:8px;font-size:14px;margin-bottom:6px;cursor:pointer;">' +
            '<input type="radio" name="yn-notify-method" value="sms" style="width:16px;height:16px;"> Text message' +
            '</label>' +
            '<label style="display:flex;align-items:center;gap:8px;font-size:14px;margin-bottom:6px;cursor:pointer;">' +
            '<input type="radio" name="yn-notify-method" value="both" style="width:16px;height:16px;"> Email &amp; Text' +
            '</label>'
            ) : '') +
            '</div>' +
            '<div style="display:flex;gap:10px;justify-content:flex-end;">' +
            '<button id="yn-cm-no" class="button" style="padding:6px 16px;">Keep</button>' +
            '<button id="yn-cm-yes" class="button button-primary" style="background:#e53e3e;border-color:#c53030;padding:6px 16px;">Yes, Cancel</button>' +
            '</div></div></div>';
        const modal = $(html);
        $('body').append(modal);
        modal.find('#yn-cm-no').on('click', function(){ modal.remove(); });
        modal.on('click', function(ev){ if($(ev.target).is(modal)) modal.remove(); });
        modal.find('#yn-cm-yes').on('click', function(){
            const notifyMethod = modal.find('input[name="yn-notify-method"]:checked').val() || 'none';
            modal.remove();
            btn.prop('disabled', true).text('...');
            $.post(ajaxurl, {
                action:          'yatoon_cancel_booking',
                nonce:           '<?php echo esc_html( wp_create_nonce("yatoon_cancel_booking") ); ?>',
                id:              id,
                notify_method:   notifyMethod
            }, function(resp) {
                if (resp.success) {
                    const $target = $('tr').filter(function(){ return $(this).find('.sbs-cancel-booking[data-id="'+id+'"]').length; });
                    if ($target.length) {
                        $target.css('opacity', 0.4);
                    }
                    location.reload();
                } else {
                    alert('Failed: ' + (resp.data && resp.data.message ? resp.data.message : 'Error'));
                    btn.prop('disabled', false).text('Cancel');
                }
            });
        });
    });
});
</script>

<!-- Diagnostic section -->
    <h2 style="margin:0 0 6px; color:#e53e3e; font-size:16px;">Availability Diagnostic Tool</h2>
     Helps identify yatoon_bookings records causing "No available times"
<!-- End diagnostic section -->
<div style="margin-top:40px; background:#fff; border:2px solid #e53e3e; border-radius:8px; padding:24px; max-width:900px;">
    <h2 style="margin:0 0 6px; color:#e53e3e; font-size:16px;">Availability Diagnostic Tool</h2>
    <p style="margin:0 0 16px; color:#555; font-size:13px;">
        If a specific date shows "No available times" when there should be free slots,<br>
        use this tool to inspect the raw booking records for that date.
        <strong>Records with confirmed/pending status</strong> are used by the local conflict filter - even if cancelled in Square.<br>
        If you see confirmed records that should be cancelled, use the <strong>Cancel</strong> button in the Bookings list above.
    </p>
    <div style="display:flex; gap:10px; align-items:center; margin-bottom:16px;">
        <input type="date" id="sbs-diag-date" value="<?php echo esc_attr(gmdate('Y-m-d')); ?>"
               style="padding:6px 10px; border:1px solid #ddd; border-radius:4px; font-size:14px;">
        <button type="button" id="sbs-diag-run"
                style="background:#e53e3e; color:#fff; border:none; border-radius:4px; padding:7px 18px; font-size:14px; cursor:pointer;">
            Inspect Date
        </button>
        <span id="sbs-diag-status" style="font-size:13px; color:#666;"></span>
    </div>
    <div id="sbs-diag-result"></div>
</div>

<script>
(function($){
    $('#sbs-diag-run').on('click', function(){
        const date = $('#sbs-diag-date').val();
        if (!date) { alert('Please select a date'); return; }
	        $('#sbs-diag-status').text('Loading...');
	        $('#sbs-diag-result').html('');
	        $.post(ajaxurl, {
	            action: 'yatoon_debug_date_bookings',
	            nonce:  '<?php echo esc_js(wp_create_nonce('yatoon_admin_nonce')); ?>',
	            date:   date
	        }, function(resp) {
            $('#sbs-diag-status').text('');
            if (!resp.success) { $('#sbs-diag-result').html('<p style="color:red">Error: ' + (resp.data||'unknown') + '</p>'); return; }
            const d = resp.data;
            if (d.booking_count === 0) {
                $('#sbs-diag-result').html('<p style="background:#f0fff4;border:1px solid #9ae6b4;padding:12px;border-radius:4px;color:#276749;">OK No bookings in yatoon_bookings for ' + date + '. The "No available times" on this date must come directly from Square API (not a local DB conflict).</p>');
                return;
            }
            let html = '<p style="font-size:13px;color:#555;margin-bottom:10px;">Found <strong>' + d.booking_count + '</strong> booking(s) for ' + date + ' (timezone: ' + d.timezone + ')</p>';
            html += '<p style="font-size:12px;color:#888;margin-bottom:12px;">' + d.note + '</p>';
            html += '<table style="width:100%;border-collapse:collapse;font-size:12px;">';
            html += '<thead><tr style="background:#f5f5f5;">';
            ['ID','Customer','Service','Staff','Status','start_time (DB raw)','end_time (DB raw)','Duration','Local Start','Local End','UTC Start','UTC End','Warning:'].forEach(function(h){
                html += '<th style="padding:6px 8px;border:1px solid #ddd;text-align:left;white-space:nowrap;">' + h + '</th>';
            });
            html += '</tr></thead><tbody>';
            d.bookings.forEach(function(b){
                const bad = b.flag !== '';
                const bg  = bad ? '#fff5f5' : (b.status==='cancelled'||b.status==='no_show' ? '#f9f9f9' : '#fff');
                html += '<tr style="background:' + bg + ';">';
                html += '<td style="padding:5px 8px;border:1px solid #ddd;">' + b.id + '</td>';
                html += '<td style="padding:5px 8px;border:1px solid #ddd;">' + (b.customer||'-') + '</td>';
                html += '<td style="padding:5px 8px;border:1px solid #ddd;">' + (b.service||'-') + '</td>';
                html += '<td style="padding:5px 8px;border:1px solid #ddd;">' + (b.staff||'-') + '</td>';
                html += '<td style="padding:5px 8px;border:1px solid #ddd;">' + b.status + '</td>';
                html += '<td style="padding:5px 8px;border:1px solid #ddd;font-family:monospace;">' + b.start_time_raw + '</td>';
                html += '<td style="padding:5px 8px;border:1px solid #ddd;font-family:monospace;' + (bad?'color:#e53e3e;font-weight:bold;':'') + '">' + b.end_time_raw + '</td>';
                html += '<td style="padding:5px 8px;border:1px solid #ddd;' + (bad?'color:#e53e3e;font-weight:bold;':'') + '">' + b.duration_min + ' min</td>';
                html += '<td style="padding:5px 8px;border:1px solid #ddd;font-family:monospace;font-size:11px;">' + b.start_local + '</td>';
                html += '<td style="padding:5px 8px;border:1px solid #ddd;font-family:monospace;font-size:11px;">' + b.end_local + '</td>';
                html += '<td style="padding:5px 8px;border:1px solid #ddd;font-family:monospace;font-size:11px;">' + b.start_utc + '</td>';
                html += '<td style="padding:5px 8px;border:1px solid #ddd;font-family:monospace;font-size:11px;">' + b.end_utc + '</td>';
                html += '<td style="padding:5px 8px;border:1px solid #ddd;">' + b.flag + '</td>';
                html += '</tr>';
            });
            html += '</tbody></table>';
            if (d.bookings.some(b => b.flag !== '')) {
                html += '<div style="margin-top:14px;padding:12px;background:#fff5f5;border:1px solid #feb2b2;border-radius:4px;color:#c53030;font-size:13px;">';
                html += '<strong>Warning: Suspicious records found above (highlighted red).</strong><br>These have abnormal durations and are causing the "No available times" false positive. ';
                html += 'Fix: go to WP Admin -> Square Booking -> Bookings, find these records and delete/cancel them, then re-sync from Square.</div>';
            } else {
                html += '<div style="margin-top:14px;padding:12px;background:#fffbeb;border:1px solid #f6e05e;border-radius:4px;color:#744210;font-size:13px;">';
                html += '<strong>All local records look OK (durations are normal).</strong><br>The no-availability response is coming from Square. Check staff schedules and blocks in Square.</div>';
            }
            $('#sbs-diag-result').html(html);
        }).fail(function(){ $('#sbs-diag-status').text(''); $('#sbs-diag-result').html('<p style="color:red">AJAX request failed.</p>'); });
    });
})(jQuery);
</script>

<script>
jQuery(function($){
    const yatoonOpsNonce = '<?php echo esc_js(wp_create_nonce('yatoon_admin_nonce')); ?>';
    $(document).on('click', '.yatoon-send-payment-request', function(e){
        e.stopPropagation();
        const $btn = $(this).prop('disabled', true).text('Sending...');
        $.post(ajaxurl, {
            action: 'yatoon_send_payment_request',
            nonce: yatoonOpsNonce,
            booking_id: $btn.data('id')
        }, function(resp){
            $btn.text(resp.success ? 'Request Sent' : 'Failed');
            if (!resp.success) {
                alert(resp.data && resp.data.message ? resp.data.message : 'Could not send payment request.');
                $btn.prop('disabled', false).text('Payment Request');
            }
        }).fail(function(){
            alert('Network error.');
            $btn.prop('disabled', false).text('Payment Request');
        });
    });
});
</script>

<!-- Diagnostic section -->
    <h2 style="margin:0 0 6px; color:#3182ce; font-size:16px;">Square API Direct Query</h2>
     Queries Square availability API directly for a date+service
<!-- End diagnostic section -->
<div style="margin-top:20px; background:#fff; border:2px solid #3182ce; border-radius:8px; padding:24px; max-width:900px;">
    <h2 style="margin:0 0 6px; color:#3182ce; font-size:16px;">Square API Direct Query</h2>
    <p style="margin:0 0 16px; color:#555; font-size:13px;">
        Queries Square's availability API directly for each staff+variation combination.<br>
        Shows exactly what Square returns - bypasses all local filtering.
        <strong>This tells you if Square itself is saying no times, or if our code is filtering them.</strong>
    </p>
    <div style="display:flex; gap:10px; align-items:center; flex-wrap:wrap; margin-bottom:16px;">
        <input type="date" id="sbs-sq-date" value="<?php echo esc_attr(gmdate('Y-m-d')); ?>"
               style="padding:6px 10px; border:1px solid #ddd; border-radius:4px; font-size:14px;">
        <select id="sbs-sq-service" style="padding:6px 10px; border:1px solid #ddd; border-radius:4px; font-size:14px;">
            <option value="">- Select Service -</option>
            <?php
            // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
            // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
            $yatoon_sq_services = $wpdb->get_results("SELECT id, name FROM {$wpdb->prefix}yatoon_services ORDER BY name ASC");
            // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
            foreach ($yatoon_sq_services as $yatoon_sq_svc) {
                echo '<option value="' . esc_attr($yatoon_sq_svc->id) . '">' . esc_html($yatoon_sq_svc->name) . '</option>';
            }
            ?>
        </select>
        <button type="button" id="sbs-sq-run"
                style="background:#3182ce; color:#fff; border:none; border-radius:4px; padding:7px 18px; font-size:14px; cursor:pointer;">
            Query Square
        </button>
        <span id="sbs-sq-status" style="font-size:13px; color:#666;"></span>
    </div>
    <div id="sbs-sq-result"></div>
</div>

<script>
(function($){
    $('#sbs-sq-run').on('click', function(){
        const date = $('#sbs-sq-date').val();
        const svcId = $('#sbs-sq-service').val();
        if (!date || !svcId) { alert('Please select both a date and a service'); return; }
        $('#sbs-sq-status').text('Querying Square API... (may take a few seconds)');
	        $('#sbs-sq-result').html('');
	        $.post(ajaxurl, {
	            action:     'yatoon_debug_square_availability',
	            nonce:      '<?php echo esc_js(wp_create_nonce('yatoon_admin_nonce')); ?>',
	            date:       date,
	            service_id: svcId
	        }, function(resp) {
            $('#sbs-sq-status').text('');
            if (!resp.success) { $('#sbs-sq-result').html('<p style="color:red">Error: ' + (resp.data||'unknown') + '</p>'); return; }
            const d = resp.data;
            let html = '<p style="font-size:13px;color:#555;margin-bottom:10px;">';
            html += '<strong>' + d.service_name + '</strong> on <strong>' + d.date + '</strong> ';
            html += ' - ' + d.staff_count + ' eligible staff - ' + d.variation_count + ' variation(s) - timezone: ' + d.timezone + '</p>';

            if (d.staff_count === 0) {
                html += '<p style="background:#fff5f5;border:1px solid #feb2b2;padding:12px;border-radius:4px;color:#c53030;">Warning: No eligible staff found for this service. Check yatoon_staff_services assignments.</p>';
            }

            d.results_per_staff.forEach(function(st) {
                html += '<div style="margin-bottom:16px;border:1px solid #e2e8f0;border-radius:6px;overflow:hidden;">';
html += '<div style="background:#ebf8ff;padding:8px 14px;font-weight:600;font-size:13px;">' + st.staff_name + ' <span style="font-weight:normal;color:#718096;font-size:11px;">(sq_id: ' + st.staff_sq_id + ')</span></div>';
                st.variations.forEach(function(v) {
                    const hasSlots = v.slots_count > 0;
                    const bg = hasSlots ? '#f0fff4' : '#fffaf0';
                    const icon = hasSlots ? 'OK' : 'X';
                    html += '<div style="padding:10px 14px;background:' + bg + ';border-top:1px solid #e2e8f0;">';
                    html += '<div style="font-size:12px;margin-bottom:4px;">';
                    html += icon + ' <strong>' + v.var_name + '</strong>';
                    html += ' <span style="color:#718096;">(' + v.duration_min + 'min, group: "' + (v.group_name||'[none]') + '")</span>';
                    html += ' -> <strong>' + v.slots_count + ' slot(s)</strong> from Square';
                    if (v.error) html += ' <span style="color:#c53030;">Error: ' + v.error + '</span>';
                    html += '</div>';
                    if (hasSlots) {
                        html += '<div style="font-size:11px;color:#276749;">' + v.slots.join(' - ') + '</div>';
                    } else if (!v.error) {
                        html += '<div style="font-size:11px;color:#c05621;">Square returned 0 slots for this staff+variation on this date.</div>';
                    }
                    html += '</div>';
                });
                html += '</div>';
            });

            // Summary diagnosis
            const totalSlots = d.results_per_staff.reduce(function(sum, st) {
                return sum + st.variations.reduce(function(s2, v) { return s2 + v.slots_count; }, 0);
            }, 0);
            if (totalSlots === 0) {
                html += '<div style="margin-top:12px;padding:12px;background:#fff5f5;border:1px solid #feb2b2;border-radius:4px;color:#c53030;font-size:13px;">';
                html += '<strong>Warning: Square returned 0 slots for ALL staff+variations on this date.</strong><br>';
                html += 'This means Square itself says no one is available - likely a staff shift/schedule issue in Square, not a plugin bug. ';
                html += 'Check Team -> Schedule in your Square dashboard for this date.';
                html += '</div>';
            } else {
                html += '<div style="margin-top:12px;padding:12px;background:#f0fff4;border:1px solid #9ae6b4;border-radius:4px;color:#276749;font-size:13px;">';
                html += '<strong>OK Square returned ' + totalSlots + ' total slot(s).</strong> ';
                html += 'If the booking form still shows "No available times", the plugin's local filtering is the cause. Share these results with support.';
                html += '</div>';
            }
            $('#sbs-sq-result').html(html);
        }).fail(function(){ $('#sbs-sq-status').text(''); $('#sbs-sq-result').html('<p style="color:red">AJAX request failed.</p>'); });
    });
})(jQuery);
</script>
