<?php
namespace Bookaro\Utils;

defined( 'ABSPATH' ) || exit;

class BookingPolicyPresenter
{
    public static function apply_window_template( string $template, int $hours ): string
    {
        $template = trim( $template );
        if ( $template === '' ) {
            return '';
        }

        $hours_value = (string) max( 0, $hours );

        return str_replace(
            [ '{{hours}}', '{{window_hours}}', '{{window}}' ],
            $hours_value,
            $template
        );
    }

    public static function build_policy_text( string $action, int $hours, string $template = '', bool $window_applies = true ): string
    {
        $action = self::normalize_action( $action );
        $hours  = max( 0, $hours );
        $custom = self::apply_window_template( $template, $hours );
        if ( $custom !== '' ) {
            return $custom;
        }

        if ( $hours > 0 && $window_applies ) {
            if ( $action === 'cancel' ) {
                return sprintf(
                    /* translators: %d: cancellation cutoff in hours. */
                    __( 'Cancellation window: request cancellation at least %d hours before the scheduled start.', 'mybookaro' ),
                    $hours
                );
            }

            return sprintf(
                /* translators: %d: reschedule cutoff in hours. */
                __( 'Reschedule window: request a new time at least %d hours before the scheduled start.', 'mybookaro' ),
                $hours
            );
        }

        if ( $action === 'cancel' ) {
            if ( $hours > 0 && ! $window_applies ) {
                return __( 'Cancellation window: no cutoff applies to this role.', 'mybookaro' );
            }

            return __( 'Cancellation window: no cutoff is configured.', 'mybookaro' );
        }

        return __( 'Reschedule window: no cutoff is configured.', 'mybookaro' );
    }

    public static function get_status_label( string $status ): string
    {
        $status = self::normalize_status( $status );
        $labels = [
            'pending'   => __( 'Pending approval', 'mybookaro' ),
            'approved'  => __( 'Approved', 'mybookaro' ),
            'rejected'  => __( 'Rejected', 'mybookaro' ),
            'cancelled' => __( 'Cancelled', 'mybookaro' ),
            'completed' => __( 'Completed', 'mybookaro' ),
            'no_show'   => __( 'No-show', 'mybookaro' ),
        ];

        if ( $status === '' ) {
            return '';
        }

        return $labels[ $status ] ?? ucfirst( str_replace( '_', ' ', $status ) );
    }

    public static function format_datetime_label( ?string $datetime ): string
    {
        $datetime = is_string( $datetime ) ? trim( $datetime ) : '';
        if ( $datetime === '' ) {
            return '';
        }

        $date_format = get_option( 'date_format' ) ?: 'Y-m-d';
        $time_format = get_option( 'time_format' ) ?: 'H:i';

        // Booking datetimes are stored as naive site-local strings (the wall-clock
        // slot the customer picked). Interpret them in the site timezone so
        // wp_date() does not shift the displayed time by the GMT offset.
        try {
            $dt = new \DateTimeImmutable( $datetime, wp_timezone() );
        } catch ( \Exception $e ) {
            $timestamp = strtotime( $datetime );
            return $timestamp ? wp_date( $date_format . ' ' . $time_format, $timestamp ) : $datetime;
        }

        return wp_date( $date_format . ' ' . $time_format, $dt->getTimestamp() );
    }

    public static function format_date_range_label( ?string $start, ?string $end ): string
    {
        $start_label = self::format_datetime_label( $start );
        if ( $start_label === '' ) {
            return '';
        }

        $end_label = self::format_datetime_label( $end );
        if ( $end_label === '' ) {
            return $start_label;
        }

        return sprintf(
            /* translators: 1: start label, 2: end label */
            __( '%1$s to %2$s', 'mybookaro' ),
            $start_label,
            $end_label
        );
    }

    public static function format_window_hours_label( int $hours ): string
    {
        $hours = max( 0, $hours );
        if ( $hours === 1 ) {
            return __( '1 hour', 'mybookaro' );
        }

        return sprintf(
            /* translators: %d: window hours */
            __( '%d hours', 'mybookaro' ),
            $hours
        );
    }

    public static function build_booking_status_policy_message( string $status ): string
    {
        $status = self::normalize_status( $status );

        switch ( $status ) {
            case 'pending':
                return __( 'This booking is waiting for provider approval. Cancellation and reschedule requests still follow the configured action windows.', 'mybookaro' );
            case 'approved':
                return __( 'This booking is confirmed. If plans change, use cancel or reschedule before the action window closes.', 'mybookaro' );
            case 'cancelled':
                return __( 'This booking is cancelled. No further schedule changes are available.', 'mybookaro' );
            case 'rejected':
                return __( 'This booking was rejected. No further schedule changes are available.', 'mybookaro' );
            case 'completed':
                return __( 'This booking is completed. Cancel and reschedule are closed.', 'mybookaro' );
            case 'no_show':
                return __( 'This booking is marked as no-show. Cancel and reschedule are closed.', 'mybookaro' );
            default:
                return '';
        }
    }

    public static function build_terminal_action_message( string $status, string $action ): string
    {
        $status = self::normalize_status( $status );
        $action = self::normalize_action( $action );

        if ( $action === 'cancel' ) {
            switch ( $status ) {
                case 'cancelled':
                    return __( 'This booking is already cancelled and cannot be cancelled again.', 'mybookaro' );
                case 'rejected':
                    return __( 'This booking was rejected and cannot be cancelled from here.', 'mybookaro' );
                case 'completed':
                    return __( 'This booking is completed and can no longer be cancelled.', 'mybookaro' );
                case 'no_show':
                    return __( 'This booking is marked as no-show and can no longer be cancelled.', 'mybookaro' );
            }
        }

        switch ( $status ) {
            case 'cancelled':
                return __( 'This booking is already cancelled and can no longer be rescheduled.', 'mybookaro' );
            case 'rejected':
                return __( 'This booking was rejected and can no longer be rescheduled.', 'mybookaro' );
            case 'completed':
                return __( 'This booking is completed and can no longer be rescheduled.', 'mybookaro' );
            case 'no_show':
                return __( 'This booking is marked as no-show and can no longer be rescheduled.', 'mybookaro' );
            default:
                return __( 'This booking can no longer be changed from here.', 'mybookaro' );
        }
    }

    public static function build_payment_policy_behavior_text( string $policy ): string
    {
        $policy = self::normalize_status( $policy );
        if ( $policy === 'pay_later_only' ) {
            return __( 'Payment policy: Pay later. Bookings are created without an online payment at checkout.', 'mybookaro' );
        }
        if ( $policy === 'customer_choice' ) {
            return __( 'Payment policy: Customer choice. Users can choose Pay now for online checkout or Pay later for offline collection.', 'mybookaro' );
        }

        return __( 'Payment policy: Pay now. Users are sent to WooCommerce checkout and the full booking amount is charged online.', 'mybookaro' );
    }

    public static function build_payout_split_behavior_text( string $split_value, bool $payouts_enabled ): string
    {
        if ( $payouts_enabled ) {
            return sprintf(
                /* translators: %s: split setting */
                __( 'Payout split: %s is assigned to website share, and the remainder is provider share. Customer checkout still charges the full booking total.', 'mybookaro' ),
                $split_value
            );
        }

        return sprintf(
            /* translators: %s: split setting */
            __( 'Payout split is configured as %s. It affects payout calculations only and does not reduce customer checkout charges.', 'mybookaro' ),
            $split_value
        );
    }

    /**
     * Legacy compatibility wrapper.
     */
    public static function build_deposit_behavior_text( string $split_value, bool $payouts_enabled ): string
    {
        return self::build_payout_split_behavior_text( $split_value, $payouts_enabled );
    }

    public static function build_cancel_fee_behavior_text( bool $enabled, int $window_hours, string $fee_value ): string
    {
        if ( ! $enabled ) {
            return __( 'Cancellation fee policy: disabled. Automatic cancellation fee/refund logic is not applied; refunds can be handled in WooCommerce when needed.', 'mybookaro' );
        }
        if ( $window_hours <= 0 ) {
            return __( 'Cancellation fee policy is enabled but the fee window is 0 hours, so automatic cancellation fee/refund logic is inactive.', 'mybookaro' );
        }

        return sprintf(
            /* translators: 1: hours, 2: fee value */
            __( 'Cancellation fee policy: if a paid booking is cancelled within %1$d hour(s) before start, %2$s is retained and the remaining paid amount is refunded. Earlier cancellations receive a full refund.', 'mybookaro' ),
            $window_hours,
            $fee_value
        );
    }

    public static function build_no_show_fee_behavior_text( bool $enabled, int $window_minutes, string $fee_value ): string
    {
        if ( ! $enabled ) {
            return __( 'No-show fee policy: disabled. Marking a booking as no-show does not run automatic fee/refund logic.', 'mybookaro' );
        }
        if ( $window_minutes <= 0 ) {
            return __( 'No-show fee policy is enabled but the fee window is 0 minutes, so automatic no-show fee/refund logic is inactive.', 'mybookaro' );
        }

        return sprintf(
            /* translators: 1: minutes, 2: fee value */
            __( 'No-show fee policy: if a paid booking is marked no-show within %1$d minute(s) after start, %2$s is retained and the remaining paid amount is refunded.', 'mybookaro' ),
            $window_minutes,
            $fee_value
        );
    }

    /**
     * Build a normalized policy payload used by frontend, admin hints, and email surfaces.
     *
     * @param array{
     *     cancel_window_hours?: int,
     *     reschedule_window_hours?: int,
     *     cancel_template?: string,
     *     reschedule_template?: string,
     *     cancel_window_applies?: bool,
     *     payment_policy_text?: string,
     *     payout_split_text?: string,
     *     deposit_text?: string,
     *     cancel_fee_text?: string,
     *     no_show_fee_text?: string,
     *     additional_lines?: array<int, string>
     * } $args
     *
     * @return array{
     *     cancel_window_hours: int,
     *     reschedule_window_hours: int,
     *     cancel_template: string,
     *     reschedule_template: string,
     *     cancel_text: string,
     *     reschedule_text: string,
     *     payment_policy_text: string,
     *     payout_split_text: string,
     *     deposit_text: string,
     *     cancel_fee_text: string,
     *     no_show_fee_text: string,
     *     lines: array<int, string>,
     *     combined: string
     * }
     */
    public static function build_policy_bundle( array $args = [] ): array
    {
        $cancel_window_hours = max( 0, (int) ( $args['cancel_window_hours'] ?? 0 ) );
        $reschedule_window_hours = max( 0, (int) ( $args['reschedule_window_hours'] ?? 0 ) );
        $cancel_template = trim( (string) ( $args['cancel_template'] ?? '' ) );
        $reschedule_template = trim( (string) ( $args['reschedule_template'] ?? '' ) );
        $cancel_window_applies = ! array_key_exists( 'cancel_window_applies', $args ) || ! empty( $args['cancel_window_applies'] );

        $cancel_text = self::build_policy_text(
            'cancel',
            $cancel_window_hours,
            $cancel_template,
            $cancel_window_applies
        );
        $reschedule_text = self::build_policy_text(
            'reschedule',
            $reschedule_window_hours,
            $reschedule_template,
            true
        );

        $payment_policy_text = trim( (string) ( $args['payment_policy_text'] ?? '' ) );
        $payout_split_text = trim( (string) ( $args['payout_split_text'] ?? $args['deposit_text'] ?? '' ) );
        $cancel_fee_text = trim( (string) ( $args['cancel_fee_text'] ?? '' ) );
        $no_show_fee_text = trim( (string) ( $args['no_show_fee_text'] ?? '' ) );
        $additional_lines = isset( $args['additional_lines'] ) && is_array( $args['additional_lines'] )
            ? $args['additional_lines']
            : [];

        $lines = self::normalize_policy_lines(
            array_merge(
                [
                    $cancel_text,
                    $reschedule_text,
                    $payment_policy_text,
                    $payout_split_text,
                    $cancel_fee_text,
                    $no_show_fee_text,
                ],
                $additional_lines
            )
        );

        return [
            'cancel_window_hours' => $cancel_window_hours,
            'reschedule_window_hours' => $reschedule_window_hours,
            'cancel_template' => $cancel_template,
            'reschedule_template' => $reschedule_template,
            'cancel_text' => $cancel_text,
            'reschedule_text' => $reschedule_text,
            'payment_policy_text' => $payment_policy_text,
            'payout_split_text' => $payout_split_text,
            'deposit_text' => $payout_split_text,
            'cancel_fee_text' => $cancel_fee_text,
            'no_show_fee_text' => $no_show_fee_text,
            'lines' => $lines,
            'combined' => trim( implode( ' ', $lines ) ),
        ];
    }

    /**
     * @param array<int, mixed> $lines
     * @return array<int, string>
     */
    public static function normalize_policy_lines( array $lines ): array
    {
        $normalized = [];
        foreach ( $lines as $line ) {
            $line = trim( (string) $line );
            if ( $line === '' ) {
                continue;
            }
            if ( in_array( $line, $normalized, true ) ) {
                continue;
            }
            $normalized[] = $line;
        }

        return $normalized;
    }

    public static function get_fee_retained_label( string $status ): string
    {
        $status = self::normalize_status( $status );
        if ( $status === 'no_show' ) {
            return __( 'No-show fee retained', 'mybookaro' );
        }

        return __( 'Cancellation fee retained', 'mybookaro' );
    }

    public static function get_payment_state_label( string $state_key ): string
    {
        $state_key = self::normalize_payment_state_key( $state_key );

        switch ( $state_key ) {
            case 'pay_later':
                return __( 'Pay later', 'mybookaro' );
            case 'cancellation_fee':
                return __( 'Cancellation fee retained', 'mybookaro' );
            case 'no_show_fee':
                return __( 'No-show fee retained', 'mybookaro' );
            case PaymentSplitCompatibility::PAYMENT_STATE_WEBSITE_SHARE_PAID_ONLINE:
                return __( 'Website share paid online', 'mybookaro' );
            case 'fully_paid':
                return __( 'Fully paid', 'mybookaro' );
            case 'refunded':
                return __( 'Refunded', 'mybookaro' );
            case 'blocked':
                return __( 'Payment blocked', 'mybookaro' );
            default:
                return __( 'Unpaid', 'mybookaro' );
        }
    }

    public static function build_fee_outcome_summary_text(
        string $status,
        string $fee_amount_label,
        string $refunded_amount_label = ''
    ): string {
        $status = self::normalize_status( $status );
        $fee_amount_label = trim( $fee_amount_label );
        $refunded_amount_label = trim( $refunded_amount_label );
        $is_no_show = $status === 'no_show';

        if ( $refunded_amount_label !== '' ) {
            return sprintf(
                /* translators: 1: retained fee amount, 2: refunded amount */
                $is_no_show
                    /* translators: %1$s: dynamic string, %2$s: dynamic string */
                    ? __( 'No-show fee retained (%1$s). Remaining amount refunded (%2$s).', 'mybookaro' )
                    /* translators: %1$s: dynamic string, %2$s: dynamic string */
                    : __( 'Cancellation fee retained (%1$s). Remaining amount refunded (%2$s).', 'mybookaro' ),
                $fee_amount_label,
                $refunded_amount_label
            );
        }

        return sprintf(
            /* translators: %s: retained fee amount */
            $is_no_show
                /* translators: %s: dynamic string */
                ? __( 'No-show fee retained (%s). No refund issued.', 'mybookaro' )
                /* translators: %s: dynamic string */
                : __( 'Cancellation fee retained (%s). No refund issued.', 'mybookaro' ),
            $fee_amount_label
        );
    }

    public static function build_terminal_refunded_summary_text( string $status, string $refunded_amount_label ): string
    {
        $status = self::normalize_status( $status );
        $refunded_amount_label = trim( $refunded_amount_label );

        if ( $status === 'no_show' ) {
            return sprintf(
                /* translators: %s: refunded amount */
                __( 'No-show fee did not apply. Full refund issued: %s.', 'mybookaro' ),
                $refunded_amount_label
            );
        }
        if ( $status === 'cancelled' ) {
            return sprintf(
                /* translators: %s: refunded amount */
                __( 'Cancellation fee did not apply. Full refund issued: %s.', 'mybookaro' ),
                $refunded_amount_label
            );
        }

        return sprintf(
            /* translators: %s: refunded amount */
            __( 'Booking closed and refunded: %s.', 'mybookaro' ),
            $refunded_amount_label
        );
    }

    public static function build_payment_state_details( string $state_key, array $context = [] ): string
    {
        $state_key = self::normalize_payment_state_key( $state_key );
        $booking_status = self::normalize_status( (string) ( $context['booking_status'] ?? '' ) );
        $order_status_label = trim( (string) ( $context['order_status_label'] ?? '' ) );
        $fee_amount_label = trim( (string) ( $context['fee_amount_label'] ?? '' ) );
        $refunded_amount_label = trim( (string) ( $context['refunded_amount_label'] ?? '' ) );
        $charge_amount_label = trim( (string) ( $context['charge_amount_label'] ?? '' ) );
        $balance_due_amount_label = trim( (string) ( $context['balance_due_amount_label'] ?? '' ) );
        $full_amount_label = trim( (string) ( $context['full_amount_label'] ?? '' ) );
        $checkout_ready = ! empty( $context['checkout_ready'] );

        switch ( $state_key ) {
            case 'pay_later':
                if ( $balance_due_amount_label !== '' ) {
                    return sprintf(
                        /* translators: %s: amount due later */
                        __( 'No online payment was collected at checkout. Amount due later: %s.', 'mybookaro' ),
                        $balance_due_amount_label
                    );
                }
                return __( 'No online payment was collected at checkout. Collect payment later using your offline process.', 'mybookaro' );

            case 'cancellation_fee':
                if ( $refunded_amount_label !== '' ) {
                    return sprintf(
                        /* translators: 1: fee amount, 2: refunded amount */
                        __( 'Cancellation fee retained: %1$s. Remaining amount refunded: %2$s.', 'mybookaro' ),
                        $fee_amount_label,
                        $refunded_amount_label
                    );
                }
                return sprintf(
                    /* translators: %s: fee amount */
                    __( 'Cancellation fee retained: %s. No refund issued.', 'mybookaro' ),
                    $fee_amount_label
                );

            case 'no_show_fee':
                if ( $refunded_amount_label !== '' ) {
                    return sprintf(
                        /* translators: 1: fee amount, 2: refunded amount */
                        __( 'No-show fee retained: %1$s. Remaining amount refunded: %2$s.', 'mybookaro' ),
                        $fee_amount_label,
                        $refunded_amount_label
                    );
                }
                return sprintf(
                    /* translators: %s: fee amount */
                    __( 'No-show fee retained: %s. No refund issued.', 'mybookaro' ),
                    $fee_amount_label
                );

            case PaymentSplitCompatibility::PAYMENT_STATE_WEBSITE_SHARE_PAID_ONLINE:
                return sprintf(
                    /* translators: 1: website share paid online, 2: split remainder */
                    __( 'Website share paid online: %1$s. Split remainder tracked for payout: %2$s.', 'mybookaro' ),
                    $charge_amount_label,
                    $balance_due_amount_label
                );

            case 'fully_paid':
                return sprintf(
                    /* translators: %s: amount paid online */
                    __( 'The full booking amount has been paid online: %s.', 'mybookaro' ),
                    $charge_amount_label !== '' ? $charge_amount_label : $full_amount_label
                );

            case 'refunded':
                return self::build_terminal_refunded_summary_text( $booking_status, $refunded_amount_label );

            case 'blocked':
                return sprintf(
                    /* translators: %s: order status label */
                    __( 'Order status is %s, so payment is blocked until the order state changes.', 'mybookaro' ),
                    $order_status_label
                );

            default:
                if ( $checkout_ready ) {
                    return __( 'Payment is still due. Use Pay now to complete checkout.', 'mybookaro' );
                }
                return __( 'Payment is still due.', 'mybookaro' );
        }
    }

    public static function build_payment_relationship_text( string $state_key, string $booking_status, array $context = [] ): string
    {
        $state_key = self::normalize_payment_state_key( $state_key );
        $booking_status = self::normalize_status( $booking_status );
        $payment_status = self::normalize_status( (string) ( $context['payment_status'] ?? '' ) );
        $checkout_ready = ! empty( $context['checkout_ready'] );
        $has_order_status = ! empty( $context['has_order_status'] );
        $refunded_amount_label = trim( (string) ( $context['refunded_amount_label'] ?? '' ) );
        $fee_amount_label = trim( (string) ( $context['fee_amount_label'] ?? '' ) );
        $charge_amount_label = trim( (string) ( $context['charge_amount_label'] ?? '' ) );
        $balance_due_amount_label = trim( (string) ( $context['balance_due_amount_label'] ?? '' ) );

        $terminal_statuses = [ 'cancelled', 'rejected', 'no_show' ];
        $is_terminal_booking = in_array( $booking_status, $terminal_statuses, true );
        $is_payment_pending = in_array( $payment_status, [ 'pending', 'unpaid', '' ], true );
        $is_payment_recorded = in_array( $payment_status, [ 'completed', 'processing', 'on-hold' ], true );

        switch ( $state_key ) {
            case 'blocked':
                if ( $is_terminal_booking ) {
                    return __( 'Booking closed before payment was completed.', 'mybookaro' );
                }
                if ( $booking_status === 'approved' ) {
                    return __( 'Booking approved, but payment is blocked by the current order state.', 'mybookaro' );
                }
                return __( 'Payment is blocked by the current order state. Update the WooCommerce order to continue.', 'mybookaro' );

            case 'cancellation_fee':
                return self::build_fee_outcome_summary_text( 'cancelled', $fee_amount_label, $refunded_amount_label );

            case 'no_show_fee':
                return self::build_fee_outcome_summary_text( 'no_show', $fee_amount_label, $refunded_amount_label );

            case 'pay_later':
                if ( $booking_status === 'pending' ) {
                    return sprintf(
                        /* translators: %s: amount due later */
                        __( 'Waiting for provider approval. Payment will be collected later (%s due).', 'mybookaro' ),
                        $balance_due_amount_label
                    );
                }
                if ( $booking_status === 'approved' ) {
                    return sprintf(
                        /* translators: %s: amount due later */
                        __( 'Booking approved. Payment will be collected later (%s due).', 'mybookaro' ),
                        $balance_due_amount_label
                    );
                }
                if ( $booking_status === 'completed' ) {
                    return sprintf(
                        /* translators: %s: amount due later */
                        __( 'Booking completed. Payment is still due (%s).', 'mybookaro' ),
                        $balance_due_amount_label
                    );
                }
                if ( $is_terminal_booking ) {
                    return __( 'Booking closed before payment was completed.', 'mybookaro' );
                }
                break;

            case PaymentSplitCompatibility::PAYMENT_STATE_WEBSITE_SHARE_PAID_ONLINE:
                if ( $booking_status === 'completed' ) {
                    return sprintf(
                        /* translators: 1: website share paid online, 2: split remainder */
                        __( 'Booking completed. Website share paid online: %1$s. Split remainder tracked for payout: %2$s.', 'mybookaro' ),
                        $charge_amount_label,
                        $balance_due_amount_label
                    );
                }
                if ( $booking_status === 'approved' ) {
                    return sprintf(
                        /* translators: 1: website share paid online, 2: split remainder */
                        __( 'Booking approved. Website share paid online: %1$s. Split remainder tracked for payout: %2$s.', 'mybookaro' ),
                        $charge_amount_label,
                        $balance_due_amount_label
                    );
                }
                if ( $booking_status === 'pending' ) {
                    return sprintf(
                        /* translators: 1: website share paid online, 2: split remainder */
                        __( 'Website share paid online: %1$s. Split remainder tracked for payout: %2$s. Waiting for provider approval.', 'mybookaro' ),
                        $charge_amount_label,
                        $balance_due_amount_label
                    );
                }
                if ( $is_terminal_booking ) {
                    return __( 'Booking closed after payment. Review the refund or fee policy if needed.', 'mybookaro' );
                }
                break;

            case 'fully_paid':
                if ( $booking_status === 'pending' ) {
                    return sprintf(
                        /* translators: %s: amount paid online */
                        __( 'Fully paid online: %s. Waiting for provider approval.', 'mybookaro' ),
                        $charge_amount_label
                    );
                }
                if ( $booking_status === 'approved' ) {
                    return sprintf(
                        /* translators: %s: amount paid online */
                        __( 'Booking approved and fully paid online: %s.', 'mybookaro' ),
                        $charge_amount_label
                    );
                }
                if ( $booking_status === 'completed' ) {
                    return sprintf(
                        /* translators: %s: amount paid online */
                        __( 'Booking completed and fully paid online: %s.', 'mybookaro' ),
                        $charge_amount_label
                    );
                }
                if ( $is_terminal_booking ) {
                    return __( 'Booking closed after payment. Review the refund or fee policy if needed.', 'mybookaro' );
                }
                break;

            case 'refunded':
                return self::build_terminal_refunded_summary_text( $booking_status, $refunded_amount_label );
        }

        if ( $is_payment_pending ) {
            if ( $checkout_ready ) {
                return __( 'Checkout is ready. Use Pay now to complete checkout.', 'mybookaro' );
            }
            if ( $has_order_status ) {
                return __( 'Payment is still due, but checkout is not available for this order right now.', 'mybookaro' );
            }
        }

        if ( $booking_status === 'pending' ) {
            if ( $is_payment_pending ) {
                return __( 'Waiting for provider approval. Payment is still due.', 'mybookaro' );
            }
            if ( $is_payment_recorded ) {
                return __( 'Fully paid. Waiting for provider approval.', 'mybookaro' );
            }
        }

        if ( $booking_status === 'approved' ) {
            if ( $is_payment_pending ) {
                return __( 'Booking approved. Payment is still due.', 'mybookaro' );
            }
            if ( $is_payment_recorded ) {
                return __( 'Booking approved and fully paid.', 'mybookaro' );
            }
        }

        if ( $booking_status === 'completed' ) {
            if ( $is_payment_recorded ) {
                return __( 'Booking completed and fully paid.', 'mybookaro' );
            }
            if ( $payment_status === 'refunded' ) {
                return __( 'Booking completed and refunded.', 'mybookaro' );
            }
            if ( $is_payment_pending || $payment_status === 'pay_later' ) {
                return __( 'Booking completed. Payment is still due.', 'mybookaro' );
            }
        }

        if ( $booking_status === 'no_show' && $payment_status === 'refunded' ) {
            return __( 'No-show fee did not apply. Full refund issued.', 'mybookaro' );
        }

        if ( $is_terminal_booking ) {
            if ( $payment_status === 'refunded' ) {
                return __( 'Booking closed and refunded.', 'mybookaro' );
            }
            if ( $payment_status === 'cancelled' ) {
                return __( 'Booking closed and payment was cancelled.', 'mybookaro' );
            }
            if ( $is_payment_recorded ) {
                return __( 'Booking closed after payment. Review the refund or fee policy if needed.', 'mybookaro' );
            }
            if ( $is_payment_pending || $payment_status === 'pay_later' || $payment_status === 'failed' ) {
                return __( 'Booking closed before payment was completed.', 'mybookaro' );
            }
        }

        return '';
    }

    public static function build_fee_refund_reason( string $status, bool $fee_applied ): string
    {
        $status = self::normalize_status( $status );
        if ( $fee_applied ) {
            return $status === 'no_show'
                ? __( 'Booking marked as no-show. Refund processed using MyBookaro no-show fee policy.', 'mybookaro' )
                : __( 'Booking cancelled. Refund processed using MyBookaro cancellation fee policy.', 'mybookaro' );
        }

        return $status === 'no_show'
            ? __( 'Booking marked as no-show outside the configured fee window. Full refund applied.', 'mybookaro' )
            : __( 'Booking cancelled outside the configured fee window. Full refund applied.', 'mybookaro' );
    }

    public static function build_no_online_refund_note( string $status, string $payment_mode, bool $order_is_paid ): string
    {
        $status = self::normalize_status( $status );
        $payment_mode = self::normalize_status( $payment_mode );

        if ( $payment_mode === 'pay_later' ) {
            return $status === 'no_show'
                ? __( 'Payment state: Pay later. Booking was marked as no-show. Online collected: 0. No WooCommerce refund is needed.', 'mybookaro' )
                : __( 'Payment state: Pay later. Booking was cancelled. Online collected: 0. No WooCommerce refund is needed.', 'mybookaro' );
        }

        if ( $order_is_paid ) {
            return $status === 'no_show'
                ? __( 'Booking was marked as no-show, but no refundable online balance remains on this order (already refunded or retained by policy).', 'mybookaro' )
                : __( 'Booking was cancelled, but no refundable online balance remains on this order (already refunded or retained by policy).', 'mybookaro' );
        }

        return $status === 'no_show'
            ? __( 'Payment state: Unpaid. Booking was marked as no-show before checkout completed. No WooCommerce refund is needed.', 'mybookaro' )
            : __( 'Payment state: Unpaid. Booking was cancelled before checkout completed. No WooCommerce refund is needed.', 'mybookaro' );
    }

    public static function build_manual_refund_required_note( string $status = 'cancelled' ): string
    {
        $status = self::normalize_status( $status );

        if ( $status === 'no_show' ) {
            return __( 'Booking was marked as no-show after online payment. Automatic no-show fee/refund logic is not active for this flow. Open this WooCommerce order and create the refund manually if needed.', 'mybookaro' );
        }

        return __( 'Booking was cancelled after online payment. Automatic cancellation fee/refund logic is not active for this flow. Open this WooCommerce order and create the refund manually if needed.', 'mybookaro' );
    }

    public static function normalize_action( string $action ): string
    {
        $action = strtolower( trim( $action ) );
        if ( $action === 'cancelled' || $action === 'cancel' ) {
            return 'cancel';
        }
        if ( $action === 'rescheduled' || $action === 'reschedule' ) {
            return 'reschedule';
        }

        return $action;
    }

    public static function normalize_status( string $status ): string
    {
        return strtolower( trim( $status ) );
    }

    private static function normalize_payment_state_key( string $state_key ): string
    {
        return PaymentSplitCompatibility::normalize_payment_state_key( self::normalize_status( $state_key ) );
    }
}
