<?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.DB.PreparedSQLPlaceholders.UnfinishedPrepare, WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange
/**
 * Orders, invoices, payments, balances, and refunds.
 */
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

class YATOON_Commerce {
    public static function init() {
        self::install_schema();
        add_action( 'yatoon_booking_created', array( __CLASS__, 'create_for_booking' ), 70, 1 );
        add_action( 'yatoon_payment_status_changed', array( __CLASS__, 'sync_payment_status' ), 20, 4 );
        add_action( 'admin_menu', array( __CLASS__, 'add_menu' ), 23 );
        add_action( 'admin_post_yatoon_record_order_payment', array( __CLASS__, 'record_payment' ) );
        add_action( 'admin_post_yatoon_record_order_refund', array( __CLASS__, 'record_refund' ) );
        add_action( 'template_redirect', array( __CLASS__, 'render_public_invoice' ) );
    }

    public static function install_schema() {

        $schema_revision = YATOON_DB_VERSION . '-refunds-v2';
if ( get_option( 'yatoon_commerce_schema_revision', '' ) === $schema_revision ) {
            return;
        }
        global $wpdb;
        require_once ABSPATH . 'wp-admin/includes/upgrade.php';
        $charset = $wpdb->get_charset_collate();
        dbDelta( "CREATE TABLE {$wpdb->prefix}yatoon_orders (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            order_number varchar(40) NOT NULL,
            source_key varchar(100) NOT NULL,
            primary_booking_id bigint(20) NOT NULL,
            customer_name varchar(255) DEFAULT '',
            customer_email varchar(255) DEFAULT '',
            customer_phone varchar(60) DEFAULT '',
            currency varchar(10) DEFAULT 'USD',
            subtotal decimal(12,2) DEFAULT 0,
            discount_total decimal(12,2) DEFAULT 0,
            tip_total decimal(12,2) DEFAULT 0,
            tax_total decimal(12,2) DEFAULT 0,
            total decimal(12,2) DEFAULT 0,
            paid_total decimal(12,2) DEFAULT 0,
            refunded_total decimal(12,2) DEFAULT 0,
            balance_due decimal(12,2) DEFAULT 0,
            status varchar(30) DEFAULT 'open',
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            updated_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY (id),
            UNIQUE KEY source_key (source_key),
            KEY order_number (order_number),
            KEY primary_booking_id (primary_booking_id),
            KEY status (status)
        ) {$charset};" );
        self::ensure_order_number_uniqueness();
        dbDelta( "CREATE TABLE {$wpdb->prefix}yatoon_order_items (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            order_id bigint(20) NOT NULL,
            booking_id bigint(20) DEFAULT NULL,
            item_type varchar(30) DEFAULT 'service',
            name varchar(255) NOT NULL,
            quantity decimal(10,2) DEFAULT 1,
            unit_price decimal(12,2) DEFAULT 0,
            line_total decimal(12,2) DEFAULT 0,
            metadata longtext DEFAULT NULL,
            PRIMARY KEY (id),
            KEY order_id (order_id),
            KEY booking_id (booking_id)
        ) {$charset};" );
        dbDelta( "CREATE TABLE {$wpdb->prefix}yatoon_invoices (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            order_id bigint(20) NOT NULL,
            invoice_number varchar(40) NOT NULL,
            public_token varchar(64) NOT NULL,
            status varchar(30) DEFAULT 'open',
            issued_at datetime DEFAULT CURRENT_TIMESTAMP,
            due_at datetime DEFAULT NULL,
            paid_at datetime DEFAULT NULL,
            PRIMARY KEY (id),
            UNIQUE KEY order_id (order_id),
            UNIQUE KEY invoice_number (invoice_number),
            UNIQUE KEY public_token (public_token)
        ) {$charset};" );
        dbDelta( "CREATE TABLE {$wpdb->prefix}yatoon_payments (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            order_id bigint(20) NOT NULL,
            booking_id bigint(20) DEFAULT NULL,
            payment_type varchar(30) DEFAULT 'payment',
            amount decimal(12,2) NOT NULL DEFAULT 0,
            method varchar(40) DEFAULT '',
            provider varchar(40) DEFAULT '',
            provider_reference varchar(255) DEFAULT '',
            parent_payment_id bigint(20) DEFAULT NULL,
            provider_status varchar(40) DEFAULT '',
            idempotency_key varchar(100) DEFAULT NULL,
            note text DEFAULT NULL,
            created_by bigint(20) DEFAULT NULL,
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            PRIMARY KEY (id),
            KEY order_id (order_id),
            KEY booking_id (booking_id),
            KEY provider_reference (provider_reference),
            KEY parent_payment_id (parent_payment_id),
            UNIQUE KEY idempotency_key (idempotency_key)
        ) {$charset};" );
        if ( YATOON_Schema_Verifier::tables_exist( array( 'yatoon_orders', 'yatoon_order_items', 'yatoon_invoices', 'yatoon_payments' ) ) ) {
            update_option( 'yatoon_commerce_schema', YATOON_DB_VERSION, false );
            update_option( 'yatoon_commerce_schema_revision', $schema_revision, false );
        }
    }

    /** Add a non-conflicting uniqueness guarantee when legacy data permits. */
    private static function ensure_order_number_uniqueness() {
        global $wpdb;
        $table = $wpdb->prefix . 'yatoon_orders';
        $exists = $wpdb->get_var(
            $wpdb->prepare(
                "SELECT COUNT(*) FROM information_schema.statistics WHERE table_schema = DATABASE() AND table_name = %s AND index_name = %s",
                $table,
                'yatoon_order_number_unique'
            )
        );
        if ( $exists ) {
            return;
        }
        $duplicate = $wpdb->get_var(
            "SELECT order_number FROM `{$table}` WHERE order_number <> '' GROUP BY order_number HAVING COUNT(*) > 1 LIMIT 1"
        );
        if ( null === $duplicate ) {
            $wpdb->query( "ALTER TABLE `{$table}` ADD UNIQUE KEY `yatoon_order_number_unique` (`order_number`)" );
        }
    }

    public static function create_for_booking( $booking ) {
        $booking_id = absint( $booking['booking_id'] ?? $booking['id'] ?? 0 );
        if ( ! $booking_id ) {
            return;
        }
        global $wpdb;
        $row = $wpdb->get_row( $wpdb->prepare(
            "SELECT * FROM {$wpdb->prefix}yatoon_bookings WHERE id=%d",
            $booking_id
        ) );
        if ( ! $row ) {
            return;
        }
        $source_key = ! empty( $row->group_booking_id ) ? 'group:' . $row->group_booking_id : 'booking:' . $booking_id;
        $existing = (int) $wpdb->get_var( $wpdb->prepare(
            "SELECT id FROM {$wpdb->prefix}yatoon_orders WHERE source_key=%s",
            $source_key
        ) );
        if ( $existing ) {
            return;
        }
        $bookings = ! empty( $row->group_booking_id )
            ? $wpdb->get_results( $wpdb->prepare(
                "SELECT b.*, s.name service_name FROM {$wpdb->prefix}yatoon_bookings b
                 LEFT JOIN {$wpdb->prefix}yatoon_services s ON s.id=b.service_id
                 WHERE b.group_booking_id=%s ORDER BY b.start_time ASC",
                $row->group_booking_id
            ) )
            : array( $wpdb->get_row( $wpdb->prepare(
                "SELECT b.*, s.name service_name FROM {$wpdb->prefix}yatoon_bookings b
                 LEFT JOIN {$wpdb->prefix}yatoon_services s ON s.id=b.service_id WHERE b.id=%d",
                $booking_id
            ) ), );
        $subtotal = array_sum( array_map( function ( $item ) {

            return max( 0, (float) $item->total_price - (float) ( $item->tip_amount ?? 0 ) );
}, $bookings ) );
$tip = array_sum( array_map( function ( $item ) {

            return (float) ( $item->tip_amount ?? 0 );
}, $bookings ) );
$total = max( 0, $subtotal + $tip );
        $wpdb->insert(
            $wpdb->prefix . 'yatoon_orders',
            array(
                'order_number' => self::next_number( 'ORD' ),
                'source_key' => $source_key,
                'primary_booking_id' => $booking_id,
                'customer_name' => $row->customer_name,
                'customer_email' => $row->customer_email,
                'customer_phone' => $row->customer_phone,
                'currency' => get_option( 'yatoon_currency', 'USD' ),
                'subtotal' => $subtotal,
                'tip_total' => $tip,
                'total' => $total,
                'balance_due' => $total,
                'status' => 'open',
                'created_at' => current_time( 'mysql' ),
                'updated_at' => current_time( 'mysql' ),
            )
        );
        $order_id = (int) $wpdb->insert_id;
        if ( ! $order_id ) {
            return;
        }
        foreach ( $bookings as $item ) {
            $wpdb->insert(
                $wpdb->prefix . 'yatoon_order_items',
                array(
                    'order_id' => $order_id,
                    'booking_id' => (int) $item->id,
                    'item_type' => 'service',
                    'name' => $item->service_name ?: 'Service',
                    'quantity' => 1,
                    'unit_price' => max( 0, (float) $item->total_price - (float) ( $item->tip_amount ?? 0 ) ),
                    'line_total' => max( 0, (float) $item->total_price - (float) ( $item->tip_amount ?? 0 ) ),
                )
            );
        }
        if ( $tip > 0 ) {
            $wpdb->insert(
                $wpdb->prefix . 'yatoon_order_items',
                array( 'order_id' => $order_id, 'item_type' => 'tip', 'name' => 'Tip', 'quantity' => 1, 'unit_price' => $tip, 'line_total' => $tip )
            );
        }
        $wpdb->insert(
            $wpdb->prefix . 'yatoon_invoices',
            array(
                'order_id' => $order_id,
                'invoice_number' => self::next_number( 'INV' ),
                'public_token' => wp_generate_password( 40, false, false ),
                'status' => 'open',
                'issued_at' => current_time( 'mysql' ),
            )
        );
        if ( 'deposit_paid' === $row->payment_status && (float) $row->deposit_amount > 0 ) {
            $deposit_ref      = (string) ( $row->deposit_intent_id ?? '' );
            $deposit_provider = strpos( $deposit_ref, 'square:' ) === 0 ? 'square' : 'booking';
            $deposit_note     = $deposit_provider === 'square' ? 'Square payment captured before booking confirmation.' : 'Deposit captured before booking confirmation.';
            self::insert_payment( $order_id, $booking_id, 'payment', (float) $row->deposit_amount, 'deposit', $deposit_provider, $deposit_ref, $deposit_note );
        }
        self::recalculate( $order_id );
    }

    public static function sync_payment_status( $booking_id, $new_status, $old_status = '', $note = '' ) {
        if ( $new_status === $old_status ) {
            return;
        }
        global $wpdb;
        $order = $wpdb->get_row( $wpdb->prepare(
            "SELECT o.* FROM {$wpdb->prefix}yatoon_orders o
             LEFT JOIN {$wpdb->prefix}yatoon_order_items i ON i.order_id=o.id
             WHERE i.booking_id=%d LIMIT 1",
            $booking_id
        ) );
        if ( ! $order ) {
            return;
        }
        if ( 'refunded' === $new_status ) {
            $available = max( 0, (float) $order->paid_total - (float) $order->refunded_total );
            if ( $available > 0 ) {
                self::insert_payment( $order->id, $booking_id, 'refund', -$available, 'status_update', 'booking', '', $note );
            }
        } elseif ( in_array( $new_status, array( 'paid_square_pos', 'paid', 'deposit_paid' ), true ) ) {
            $amount = 'deposit_paid' === $new_status
                ? (float) $wpdb->get_var( $wpdb->prepare( "SELECT deposit_amount FROM {$wpdb->prefix}yatoon_bookings WHERE id=%d", $booking_id ) )
                : max( 0, (float) $order->balance_due );
            if ( $amount > 0 ) {
                self::insert_payment( $order->id, $booking_id, 'payment', $amount, $new_status, 'booking', '', $note );
            }
        }
        self::recalculate( $order->id );
    }

    /**
     * Record a fee taken outside the normal checkout, against a booking.
     *
     * 4.6.1: added for card-on-file no-show and late-cancellation fees. Those
     * are real money and have to appear in the ledger and in reporting like
     * any other payment, but the existing entry points are either an
     * admin-post handler (record_payment) or private. This is the seam.
     *
     * @param int    $booking_id Booking the fee belongs to.
     * @param float  $amount     Amount in store currency.
     * @param string $method     'no_show_fee' | 'late_cancel_fee' | 'fee'
     * @param string $provider   'stripe' | 'square' | ...
     * @param string $reference  Provider reference (e.g. PaymentIntent id).
     * @param string $note       Human-readable note.
     * @return int Payment row id, or 0 when nothing could be recorded.
     */
    public static function record_booking_fee( $booking_id, $amount, $method, $provider, $reference, $note = '' ) {
        global $wpdb;
        $booking_id = absint( $booking_id );
        $amount     = round( (float) $amount, 2 );
        if ( ! $booking_id || $amount <= 0 ) {
            return 0;
        }
        $orders = $wpdb->prefix . 'yatoon_orders';
        $order_id = (int) $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$orders} WHERE primary_booking_id=%d ORDER BY id DESC LIMIT 1", $booking_id ) );
        if ( ! $order_id ) {
            self::create_for_booking( array( 'booking_id' => $booking_id ) );
            $order_id = (int) $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$orders} WHERE primary_booking_id=%d ORDER BY id DESC LIMIT 1", $booking_id ) );
        }
        if ( ! $order_id ) {
            return 0;
        }
        $payment_id = self::insert_payment(
            $order_id,
            $booking_id,
            'payment',
            $amount,
            $method,
            $provider,
            $reference,
            $note,
            0,
            'succeeded',
            $reference ? 'fee:' . $reference : ''
        );
        self::recalculate( $order_id );
        return (int) $payment_id;
    }

    private static function insert_payment( $order_id, $booking_id, $type, $amount, $method, $provider, $reference, $note, $parent_payment_id = 0, $provider_status = '', $idempotency_key = '' ) {

        global $wpdb;
        $wpdb->insert(
            $wpdb->prefix . 'yatoon_payments',
            array(
                'order_id' => absint( $order_id ),
                'booking_id' => absint( $booking_id ) ?: null,
                'payment_type' => sanitize_key( $type ),
                'amount' => round( (float) $amount, 2 ),
                'method' => sanitize_key( $method ),
                'provider' => sanitize_key( $provider ),
                'provider_reference' => sanitize_text_field( $reference ),
                'parent_payment_id' => absint( $parent_payment_id ) ?: null,
                'provider_status' => sanitize_key( $provider_status ),
                'idempotency_key' => $idempotency_key ? sanitize_text_field( $idempotency_key ) : null,
                'note' => sanitize_textarea_field( $note ),
                'created_by' => get_current_user_id() ?: null,
                'created_at' => current_time( 'mysql' ),
            )
        );
return (int) $wpdb->insert_id;
    }

    private static function recalculate( $order_id ) {
        global $wpdb;
        $order = $wpdb->get_row( $wpdb->prepare( "SELECT total FROM {$wpdb->prefix}yatoon_orders WHERE id=%d", $order_id ) );
        if ( ! $order ) {
            return;
        }
        $paid = (float) $wpdb->get_var( $wpdb->prepare(
            "SELECT COALESCE(SUM(amount),0) FROM {$wpdb->prefix}yatoon_payments WHERE order_id=%d AND payment_type='payment'",
            $order_id
        ) );
        $refunds = abs( (float) $wpdb->get_var( $wpdb->prepare(
            "SELECT COALESCE(SUM(amount),0) FROM {$wpdb->prefix}yatoon_payments WHERE order_id=%d AND payment_type='refund'",
            $order_id
        ) ) );
        $net_paid = max( 0, $paid - $refunds );
        $balance = max( 0, (float) $order->total - $net_paid );
        $status = $refunds >= $paid && $paid > 0 ? 'refunded' : ( $balance <= 0 ? 'paid' : ( $net_paid > 0 ? 'partial' : 'open' ) );
        $wpdb->update(
            $wpdb->prefix . 'yatoon_orders',
            array( 'paid_total' => $paid, 'refunded_total' => $refunds, 'balance_due' => $balance, 'status' => $status, 'updated_at' => current_time( 'mysql' ) ),
            array( 'id' => $order_id )
        );
        $wpdb->update(
            $wpdb->prefix . 'yatoon_invoices',
            array( 'status' => $status, 'paid_at' => 'paid' === $status ? current_time( 'mysql' ) : null ),
            array( 'order_id' => $order_id )
        );
    }

    private static function next_number( $prefix ) {
        return $prefix . '-' . gmdate( 'ymd' ) . '-' . strtoupper( wp_generate_password( 6, false, false ) );
    }

    public static function add_menu() {
        add_submenu_page(
            'yatoon-booking-system',
            __( 'Orders & Invoices', 'yatoon-booking-system' ),
            __( 'Orders & Invoices', 'yatoon-booking-system' ),
            'manage_options',
            'yatoon-orders',
            array( __CLASS__, 'render_admin' )
        );
    }

    private static function require_admin() {
        if ( ! current_user_can( 'manage_options' ) ) {
            wp_die( esc_html__( 'You do not have permission to manage orders.', 'yatoon-booking-system' ) );
        }
    }

    public static function record_payment() {
        self::require_admin();
        check_admin_referer( 'yatoon_order_money' );
        $order_id = absint( $_POST['order_id'] ?? 0 );
        $amount = max( 0, (float) ( $_POST['amount'] ?? 0 ) );
        if ( $order_id && $amount > 0 ) {
            self::insert_payment( $order_id, 0, 'payment', $amount, $_POST['method'] ?? 'manual', 'manual', $_POST['reference'] ?? '', $_POST['note'] ?? '' );
            self::recalculate( $order_id );
        }
        wp_safe_redirect( admin_url( 'admin.php?page=yatoon-orders&order_id=' . $order_id ) );
        exit;
    }

    public static function record_refund() {

        self::require_admin();
        check_admin_referer( 'yatoon_order_money' );
        $order_id = absint( $_POST['order_id'] ?? 0 );
        $amount = max( 0, (float) ( $_POST['amount'] ?? 0 ) );
        $method = sanitize_key( $_POST['method'] ?? 'manual' );
$notice = '';
if ( $order_id && $amount > 0 ) {
            if ( in_array( $method, array( 'square', 'stripe' ), true ) ) {
                $result = self::process_provider_refund( $order_id, $amount, $method, $_POST['note'] ?? '' );
$notice = is_wp_error( $result ) ? $result->get_error_message() : __( 'The payment provider accepted the refund.', 'yatoon-booking-system' );
} else {
                $available = self::refundable_amount( $order_id );
if ( $amount > $available + 0.00001 ) {
                    $notice = __( 'Refund amount exceeds the remaining paid amount.', 'yatoon-booking-system' );
} else {
                    self::insert_payment( $order_id, 0, 'refund', -$amount, $method, 'manual', $_POST['reference'] ?? '', $_POST['note'] ?? '', 0, 'recorded' );
self::recalculate( $order_id );
$notice = __( 'Manual refund recorded.', 'yatoon-booking-system' );
}
            }
        }
        wp_safe_redirect( add_query_arg( array(
            'page' => 'yatoon-orders',
            'order_id' => $order_id,
            'yatoon_notice' => $notice,
        ), admin_url( 'admin.php' ) ) );
exit;
}

    private static function refundable_amount( $order_id ) {

        global $wpdb;
$order = $wpdb->get_row( $wpdb->prepare( "SELECT paid_total,refunded_total FROM {$wpdb->prefix}yatoon_orders WHERE id=%d", $order_id ) );
return $order ? max( 0, (float) $order->paid_total - (float) $order->refunded_total ) : 0.0;
}

    public static function process_provider_refund( $order_id, $amount, $provider, $reason = '' ) {

        return new WP_Error( 'provider_refunds_pro_only', __( 'Direct Square and Stripe refunds require Yatoon Pro.', 'yatoon-booking-system' ) );
    }
    public static function render_admin() {
        self::require_admin();
        global $wpdb;
        $order_id = absint( $_GET['order_id'] ?? 0 );
        echo '<div class="wrap yatoon-commerce"><h1>Orders &amp; Invoices</h1>';
        if ( $order_id ) {
            if ( ! empty( $_GET['yatoon_notice'] ) ) {
                echo '<div class="notice notice-info is-dismissible"><p>' . esc_html( sanitize_text_field( wp_unslash( $_GET['yatoon_notice'] ) ) ) . '</p></div>';
            }
            $order = $wpdb->get_row( $wpdb->prepare(
                "SELECT o.*, i.invoice_number, i.public_token FROM {$wpdb->prefix}yatoon_orders o
                 LEFT JOIN {$wpdb->prefix}yatoon_invoices i ON i.order_id=o.id WHERE o.id=%d",
                $order_id
            ) );
            if ( ! $order ) {
                echo '<p>Order not found.</p></div>';
                return;
            }
            $items = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}yatoon_order_items WHERE order_id=%d ORDER BY id", $order_id ) );
            $payments = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}yatoon_payments WHERE order_id=%d ORDER BY id DESC", $order_id ) );
            $invoice_url = add_query_arg( 'yatoon_invoice', rawurlencode( $order->public_token ), home_url( '/' ) );
            ?>
            <p><a href="<?php echo esc_url( admin_url( 'admin.php?page=yatoon-orders' ) ); ?>">&larr; All orders</a></p>
            <section class="yc-panel"><div class="yc-head"><div><h2><?php echo esc_html( $order->order_number ); ?></h2><p><?php echo esc_html( $order->customer_name ); ?> · <?php echo esc_html( $order->customer_email ); ?></p></div><span class="yc-status"><?php echo esc_html( ucfirst( $order->status ) ); ?></span></div>
            <table class="widefat striped"><tbody><?php foreach ( $items as $item ) : ?><tr><td><?php echo esc_html( $item->name ); ?></td><td class="num"><?php echo esc_html( number_format_i18n( $item->line_total, 2 ) ); ?></td></tr><?php endforeach; ?></tbody><tfoot><tr><th>Total</th><th class="num"><?php echo esc_html( $order->currency . ' ' . number_format_i18n( $order->total, 2 ) ); ?></th></tr><tr><th>Paid</th><th class="num"><?php echo esc_html( number_format_i18n( $order->paid_total, 2 ) ); ?></th></tr><tr><th>Refunded</th><th class="num"><?php echo esc_html( number_format_i18n( $order->refunded_total, 2 ) ); ?></th></tr><tr><th>Balance due</th><th class="num"><?php echo esc_html( number_format_i18n( $order->balance_due, 2 ) ); ?></th></tr></tfoot></table>
            <p><a class="button" target="_blank" href="<?php echo esc_url( $invoice_url ); ?>">View invoice <?php echo esc_html( $order->invoice_number ); ?></a></p></section>
            <div class="yc-grid"><?php foreach ( array( 'payment' => 'Record payment', 'refund' => 'Record refund' ) as $type => $label ) : ?><section class="yc-panel"><h2><?php echo esc_html( $label ); ?></h2><form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>"><?php wp_nonce_field( 'yatoon_order_money' ); ?><input type="hidden" name="action" value="yatoon_record_order_<?php echo esc_attr( $type ); ?>"><input type="hidden" name="order_id" value="<?php echo esc_attr( $order_id ); ?>"><label>Amount<input type="number" name="amount" min="0.01" step="0.01" required></label><label>Method<select name="method"><option value="cash">Cash</option><option value="card">Card</option><option value="square">Square</option><option value="stripe">Stripe</option><option value="other">Other</option></select></label><label>Reference<input name="reference"></label><label>Note<textarea name="note"></textarea></label><button class="button button-primary"><?php echo esc_html( $label ); ?></button></form></section><?php endforeach; ?></div>
            <section class="yc-panel"><h2>Payment history</h2><table class="widefat striped"><thead><tr><th>Date</th><th>Type</th><th>Method</th><th>Reference</th><th class="num">Amount</th></tr></thead><tbody><?php foreach ( $payments as $payment ) : ?><tr><td><?php echo esc_html( $payment->created_at ); ?></td><td><?php echo esc_html( ucfirst( $payment->payment_type ) ); ?></td><td><?php echo esc_html( $payment->method ); ?></td><td><?php echo esc_html( $payment->provider_reference ); ?></td><td class="num"><?php echo esc_html( number_format_i18n( $payment->amount, 2 ) ); ?></td></tr><?php endforeach; ?></tbody></table></section>
            <?php
        } else {
            $search = sanitize_text_field( wp_unslash( $_GET['s'] ?? '' ) );
            $where = '';
            if ( $search ) {
                $like = '%' . $wpdb->esc_like( $search ) . '%';
                $where = $wpdb->prepare( 'WHERE order_number LIKE %s OR customer_name LIKE %s OR customer_email LIKE %s', $like, $like, $like );
            }
            $orders = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}yatoon_orders {$where} ORDER BY id DESC LIMIT 100" );
            ?><form method="get"><input type="hidden" name="page" value="yatoon-orders"><p class="search-box"><input name="s" value="<?php echo esc_attr( $search ); ?>" placeholder="Order, customer, or email"><button class="button">Search</button></p></form><table class="widefat striped"><thead><tr><th>Order</th><th>Customer</th><th>Date</th><th>Status</th><th class="num">Total</th><th class="num">Balance</th></tr></thead><tbody><?php foreach ( $orders as $order ) : ?><tr><td><a href="<?php echo esc_url( admin_url( 'admin.php?page=yatoon-orders&order_id=' . $order->id ) ); ?>"><?php echo esc_html( $order->order_number ); ?></a></td><td><?php echo esc_html( $order->customer_name ); ?><br><small><?php echo esc_html( $order->customer_email ); ?></small></td><td><?php echo esc_html( $order->created_at ); ?></td><td><?php echo esc_html( ucfirst( $order->status ) ); ?></td><td class="num"><?php echo esc_html( number_format_i18n( $order->total, 2 ) ); ?></td><td class="num"><?php echo esc_html( number_format_i18n( $order->balance_due, 2 ) ); ?></td></tr><?php endforeach; ?></tbody></table><?php
        }
        echo '<style>.yatoon-commerce{max-width:1200px}.yc-panel{background:#fff;border:1px solid #dcdcde;border-radius:6px;padding:20px;margin:18px 0}.yc-head{display:flex;justify-content:space-between;gap:20px}.yc-head h2{margin:0}.yc-status{font-weight:700}.yc-grid{display:grid;grid-template-columns:1fr 1fr;gap:18px}.yc-panel label{display:block;font-weight:600;margin:12px 0}.yc-panel input,.yc-panel select,.yc-panel textarea{display:block;width:100%;margin-top:5px}.num{text-align:right}@media(max-width:782px){.yc-grid{grid-template-columns:1fr}}</style></div>';
    }

    public static function render_public_invoice() {
        $token = sanitize_text_field( wp_unslash( $_GET['yatoon_invoice'] ?? '' ) );
        if ( ! $token ) {
            return;
        }
        global $wpdb;
        $invoice = $wpdb->get_row( $wpdb->prepare(
            "SELECT i.*, o.* FROM {$wpdb->prefix}yatoon_invoices i
             JOIN {$wpdb->prefix}yatoon_orders o ON o.id=i.order_id WHERE i.public_token=%s",
            $token
        ) );
        if ( ! $invoice ) {
            status_header( 404 );
            exit( esc_html__( 'Invoice not found.', 'yatoon-booking-system' ) );
        }
        $items = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}yatoon_order_items WHERE order_id=%d ORDER BY id", $invoice->order_id ) );
        status_header( 200 );
        nocache_headers();
        ?><!doctype html><html><head><meta charset="<?php bloginfo( 'charset' ); ?>"><meta name="viewport" content="width=device-width,initial-scale=1"><title><?php echo esc_html( $invoice->invoice_number ); ?></title><style>body{margin:0;background:#f5f6f8;color:#172033;font:16px -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}.invoice{max-width:760px;margin:40px auto;background:#fff;padding:40px;border:1px solid #e1e4e8}.head{display:flex;justify-content:space-between;gap:24px;border-bottom:2px solid #172033;padding-bottom:24px}.head h1{margin:0}.status{text-transform:uppercase;font-weight:700}table{width:100%;border-collapse:collapse;margin:28px 0}td,th{padding:13px 0;border-bottom:1px solid #e5e7eb;text-align:left}.num{text-align:right}.totals{margin-left:auto;width:min(360px,100%)}@media(max-width:600px){.invoice{margin:0;padding:24px}.head{display:block}.status{display:block;margin-top:12px}}</style></head><body><main class="invoice"><div class="head"><div><h1><?php echo esc_html( get_option( 'yatoon_business_name', get_bloginfo( 'name' ) ) ); ?></h1><p>Invoice <?php echo esc_html( $invoice->invoice_number ); ?></p></div><span class="status"><?php echo esc_html( $invoice->status ); ?></span></div><p><strong>Bill to</strong><br><?php echo esc_html( $invoice->customer_name ); ?><br><?php echo esc_html( $invoice->customer_email ); ?></p><table><thead><tr><th>Description</th><th class="num">Amount</th></tr></thead><tbody><?php foreach ( $items as $item ) : ?><tr><td><?php echo esc_html( $item->name ); ?></td><td class="num"><?php echo esc_html( $invoice->currency . ' ' . number_format_i18n( $item->line_total, 2 ) ); ?></td></tr><?php endforeach; ?></tbody></table><table class="totals"><tr><th>Total</th><td class="num"><?php echo esc_html( number_format_i18n( $invoice->total, 2 ) ); ?></td></tr><tr><th>Paid</th><td class="num"><?php echo esc_html( number_format_i18n( $invoice->paid_total - $invoice->refunded_total, 2 ) ); ?></td></tr><tr><th>Balance due</th><td class="num"><strong><?php echo esc_html( number_format_i18n( $invoice->balance_due, 2 ) ); ?></strong></td></tr></table></main></body></html><?php
        exit;
    }
}
