<?php
/**
 * Tips and staff payment visibility settings.
 *
 * @package Maca_Menu_List
 */

if (!defined('ABSPATH')) {
    exit;
}

/**
 * Whether tips are enabled for guest orders.
 *
 * @return bool
 */
function maca_menulist_tips_enabled() {
    if (!maca_menulist_payments_guest_flow_enabled()) {
        return false;
    }

    return get_option('maca_menulist_tips_enabled', '0') === '1';
}

/**
 * Tip preset mode: percent or fixed amounts.
 *
 * @return string percent|fixed
 */
function maca_menulist_tips_mode() {
    $mode = sanitize_key((string) get_option('maca_menulist_tips_mode', 'percent'));

    return in_array($mode, array('percent', 'fixed'), true) ? $mode : 'percent';
}

/**
 * Whether guests may enter a custom tip amount.
 *
 * @return bool
 */
function maca_menulist_tips_allow_custom() {
    return get_option('maca_menulist_tips_allow_custom', '1') === '1';
}

/**
 * Whether "no tip" is offered in presets.
 *
 * @return bool
 */
function maca_menulist_tips_allow_none() {
    return get_option('maca_menulist_tips_allow_none', '1') === '1';
}

/**
 * Parsed tip preset values from settings.
 *
 * @return array<int, float>
 */
function maca_menulist_tips_get_preset_values() {
    $default = maca_menulist_tips_mode() === 'fixed' ? '0,20,50,100' : '0,5,10,15';
    $raw = (string) get_option('maca_menulist_tips_presets', $default);
    $parts = preg_split('/[\s,;]+/', $raw, -1, PREG_SPLIT_NO_EMPTY);
    $values = array();

    foreach ($parts as $part) {
        $value = (float) str_replace(',', '.', $part);
        if ($value < 0) {
            continue;
        }
        if (maca_menulist_tips_mode() === 'percent' && $value > 100) {
            $value = 100;
        }
        $values[] = round($value, 2);
    }

    if (empty($values)) {
        $values = maca_menulist_tips_mode() === 'fixed' ? array(0.0, 20.0, 50.0, 100.0) : array(0.0, 5.0, 10.0, 15.0);
    }

    if (maca_menulist_tips_allow_none() && !in_array(0.0, $values, true)) {
        array_unshift($values, 0.0);
    } elseif (!maca_menulist_tips_allow_none()) {
        $values = array_values(array_filter(
            $values,
            static function ($value) {
                return (float) $value > 0;
            }
        ));
    }

    $values = array_values(array_unique($values));
    sort($values, SORT_NUMERIC);

    return $values;
}

/**
 * Who sees payment details on staff boards: waiter, kitchen, or both.
 *
 * @return string waiter|kitchen|both
 */
function maca_menulist_staff_payment_visibility() {
    $value = sanitize_key((string) get_option('maca_menulist_staff_payment_visibility', 'waiter'));

    if (!in_array($value, array('waiter', 'kitchen', 'both'), true)) {
        return 'waiter';
    }

    return $value;
}

/**
 * Whether a staff view should include payment details.
 *
 * @param string $view waiter|kitchen.
 * @return bool
 */
function maca_menulist_staff_shows_payment_info($view) {
    if (!maca_menulist_payments_guest_flow_enabled()) {
        return false;
    }

    $view = sanitize_key($view);
    $visibility = maca_menulist_staff_payment_visibility();

    if ($visibility === 'both') {
        return true;
    }

    return $visibility === $view;
}

/**
 * Tip amount stored on an order row.
 *
 * @param object $order Order row.
 * @return float
 */
function maca_menulist_get_order_tip_amount($order) {
    if (!isset($order->tip_amount) || $order->tip_amount === '' || $order->tip_amount === null) {
        return 0.0;
    }

    return max(0.0, round((float) $order->tip_amount, 2));
}

/**
 * Food subtotal for an order with lines.
 *
 * @param object $order Order with lines.
 * @return float
 */
function maca_menulist_get_order_subtotal($order) {
    return maca_menulist_calculate_table_order_total($order);
}

/**
 * Subtotal + tip.
 *
 * @param object $order Order with lines.
 * @return float
 */
function maca_menulist_order_payment_total($order) {
    return round(maca_menulist_get_order_subtotal($order) + maca_menulist_get_order_tip_amount($order), 2);
}

/**
 * Maximum allowed custom tip (SEK or order currency).
 *
 * @param float $subtotal Order subtotal.
 * @return float
 */
function maca_menulist_tips_max_custom_amount($subtotal) {
    $subtotal = max(0.0, (float) $subtotal);
    $cap = (float) apply_filters('maca_menulist_tips_max_custom_amount', max(500.0, $subtotal * 2), $subtotal);

    return max(0.0, $cap);
}

/**
 * Sanitize tip amount for an order.
 *
 * @param float $amount   Requested tip.
 * @param float $subtotal Order subtotal.
 * @return float
 */
function maca_menulist_sanitize_tip_amount($amount, $subtotal) {
    $amount = max(0.0, round((float) $amount, 2));
    $max = maca_menulist_tips_max_custom_amount($subtotal);

    return min($amount, $max);
}

/**
 * Compute tip from a preset value.
 *
 * @param float  $subtotal Order subtotal.
 * @param string $mode     percent|fixed.
 * @param float  $value    Preset value.
 * @return float
 */
function maca_menulist_calculate_tip_from_preset($subtotal, $mode, $value) {
    $subtotal = max(0.0, (float) $subtotal);
    $value = max(0.0, (float) $value);

    if ($mode === 'percent') {
        return maca_menulist_sanitize_tip_amount($subtotal * ($value / 100), $subtotal);
    }

    return maca_menulist_sanitize_tip_amount($value, $subtotal);
}

/**
 * Guest tip choices for JSON / UI.
 *
 * @param object $order Order with lines.
 * @return array<int, array<string, mixed>>
 */
function maca_menulist_get_guest_tip_choices($order) {
    if (!maca_menulist_tips_enabled()) {
        return array();
    }

    $subtotal = maca_menulist_get_order_subtotal($order);
    if ($subtotal <= 0) {
        return array();
    }

    $mode = maca_menulist_tips_mode();
    $choices = array();

    foreach (maca_menulist_tips_get_preset_values() as $value) {
        $amount = maca_menulist_calculate_tip_from_preset($subtotal, $mode, $value);
        $id = $mode . '_' . str_replace('.', '_', (string) $value);

        if ($mode === 'percent') {
            $label = $value <= 0
                ? __('No tip', 'maca-restu-pro')
                : sprintf(
                    /* translators: %s: percent value */
                    __('%s%%', 'maca-restu-pro'),
                    rtrim(rtrim(number_format_i18n($value, 2), '0'), ',.')
                );
        } else {
            $label = $value <= 0
                ? __('No tip', 'maca-restu-pro')
                : maca_menulist_format_price($value);
        }

        $choices[] = array(
            'id' => $id,
            'preset' => $value,
            'amount' => $amount,
            'label' => $label,
            'amount_label' => $amount > 0 ? maca_menulist_format_price($amount) : '',
        );
    }

    if (maca_menulist_tips_allow_custom()) {
        $choices[] = array(
            'id' => 'custom',
            'preset' => null,
            'amount' => null,
            'label' => __('Custom amount', 'maca-restu-pro'),
            'amount_label' => '',
            'is_custom' => true,
        );
    }

    return $choices;
}

/**
 * Save tip amount on an order.
 *
 * @param int   $order_id Order ID.
 * @param float $amount   Tip amount.
 * @return true|WP_Error
 */
function maca_menulist_db_set_order_tip_amount($order_id, $amount) {
    global $wpdb;

    maca_menulist_db_ensure_table_order_tables();

    $order_id = absint($order_id);
    $order = maca_menulist_db_get_table_order($order_id);

    if (!$order) {
        return new WP_Error('not_found', __('Order not found.', 'maca-restu-pro'));
    }

    $orders = maca_menulist_db_attach_table_order_lines(array($order));
    $order = $orders[0];

    if (maca_menulist_order_is_payment_complete($order)) {
        return new WP_Error('paid', __('This order is already paid.', 'maca-restu-pro'));
    }
    $subtotal = maca_menulist_get_order_subtotal($order);
    $amount = maca_menulist_sanitize_tip_amount($amount, $subtotal);

    if (!maca_menulist_tips_enabled()) {
        $amount = 0.0;
    }

    $updated = $wpdb->update(
        maca_menulist_db_table_orders_table(),
        array(
            'tip_amount' => $amount,
            'tip_confirmed' => 1,
        ),
        array('id' => $order_id),
        array('%f', '%d'),
        array('%d')
    );

    if ($updated === false) {
        return new WP_Error('db', __('Could not save tip.', 'maca-restu-pro'));
    }

    return true;
}

/**
 * Resolve tip from AJAX payload (amount or preset id).
 *
 * @param object $order Order with lines.
 * @return float|WP_Error
 */
function maca_menulist_resolve_tip_from_request($order) {
    return maca_menulist_resolve_tip_from_request_for_subtotal(maca_menulist_get_order_subtotal($order));
}

/**
 * Resolve tip from AJAX payload using an explicit subtotal.
 *
 * @param float $subtotal Order subtotal used for tip presets.
 * @return float|WP_Error
 */
function maca_menulist_resolve_tip_from_request_for_subtotal($subtotal) {
    $subtotal = max(0.0, (float) $subtotal);

    if (isset($_POST['tip_amount'])) {
        return maca_menulist_sanitize_tip_amount((float) wp_unslash($_POST['tip_amount']), $subtotal);
    }

    $choice = isset($_POST['tip_choice']) ? sanitize_key(wp_unslash($_POST['tip_choice'])) : '';

    if ($choice === 'none' || $choice === '') {
        return maca_menulist_tips_allow_none() ? 0.0 : new WP_Error('tip_required', __('Please choose a tip option.', 'maca-restu-pro'));
    }

    if ($choice === 'custom') {
        if (!maca_menulist_tips_allow_custom()) {
            return new WP_Error('tip_invalid', __('Custom tip is not allowed.', 'maca-restu-pro'));
        }
        if (!isset($_POST['tip_custom_amount'])) {
            return new WP_Error('tip_required', __('Enter a tip amount.', 'maca-restu-pro'));
        }

        return maca_menulist_sanitize_tip_amount((float) wp_unslash($_POST['tip_custom_amount']), $subtotal);
    }

    $mode = maca_menulist_tips_mode();
    if (preg_match('/^(percent|fixed)_([0-9]+(?:_[0-9]+)?)$/', $choice, $matches)) {
        $preset_mode = $matches[1];
        $preset_value = (float) str_replace('_', '.', $matches[2]);

        if ($preset_mode !== $mode) {
            return new WP_Error('tip_invalid', __('Invalid tip choice.', 'maca-restu-pro'));
        }

        return maca_menulist_calculate_tip_from_preset($subtotal, $mode, $preset_value);
    }

    foreach (maca_menulist_tips_get_preset_values() as $value) {
        $id = $mode . '_' . str_replace('.', '_', (string) $value);
        if ($choice === $id) {
            return maca_menulist_calculate_tip_from_preset($subtotal, $mode, $value);
        }
    }

    return new WP_Error('tip_invalid', __('Invalid tip choice.', 'maca-restu-pro'));
}
