<?php
/**
 * REST API for staff order boards (waiter / kitchen).
 *
 * @package Maca_Menu_List
 */

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

add_action('rest_api_init', 'maca_menulist_register_staff_rest_routes');

/**
 * Register staff board REST routes.
 *
 * @return void
 */
function maca_menulist_register_staff_rest_routes() {
    register_rest_route(
        'maca-menulist/v1',
        '/staff',
        array(
            'methods'             => 'POST',
            'callback'            => 'maca_menulist_rest_staff_handler',
            'permission_callback' => '__return_true',
        )
    );
}

/**
 * Copy REST request params into $_POST for shared staff handlers.
 *
 * @param WP_REST_Request $request Request.
 * @return void
 */
function maca_menulist_rest_staff_merge_request_params(WP_REST_Request $request) {
    foreach ($request->get_params() as $key => $value) {
        if (!is_scalar($value)) {
            continue;
        }

        $_POST[$key] = wp_unslash((string) $value);
    }
}

/**
 * Build a REST response in the same shape as admin-ajax handlers.
 *
 * @param array<string, mixed> $result Dispatch result.
 * @return WP_REST_Response
 */
function maca_menulist_rest_staff_response(array $result) {
    $success = !empty($result['success']);
    $status = isset($result['status']) ? (int) $result['status'] : ($success ? 200 : 403);

    return new WP_REST_Response(
        array(
            'success' => $success,
            'data'    => isset($result['data']) && is_array($result['data']) ? $result['data'] : array(),
        ),
        $status
    );
}

/**
 * Dispatch a staff API action and return a structured result.
 *
 * @param string $action Staff action name.
 * @return array<string, mixed>
 */
function maca_menulist_staff_api_dispatch($action) {
    if (function_exists('maca_menulist_mark_staff_api_request')) {
        maca_menulist_mark_staff_api_request();
    }

    $action = sanitize_key($action);

    $pin_result = maca_menulist_validate_staff_pin_from_request();
    if (empty($pin_result['success'])) {
        return $pin_result;
    }

    switch ($action) {
        case 'maca_verify_staff_pin':
            return maca_menulist_staff_api_verify_pin();
        case 'maca_get_staff_table_summary':
            return maca_menulist_staff_api_get_table_summary();
        case 'maca_get_staff_orders':
            return maca_menulist_staff_api_get_orders();
        case 'maca_update_staff_order_table':
            return maca_menulist_staff_api_update_order_table();
        case 'maca_handle_staff_order':
            return maca_menulist_staff_api_handle_order();
        default:
            return array(
                'success' => false,
                'status'  => 400,
                'data'    => array(
                    'message' => __('Unknown staff action.', 'maca-restu-pro'),
                ),
            );
    }
}

/**
 * Fast PIN check for staff unlock (no order payload).
 *
 * @return array<string, mixed>
 */
function maca_menulist_staff_api_verify_pin() {
    $view = isset($_POST['view']) ? sanitize_key(wp_unslash($_POST['view'])) : 'waiter';

    return array(
        'success' => true,
        'status'  => 200,
        'data'    => array_merge(
            maca_menulist_get_staff_pin_attempt_feedback(),
            array(
                'verified'      => true,
                'staff_session' => function_exists('maca_menulist_create_staff_session')
                    ? maca_menulist_create_staff_session($view)
                    : '',
            )
        ),
    );
}

/**
 * Staff table overview for waiter drill-down UI.
 *
 * @return array<string, mixed>
 */
function maca_menulist_staff_api_get_table_summary() {
    $view = isset($_POST['view']) ? sanitize_key(wp_unslash($_POST['view'])) : 'waiter';

    if ($view !== 'waiter') {
        return array(
            'success' => false,
            'status'  => 400,
            'data'    => array('message' => __('Table overview is only available on the waiter screen.', 'maca-restu-pro')),
        );
    }

    $block_reason = maca_menulist_get_staff_order_pages_block_reason();
    if ($block_reason !== '') {
        return array(
            'success' => false,
            'status'  => 403,
            'data'    => array('message' => $block_reason),
        );
    }

    if (!maca_menulist_table_order_waiter_page_enabled()) {
        return array(
            'success' => false,
            'status'  => 403,
            'data'    => array('message' => __('Waiter page is disabled.', 'maca-restu-pro')),
        );
    }

    $filter = maca_menulist_parse_staff_order_filter_from_request();
    $orders = maca_menulist_db_get_staff_order_summary_rows('waiter');

    if ($filter['scope'] === 'waiter') {
        $orders = maca_menulist_filter_orders_for_staff_scope($orders, $filter['scope'], $filter['waiter_id']);
    }
    if (function_exists('maca_menulist_filter_orders_for_staff_boards')) {
        $orders = maca_menulist_filter_orders_for_staff_boards($orders, 'waiter');
    }

    return array(
        'success' => true,
        'status'  => 200,
        'data'    => array(
            'tables' => maca_menulist_build_staff_table_summary($orders),
        ),
    );
}

/**
 * Staff orders payload for polling.
 *
 * @return array<string, mixed>
 */
function maca_menulist_staff_api_get_orders() {
    $view = isset($_POST['view']) ? sanitize_key(wp_unslash($_POST['view'])) : 'waiter';

    $block_reason = maca_menulist_get_staff_order_pages_block_reason();
    if ($block_reason !== '') {
        return array(
            'success' => false,
            'status'  => 403,
            'data'    => array('message' => $block_reason),
        );
    }

    if ($view === 'kitchen' && !maca_menulist_table_order_kitchen_page_enabled()) {
        return array(
            'success' => false,
            'status'  => 403,
            'data'    => array('message' => __('Kitchen page is disabled.', 'maca-restu-pro')),
        );
    }

    if ($view === 'waiter' && !maca_menulist_table_order_waiter_page_enabled()) {
        return array(
            'success' => false,
            'status'  => 403,
            'data'    => array('message' => __('Waiter page is disabled.', 'maca-restu-pro')),
        );
    }

    $filter = maca_menulist_parse_staff_order_filter_from_request();
    $table_filter = maca_menulist_parse_staff_table_filter_from_request();
    $table_scope_active = $view === 'waiter' && maca_menulist_staff_table_filter_is_active($table_filter);

    if ($view === 'waiter' && !$table_scope_active) {
        return array(
            'success' => true,
            'status'  => 200,
            'data'    => array('orders' => array()),
        );
    }

    $orders = maca_menulist_db_get_table_orders(
        $view,
        false,
        $table_scope_active ? $table_filter : null
    );
    if ($view === 'waiter') {
        $orders = maca_menulist_filter_orders_for_staff_scope($orders, $filter['scope'], $filter['waiter_id']);
    }
    if (!$table_scope_active && function_exists('maca_menulist_filter_orders_for_staff_boards')) {
        $orders = maca_menulist_filter_orders_for_staff_boards($orders, $view);
    }

    $use_poll_format = $table_scope_active && $view === 'waiter';
    $payload = array();
    foreach ($orders as $order) {
        try {
            if ($use_poll_format && function_exists('maca_menulist_format_table_order_staff_poll')) {
                $payload[] = maca_menulist_format_table_order_staff_poll($order, $view);
            } else {
                $payload[] = maca_menulist_format_table_order_for_json($order, $view, true);
            }
        } catch (Throwable $format_error) {
            if (function_exists('maca_menulist_debug_log')) {
                maca_menulist_debug_log(
                    'staff order json error order ' . (int) ($order->id ?? 0) . ': ' . $format_error->getMessage()
                );
            }
        }
    }

    $response = array(
        'orders' => $payload,
    );

    if ($view === 'kitchen') {
        $response['stats'] = array(
            'orders_today' => maca_menulist_db_count_table_orders_today(),
        );
    }

    return array(
        'success' => true,
        'status'  => 200,
        'data'    => $response,
    );
}

/**
 * Mark an order as handled.
 *
 * @return array<string, mixed>
 */
function maca_menulist_staff_api_handle_order() {
    $order_id = isset($_POST['order_id']) ? intval($_POST['order_id']) : 0;

    if ($order_id <= 0 || !maca_menulist_db_handle_table_order($order_id)) {
        return array(
            'success' => false,
            'status'  => 400,
            'data'    => array('message' => __('Could not update order.', 'maca-restu-pro')),
        );
    }

    return array(
        'success' => true,
        'status'  => 200,
        'data'    => array('order_id' => $order_id),
    );
}

/**
 * Update staff order table number.
 *
 * @return array<string, mixed>
 */
function maca_menulist_staff_api_update_order_table() {
    $order_id = isset($_POST['order_id']) ? intval($_POST['order_id']) : 0;
    $table_number = isset($_POST['table_number']) ? sanitize_text_field(wp_unslash($_POST['table_number'])) : '';

    if ($order_id <= 0) {
        return array(
            'success' => false,
            'status'  => 400,
            'data'    => array('message' => __('Could not update table number.', 'maca-restu-pro')),
        );
    }

    $order_row = maca_menulist_db_get_table_order($order_id);
    if (!$order_row) {
        return array(
            'success' => false,
            'status'  => 404,
            'data'    => array('message' => __('Order not found.', 'maca-restu-pro')),
        );
    }

    if (!maca_menulist_staff_can_change_order_table($order_row)) {
        $message = (
            function_exists('maca_menulist_order_is_payment_complete')
            && maca_menulist_order_is_payment_complete($order_row)
        )
            ? __('Table number cannot be changed after payment.', 'maca-restu-pro')
            : __('This order cannot be moved to another table.', 'maca-restu-pro');

        return array(
            'success' => false,
            'status'  => 403,
            'data'    => array('message' => $message),
        );
    }

    if (!maca_menulist_is_allowed_guest_order_table_number($table_number, (string) $order_row->table_number)) {
        return array(
            'success' => false,
            'status'  => 400,
            'data'    => array('message' => __('Invalid table number.', 'maca-restu-pro')),
        );
    }

    $new_table = trim($table_number);
    $current_table = trim((string) $order_row->table_number);

    if ($new_table === $current_table) {
        return array(
            'success' => true,
            'status'  => 200,
            'data'    => array(
                'order_id'     => $order_id,
                'table_number' => $new_table,
            ),
        );
    }

    if (!maca_menulist_db_update_table_order_table_number($order_id, $new_table)) {
        return array(
            'success' => false,
            'status'  => 400,
            'data'    => array('message' => __('Could not update table number.', 'maca-restu-pro')),
        );
    }

    return array(
        'success' => true,
        'status'  => 200,
        'data'    => array(
            'order_id'     => $order_id,
            'table_number' => $new_table,
        ),
    );
}

/**
 * REST callback for staff board actions.
 *
 * @param WP_REST_Request $request Request.
 * @return WP_REST_Response
 */
function maca_menulist_rest_staff_handler(WP_REST_Request $request) {
    maca_menulist_rest_staff_merge_request_params($request);

    $action = maca_menulist_get_staff_action_from_request();
    if ($action === '') {
        return maca_menulist_rest_staff_response(
            array(
                'success' => false,
                'status'  => 400,
                'data'    => array(
                    'message' => __('Missing staff action.', 'maca-restu-pro'),
                ),
            )
        );
    }

    return maca_menulist_rest_staff_response(maca_menulist_staff_api_dispatch($action));
}

add_action('init', 'maca_menulist_maybe_mark_staff_api_request', 6);
add_action('plugins_loaded', 'maca_menulist_maybe_early_dispatch_staff_post', 2);
add_action('init', 'maca_menulist_maybe_early_dispatch_staff_post', 0);

/**
 * Mark staff API requests early so guest gettext filters stay off.
 *
 * @return void
 */
function maca_menulist_maybe_mark_staff_api_request() {
    if (!function_exists('maca_menulist_is_staff_api_request')
        || !function_exists('maca_menulist_mark_staff_api_request')) {
        return;
    }

    if (maca_menulist_is_staff_api_request()) {
        maca_menulist_mark_staff_api_request();
    }
}

/**
 * Whether the current POST should be handled by the lightweight staff API exit.
 *
 * @return bool
 */
function maca_menulist_should_early_dispatch_staff_post() {
    if (strtoupper((string) ($_SERVER['REQUEST_METHOD'] ?? 'GET')) !== 'POST') {
        return false;
    }

    if (defined('DOING_AJAX') && DOING_AJAX) {
        return false;
    }

    if (defined('REST_REQUEST') && REST_REQUEST) {
        return false;
    }

    if (!function_exists('maca_menulist_get_staff_action_from_request')
        || !function_exists('maca_menulist_get_staff_api_actions')) {
        return false;
    }

    $action = maca_menulist_get_staff_action_from_request();
    if ($action === '' || !in_array($action, maca_menulist_get_staff_api_actions(), true)) {
        return false;
    }

    if ($action === 'maca_update_staff_order_status') {
        return false;
    }

    if (function_exists('maca_menulist_is_staff_orders_request') && maca_menulist_is_staff_orders_request()) {
        return true;
    }

    return function_exists('maca_menulist_bootstrap_staff_request_query_vars')
        && maca_menulist_bootstrap_staff_request_query_vars();
}

/**
 * Answer staff board POST on plugins_loaded to avoid theme bootstrap / gettext recursion.
 *
 * @return void
 */
function maca_menulist_maybe_early_dispatch_staff_post() {
    static $handled = false;

    if ($handled || !maca_menulist_should_early_dispatch_staff_post()) {
        return;
    }

    $handled = true;

    if (function_exists('maca_menulist_mark_staff_api_request')) {
        maca_menulist_mark_staff_api_request();
    }

    try {
        $action = maca_menulist_get_staff_action_from_request();
        $result = maca_menulist_staff_api_dispatch($action);

        if (function_exists('nocache_headers')) {
            nocache_headers();
        }

        if (empty($result['success'])) {
            wp_send_json_error($result['data'], $result['status'] ?? 403);
        }

        wp_send_json_success($result['data']);
    } catch (Throwable $dispatch_error) {
        if (function_exists('maca_menulist_debug_log')) {
            maca_menulist_debug_log(
                'staff early dispatch error: ' . $dispatch_error->getMessage() . ' @ ' . $dispatch_error->getFile() . ':' . $dispatch_error->getLine()
            );
        }

        if (function_exists('nocache_headers')) {
            nocache_headers();
        }

        wp_send_json_error(
            array(
                'message' => __('Could not load staff orders. Reload the page and try again.', 'maca-restu-pro'),
            ),
            500
        );
    }
}
