<?php
namespace Bookaro\Controller\Rest;

defined( 'ABSPATH' ) || exit;

// phpcs:disable WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- meta_query resolves a provider's services and is bounded by provider/listing; results feed a paginated REST response.

use WP_REST_Request;
use WP_REST_Response;
use WP_REST_Server;
use WP_Error;

class ProviderServicesController extends BaseController
{
    public function register_routes(): void
    {
        register_rest_route( $this->namespace, '/provider/listings', [
            [
                'methods'             => WP_REST_Server::READABLE,
                'callback'            => [ $this, 'get_listings' ],
                'permission_callback' => [ $this, 'can_manage_services' ],
            ],
        ] );

        register_rest_route( $this->namespace, '/provider/services', [
            [
                'methods'             => WP_REST_Server::READABLE,
                'callback'            => [ $this, 'get_services' ],
                'permission_callback' => [ $this, 'can_manage_services' ],
                'args'                => [
                    'listing_id' => [ 'type' => 'integer', 'required' => true ],
                ],
            ],
            [
                'methods'             => WP_REST_Server::CREATABLE,
                'callback'            => [ $this, 'create_service' ],
                'permission_callback' => [ $this, 'can_manage_services_write' ],
                'args'                => [
                    'listing_id'  => [ 'type' => 'integer', 'required' => true ],
                    'title'       => [ 'type' => 'string', 'required' => true ],
                    'description' => [ 'type' => 'string', 'required' => false, 'default' => '' ],
                    'price'       => [ 'type' => 'number', 'required' => false, 'default' => 0 ],
                    'duration'    => [ 'type' => 'integer', 'required' => false, 'default' => 0 ],
                ],
            ],
        ] );

        register_rest_route( $this->namespace, '/provider/services/(?P<id>\\d+)', [
            [
                'methods'             => WP_REST_Server::EDITABLE,
                'callback'            => [ $this, 'update_service' ],
                'permission_callback' => [ $this, 'can_manage_services_write' ],
                'args'                => [
                    'title'       => [ 'type' => 'string', 'required' => false ],
                    'description' => [ 'type' => 'string', 'required' => false ],
                    'price'       => [ 'type' => 'number', 'required' => false ],
                    'duration'    => [ 'type' => 'integer', 'required' => false ],
                    'listing_id'  => [ 'type' => 'integer', 'required' => false ],
                ],
            ],
            [
                'methods'             => WP_REST_Server::DELETABLE,
                'callback'            => [ $this, 'delete_service' ],
                'permission_callback' => [ $this, 'can_manage_services_write' ],
            ],
        ] );

        register_rest_route( $this->namespace, '/provider/services/provider', [
            [
                'methods'             => WP_REST_Server::READABLE,
                'callback'            => [ $this, 'get_provider_scoped_services' ],
                'permission_callback' => [ $this, 'can_manage_services' ],
            ],
            [
                'methods'             => WP_REST_Server::CREATABLE,
                'callback'            => [ $this, 'create_provider_scoped_service' ],
                'permission_callback' => [ $this, 'can_manage_services_write' ],
                'args'                => [
                    'title'       => [ 'type' => 'string', 'required' => true ],
                    'description' => [ 'type' => 'string', 'required' => false, 'default' => '' ],
                    'price'       => [ 'type' => 'number', 'required' => false, 'default' => 0 ],
                    'duration'    => [ 'type' => 'integer', 'required' => false, 'default' => 0 ],
                    'listing_id'  => [ 'type' => 'integer', 'required' => false, 'default' => 0 ],
                ],
            ],
        ] );

        register_rest_route( $this->namespace, '/provider/services/provider/(?P<id>\\d+)', [
            [
                'methods'             => WP_REST_Server::EDITABLE,
                'callback'            => [ $this, 'update_provider_scoped_service' ],
                'permission_callback' => [ $this, 'can_manage_services_write' ],
                'args'                => [
                    'title'       => [ 'type' => 'string', 'required' => false ],
                    'description' => [ 'type' => 'string', 'required' => false ],
                    'price'       => [ 'type' => 'number', 'required' => false ],
                    'duration'    => [ 'type' => 'integer', 'required' => false ],
                    'listing_id'  => [ 'type' => 'integer', 'required' => false ],
                ],
            ],
            [
                'methods'             => WP_REST_Server::DELETABLE,
                'callback'            => [ $this, 'delete_provider_scoped_service' ],
                'permission_callback' => [ $this, 'can_manage_services_write' ],
            ],
        ] );
    }

    public function can_manage_services(): bool
    {
        return bookaro_frontend_services_enabled() && bookaro_user_has_provider_access();
    }

    public function can_manage_services_write( WP_REST_Request $request ): bool|\WP_Error
    {
        $auth = $this->require_authenticated_write(
            $request,
            __( 'You must be logged in to manage services.', 'mybookaro' )
        );
        if ( is_wp_error( $auth ) ) {
            return $auth;
        }

        if ( ! bookaro_frontend_services_enabled() || ! bookaro_user_has_provider_access() ) {
            return new WP_Error(
                'bookaro_forbidden',
                __( 'You do not have permission to manage services.', 'mybookaro' ),
                [ 'status' => 403 ]
            );
        }

        return true;
    }

    public function get_listings( WP_REST_Request $request ): WP_REST_Response
    {
        $user_id = get_current_user_id();
        $types = bookaro_get_allowed_listing_post_types();
        if ( empty( $types ) ) {
            return rest_ensure_response( [] );
        }

        $args = [
            'post_type'      => $types,
            'post_status'    => [ 'publish', 'draft', 'pending', 'private' ],
            'posts_per_page' => 200,
            'orderby'        => 'title',
            'order'          => 'ASC',
            'fields'         => 'ids',
        ];
        $resolution_mode = function_exists( 'bookaro_get_option' )
            ? (string) bookaro_get_option( 'provider_resolution_mode', '' )
            : '';
        $resolution_mode = sanitize_key( $resolution_mode );
        $provider_meta_key = function_exists( 'bookaro_get_option' )
            ? (string) bookaro_get_option( 'provider_meta_key', '' )
            : '';
        $provider_meta_key = sanitize_key( $provider_meta_key );
        if ( $provider_meta_key === '' ) {
            $legacy_meta_key = function_exists( 'bookaro_get_option' )
                ? (string) bookaro_get_option( 'listing_provider_meta_key', '' )
                : '';
            $legacy_meta_key = sanitize_key( $legacy_meta_key );
            if ( $legacy_meta_key !== '' ) {
                $provider_meta_key = $legacy_meta_key;
            }
        }
        if ( ! in_array( $resolution_mode, [ 'author', 'meta_key' ], true ) ) {
            $resolution_mode = $provider_meta_key !== '' ? 'meta_key' : 'author';
        }
        if ( 'meta_key' === $resolution_mode && $provider_meta_key !== '' ) {
            $args['meta_query'] = [
                [
                    'key'   => $provider_meta_key,
                    'value' => $user_id,
                    'compare' => '=',
                    'type'  => 'NUMERIC',
                ],
            ];
        } else {
            $args['author'] = $user_id;
        }
        $args = apply_filters( 'bookaro_provider_listings_query_args', $args, $user_id );
        $ids = get_posts( $args );

        $listings = [];
        foreach ( $ids as $listing_id ) {
            $listing_id = (int) $listing_id;
            if ( ! bookaro_is_allowed_listing( $listing_id ) ) {
                continue;
            }
            if ( function_exists( 'bookaro_is_lite_listing_allowed' ) && ! bookaro_is_lite_listing_allowed( $listing_id ) ) {
                continue;
            }
            if ( ! $this->user_owns_listing( $listing_id ) ) {
                continue;
            }
            $post = get_post( $listing_id );
            if ( ! $post ) {
                continue;
            }
            $listings[] = [
                'id'     => $listing_id,
                'title'  => $post->post_title,
                'type'   => $post->post_type,
                'status' => $post->post_status,
                'url'    => get_permalink( $listing_id ),
            ];
        }

        return rest_ensure_response( $listings );
    }

    public function get_services( WP_REST_Request $request ): WP_REST_Response|WP_Error
    {
        $listing_id = absint( $request->get_param( 'listing_id' ) );
        if ( ! $listing_id ) {
            return new WP_Error( 'bookaro_invalid_listing', __( 'Invalid listing.', 'mybookaro' ), [ 'status' => 400 ] );
        }
        if ( ! bookaro_is_allowed_listing( $listing_id ) ) {
            return new WP_Error( 'bookaro_invalid_listing', __( 'Listing not supported.', 'mybookaro' ), [ 'status' => 400 ] );
        }
        if ( function_exists( 'bookaro_is_lite_listing_allowed' ) && ! bookaro_is_lite_listing_allowed( $listing_id ) ) {
            return new WP_Error( 'bookaro_invalid_listing', __( 'Listing not supported.', 'mybookaro' ), [ 'status' => 403 ] );
        }
        if ( ! $this->user_owns_listing( $listing_id ) ) {
            return new WP_Error( 'bookaro_forbidden', __( 'You do not have permission to manage this listing.', 'mybookaro' ), [ 'status' => 403 ] );
        }

        if ( ! $this->provider_services_allowed() ) {
            return new WP_Error( 'bookaro_forbidden', __( 'Provider services are disabled.', 'mybookaro' ), [ 'status' => 403 ] );
        }

        $services = function_exists( 'bookaro_get_bookaro_provider_services_for_listing' )
            ? bookaro_get_bookaro_provider_services_for_listing( $listing_id )
            : bookaro_get_bookaro_services_for_listing( $listing_id );
        return rest_ensure_response( $services );
    }

    public function create_service( WP_REST_Request $request ): WP_REST_Response|WP_Error
    {
        $listing_id = absint( $request->get_param( 'listing_id' ) );
        $title      = sanitize_text_field( $request->get_param( 'title' ) );
        $description = sanitize_textarea_field( (string) $request->get_param( 'description' ) );
        $price      = (float) $request->get_param( 'price' );
        $duration   = absint( $request->get_param( 'duration' ) );

        if ( function_exists( 'bookaro_service_limit_reached' ) && bookaro_service_limit_reached() ) {
            return new WP_Error(
                'bookaro_service_limit',
                __( 'Service limit reached for this site.', 'mybookaro' ),
                [ 'status' => 403 ]
            );
        }
        if ( ! $this->provider_services_allowed() ) {
            return new WP_Error( 'bookaro_forbidden', __( 'Provider services are disabled.', 'mybookaro' ), [ 'status' => 403 ] );
        }
        if ( ! $listing_id || '' === $title ) {
            return new WP_Error( 'bookaro_invalid_input', __( 'Listing and title are required.', 'mybookaro' ), [ 'status' => 400 ] );
        }
        if ( ! bookaro_is_allowed_listing( $listing_id ) ) {
            return new WP_Error( 'bookaro_invalid_listing', __( 'Listing not supported.', 'mybookaro' ), [ 'status' => 400 ] );
        }
        if ( function_exists( 'bookaro_is_lite_listing_allowed' ) && ! bookaro_is_lite_listing_allowed( $listing_id ) ) {
            return new WP_Error( 'bookaro_invalid_listing', __( 'Listing not supported.', 'mybookaro' ), [ 'status' => 403 ] );
        }
        if ( ! $this->user_owns_listing( $listing_id ) ) {
            return new WP_Error( 'bookaro_forbidden', __( 'You do not have permission to manage this listing.', 'mybookaro' ), [ 'status' => 403 ] );
        }
        if ( ! $this->provider_custom_services_allowed() ) {
            if ( ! $this->provider_override_allowed() ) {
                return new WP_Error( 'bookaro_forbidden', __( 'Provider services are disabled.', 'mybookaro' ), [ 'status' => 403 ] );
            }
            if ( ! $this->is_catalog_service_label( $listing_id, $title ) ) {
                return new WP_Error(
                    'bookaro_invalid_service',
                    __( 'This service must match a catalog service label.', 'mybookaro' ),
                    [ 'status' => 400 ]
                );
            }
        }

        $service_id = wp_insert_post( [
            'post_type'    => BOOKARO_SERVICE_POST_TYPE,
            'post_title'   => $title,
            'post_content' => $description,
            'post_status'  => 'publish',
            'post_author'  => get_current_user_id(),
        ] );

        if ( is_wp_error( $service_id ) ) {
            return $service_id;
        }

        delete_post_meta( $service_id, BOOKARO_SERVICE_LISTING_META );
        update_post_meta( $service_id, BOOKARO_SERVICE_LISTING_META, $listing_id );
        update_post_meta( $service_id, BOOKARO_SERVICE_PRICE_META, $price );
        update_post_meta( $service_id, BOOKARO_SERVICE_DURATION_META, $duration );
        update_post_meta( $service_id, BOOKARO_SERVICE_DURATION_MINUTES_META, $duration );
        update_post_meta( $service_id, BOOKARO_SERVICE_LABEL_META, $title );
        update_post_meta( $service_id, BOOKARO_SERVICE_DESCRIPTION_META, $description );
        update_post_meta( $service_id, BOOKARO_SERVICE_SCOPE_META, 'provider' );
        update_post_meta( $service_id, BOOKARO_SERVICE_PROVIDER_META, get_current_user_id() );
        update_post_meta( $service_id, BOOKARO_SERVICE_OWNER_META, 'provider' );
        update_post_meta( $service_id, BOOKARO_SERVICE_SHARED_META, 0 );
        update_post_meta( $service_id, BOOKARO_SERVICE_IS_SHARED_META, 0 );

        return rest_ensure_response( $this->serialize_service( get_post( $service_id ) ) );
    }

    public function get_provider_scoped_services( WP_REST_Request $request ): WP_REST_Response|WP_Error
    {
        if ( ! $this->provider_services_allowed() ) {
            return new WP_Error( 'bookaro_forbidden', __( 'Provider services are disabled.', 'mybookaro' ), [ 'status' => 403 ] );
        }

        $provider_id = get_current_user_id();
        if ( $provider_id < 1 ) {
            return new WP_Error( 'bookaro_forbidden', __( 'You must be logged in to manage services.', 'mybookaro' ), [ 'status' => 401 ] );
        }

        return rest_ensure_response( $this->get_provider_services_for_provider_context( $provider_id ) );
    }

    public function create_provider_scoped_service( WP_REST_Request $request ): WP_REST_Response|WP_Error
    {
        $provider_id = get_current_user_id();
        $title = sanitize_text_field( (string) $request->get_param( 'title' ) );
        $description = sanitize_textarea_field( (string) $request->get_param( 'description' ) );
        $price = (float) $request->get_param( 'price' );
        $duration = absint( $request->get_param( 'duration' ) );
        $listing_id = absint( $request->get_param( 'listing_id' ) );

        if ( function_exists( 'bookaro_service_limit_reached' ) && bookaro_service_limit_reached() ) {
            return new WP_Error(
                'bookaro_service_limit',
                __( 'Service limit reached for this site.', 'mybookaro' ),
                [ 'status' => 403 ]
            );
        }
        if ( ! $this->provider_services_allowed() ) {
            return new WP_Error( 'bookaro_forbidden', __( 'Provider services are disabled.', 'mybookaro' ), [ 'status' => 403 ] );
        }
        if ( '' === $title ) {
            return new WP_Error( 'bookaro_invalid_input', __( 'Service title is required.', 'mybookaro' ), [ 'status' => 400 ] );
        }
        if ( $listing_id > 0 ) {
            if ( ! bookaro_is_allowed_listing( $listing_id ) ) {
                return new WP_Error( 'bookaro_invalid_listing', __( 'Listing not supported.', 'mybookaro' ), [ 'status' => 400 ] );
            }
            if ( function_exists( 'bookaro_is_lite_listing_allowed' ) && ! bookaro_is_lite_listing_allowed( $listing_id ) ) {
                return new WP_Error( 'bookaro_invalid_listing', __( 'Listing not supported.', 'mybookaro' ), [ 'status' => 403 ] );
            }
            if ( ! $this->user_owns_listing( $listing_id ) ) {
                return new WP_Error( 'bookaro_forbidden', __( 'You do not have permission to manage this listing.', 'mybookaro' ), [ 'status' => 403 ] );
            }
        }
        if ( ! $this->provider_custom_services_allowed() ) {
            if ( ! $this->provider_override_allowed() ) {
                return new WP_Error( 'bookaro_forbidden', __( 'Provider services are disabled.', 'mybookaro' ), [ 'status' => 403 ] );
            }
            if ( ! $this->is_catalog_service_label_for_provider_context( $provider_id, $title ) ) {
                return new WP_Error(
                    'bookaro_invalid_service',
                    __( 'This service must match a catalog service label.', 'mybookaro' ),
                    [ 'status' => 400 ]
                );
            }
        }

        $service_id = wp_insert_post( [
            'post_type'    => BOOKARO_SERVICE_POST_TYPE,
            'post_title'   => $title,
            'post_content' => $description,
            'post_status'  => 'publish',
            'post_author'  => $provider_id,
        ] );
        if ( is_wp_error( $service_id ) ) {
            return $service_id;
        }

        delete_post_meta( $service_id, BOOKARO_SERVICE_LISTING_META );
        update_post_meta( $service_id, BOOKARO_SERVICE_LISTING_META, $listing_id );
        update_post_meta( $service_id, BOOKARO_SERVICE_PRICE_META, $price );
        update_post_meta( $service_id, BOOKARO_SERVICE_DURATION_META, $duration );
        update_post_meta( $service_id, BOOKARO_SERVICE_DURATION_MINUTES_META, $duration );
        update_post_meta( $service_id, BOOKARO_SERVICE_LABEL_META, $title );
        update_post_meta( $service_id, BOOKARO_SERVICE_DESCRIPTION_META, $description );
        update_post_meta( $service_id, BOOKARO_SERVICE_SCOPE_META, 'provider' );
        update_post_meta( $service_id, BOOKARO_SERVICE_PROVIDER_META, $provider_id );
        update_post_meta( $service_id, BOOKARO_SERVICE_OWNER_META, 'provider' );
        update_post_meta( $service_id, BOOKARO_SERVICE_SHARED_META, 0 );
        update_post_meta( $service_id, BOOKARO_SERVICE_IS_SHARED_META, 0 );

        return rest_ensure_response( $this->serialize_service( get_post( $service_id ) ) );
    }

    public function update_provider_scoped_service( WP_REST_Request $request ): WP_REST_Response|WP_Error
    {
        $service_id = absint( $request->get_param( 'id' ) );
        if ( ! $service_id ) {
            return new WP_Error( 'bookaro_invalid_service', __( 'Invalid service.', 'mybookaro' ), [ 'status' => 400 ] );
        }
        $service = get_post( $service_id );
        if ( ! $service || BOOKARO_SERVICE_POST_TYPE !== $service->post_type ) {
            return new WP_Error( 'bookaro_invalid_service', __( 'Service not found.', 'mybookaro' ), [ 'status' => 404 ] );
        }
        if ( ! $this->provider_services_allowed() ) {
            return new WP_Error( 'bookaro_forbidden', __( 'Provider services are disabled.', 'mybookaro' ), [ 'status' => 403 ] );
        }
        if ( ! $this->user_can_manage_provider_service( $service ) ) {
            return new WP_Error( 'bookaro_forbidden', __( 'You do not have permission to edit this service.', 'mybookaro' ), [ 'status' => 403 ] );
        }

        $provider_id = get_current_user_id();
        if ( ! $this->provider_custom_services_allowed() ) {
            if ( ! $this->provider_override_allowed() ) {
                return new WP_Error( 'bookaro_forbidden', __( 'Provider services are disabled.', 'mybookaro' ), [ 'status' => 403 ] );
            }
            $incoming_title = $request->get_param( 'title' );
            $title_check = null !== $incoming_title
                ? sanitize_text_field( (string) $incoming_title )
                : ( function_exists( 'bookaro_get_service_label' )
                    ? bookaro_get_service_label( $service )
                    : $service->post_title );
            if ( ! $this->is_catalog_service_label_for_provider_context( $provider_id, $title_check ) ) {
                return new WP_Error(
                    'bookaro_invalid_service',
                    __( 'This service must match a catalog service label.', 'mybookaro' ),
                    [ 'status' => 400 ]
                );
            }
        }

        $listing_id = absint( $request->get_param( 'listing_id' ) );
        if ( $listing_id > 0 ) {
            if ( ! bookaro_is_allowed_listing( $listing_id ) ) {
                return new WP_Error( 'bookaro_invalid_listing', __( 'Listing not supported.', 'mybookaro' ), [ 'status' => 400 ] );
            }
            if ( function_exists( 'bookaro_is_lite_listing_allowed' ) && ! bookaro_is_lite_listing_allowed( $listing_id ) ) {
                return new WP_Error( 'bookaro_invalid_listing', __( 'Listing not supported.', 'mybookaro' ), [ 'status' => 403 ] );
            }
            if ( ! $this->user_owns_listing( $listing_id ) ) {
                return new WP_Error( 'bookaro_forbidden', __( 'You do not have permission to manage this listing.', 'mybookaro' ), [ 'status' => 403 ] );
            }
        }

        $post_update = [ 'ID' => $service_id ];
        if ( null !== $request->get_param( 'title' ) ) {
            $post_update['post_title'] = sanitize_text_field( (string) $request->get_param( 'title' ) );
            update_post_meta( $service_id, BOOKARO_SERVICE_LABEL_META, $post_update['post_title'] );
        }
        if ( null !== $request->get_param( 'description' ) ) {
            $post_update['post_content'] = sanitize_textarea_field( (string) $request->get_param( 'description' ) );
            update_post_meta( $service_id, BOOKARO_SERVICE_DESCRIPTION_META, $post_update['post_content'] );
        }
        if ( count( $post_update ) > 1 ) {
            wp_update_post( $post_update );
        }
        if ( null !== $request->get_param( 'price' ) ) {
            update_post_meta( $service_id, BOOKARO_SERVICE_PRICE_META, (float) $request->get_param( 'price' ) );
        }
        if ( null !== $request->get_param( 'duration' ) ) {
            $duration = absint( $request->get_param( 'duration' ) );
            update_post_meta( $service_id, BOOKARO_SERVICE_DURATION_META, $duration );
            update_post_meta( $service_id, BOOKARO_SERVICE_DURATION_MINUTES_META, $duration );
        }

        if ( null !== $request->get_param( 'listing_id' ) ) {
            delete_post_meta( $service_id, BOOKARO_SERVICE_LISTING_META );
            update_post_meta( $service_id, BOOKARO_SERVICE_LISTING_META, $listing_id );
        }
        update_post_meta( $service_id, BOOKARO_SERVICE_SCOPE_META, 'provider' );
        update_post_meta( $service_id, BOOKARO_SERVICE_PROVIDER_META, $provider_id );
        update_post_meta( $service_id, BOOKARO_SERVICE_OWNER_META, 'provider' );
        update_post_meta( $service_id, BOOKARO_SERVICE_SHARED_META, 0 );
        update_post_meta( $service_id, BOOKARO_SERVICE_IS_SHARED_META, 0 );

        return rest_ensure_response( $this->serialize_service( get_post( $service_id ) ) );
    }

    public function delete_provider_scoped_service( WP_REST_Request $request ): WP_REST_Response|WP_Error
    {
        $service_id = absint( $request->get_param( 'id' ) );
        if ( ! $service_id ) {
            return new WP_Error( 'bookaro_invalid_service', __( 'Invalid service.', 'mybookaro' ), [ 'status' => 400 ] );
        }
        $service = get_post( $service_id );
        if ( ! $service || BOOKARO_SERVICE_POST_TYPE !== $service->post_type ) {
            return new WP_Error( 'bookaro_invalid_service', __( 'Service not found.', 'mybookaro' ), [ 'status' => 404 ] );
        }
        if ( ! $this->provider_services_allowed() ) {
            return new WP_Error( 'bookaro_forbidden', __( 'Provider services are disabled.', 'mybookaro' ), [ 'status' => 403 ] );
        }
        if ( ! $this->user_can_manage_provider_service( $service ) ) {
            return new WP_Error( 'bookaro_forbidden', __( 'You do not have permission to delete this service.', 'mybookaro' ), [ 'status' => 403 ] );
        }

        $trashed = wp_trash_post( $service_id );
        if ( ! $trashed ) {
            return new WP_Error( 'bookaro_delete_failed', __( 'Unable to delete service.', 'mybookaro' ), [ 'status' => 500 ] );
        }

        return rest_ensure_response( [ 'success' => true ] );
    }

    public function update_service( WP_REST_Request $request ): WP_REST_Response|WP_Error
    {
        $service_id = absint( $request->get_param( 'id' ) );
        if ( ! $service_id ) {
            return new WP_Error( 'bookaro_invalid_service', __( 'Invalid service.', 'mybookaro' ), [ 'status' => 400 ] );
        }
        $service = get_post( $service_id );
        if ( ! $service || BOOKARO_SERVICE_POST_TYPE !== $service->post_type ) {
            return new WP_Error( 'bookaro_invalid_service', __( 'Service not found.', 'mybookaro' ), [ 'status' => 404 ] );
        }
        if ( ! $this->provider_services_allowed() ) {
            return new WP_Error( 'bookaro_forbidden', __( 'Provider services are disabled.', 'mybookaro' ), [ 'status' => 403 ] );
        }
        $owner_type = sanitize_key( (string) get_post_meta( $service_id, BOOKARO_SERVICE_OWNER_META, true ) );
        if ( 'provider' !== $owner_type ) {
            return new WP_Error( 'bookaro_forbidden', __( 'You do not have permission to edit this service.', 'mybookaro' ), [ 'status' => 403 ] );
        }

        $current_listing_id = (int) get_post_meta( $service_id, BOOKARO_SERVICE_LISTING_META, true );
        if ( ! $current_listing_id || ! bookaro_is_allowed_listing( $current_listing_id ) ) {
            return new WP_Error( 'bookaro_invalid_listing', __( 'Listing not supported.', 'mybookaro' ), [ 'status' => 400 ] );
        }
        if ( function_exists( 'bookaro_is_lite_listing_allowed' ) && ! bookaro_is_lite_listing_allowed( $current_listing_id ) ) {
            return new WP_Error( 'bookaro_invalid_listing', __( 'Listing not supported.', 'mybookaro' ), [ 'status' => 403 ] );
        }
        if ( ! $this->user_owns_listing( $current_listing_id ) ) {
            return new WP_Error( 'bookaro_forbidden', __( 'You do not have permission to manage this listing.', 'mybookaro' ), [ 'status' => 403 ] );
        }
        if ( ! $this->provider_custom_services_allowed() ) {
            if ( ! $this->provider_override_allowed() ) {
                return new WP_Error( 'bookaro_forbidden', __( 'Provider services are disabled.', 'mybookaro' ), [ 'status' => 403 ] );
            }
            $incoming_title = $request->get_param( 'title' );
            $title_check = null !== $incoming_title
                ? sanitize_text_field( $incoming_title )
                : ( function_exists( 'bookaro_get_service_label' )
                    ? bookaro_get_service_label( $service )
                    : $service->post_title );
            if ( ! $this->is_catalog_service_label( $current_listing_id, $title_check ) ) {
                return new WP_Error(
                    'bookaro_invalid_service',
                    __( 'This service must match a catalog service label.', 'mybookaro' ),
                    [ 'status' => 400 ]
                );
            }
        }

        $listing_id = absint( $request->get_param( 'listing_id' ) );
        if ( $listing_id && $listing_id !== $current_listing_id ) {
            if ( ! bookaro_is_allowed_listing( $listing_id ) ) {
                return new WP_Error( 'bookaro_invalid_listing', __( 'Listing not supported.', 'mybookaro' ), [ 'status' => 400 ] );
            }
            if ( function_exists( 'bookaro_is_lite_listing_allowed' ) && ! bookaro_is_lite_listing_allowed( $listing_id ) ) {
                return new WP_Error( 'bookaro_invalid_listing', __( 'Listing not supported.', 'mybookaro' ), [ 'status' => 403 ] );
            }
            if ( ! $this->user_owns_listing( $listing_id ) ) {
                return new WP_Error( 'bookaro_forbidden', __( 'You do not have permission to manage this listing.', 'mybookaro' ), [ 'status' => 403 ] );
            }
        }

        delete_post_meta( $service_id, BOOKARO_SERVICE_LISTING_META );
        $post_update = [ 'ID' => $service_id ];
        if ( null !== $request->get_param( 'title' ) ) {
            $post_update['post_title'] = sanitize_text_field( $request->get_param( 'title' ) );
            update_post_meta( $service_id, BOOKARO_SERVICE_LABEL_META, $post_update['post_title'] );
        }
        if ( null !== $request->get_param( 'description' ) ) {
            $post_update['post_content'] = sanitize_textarea_field( (string) $request->get_param( 'description' ) );
            update_post_meta( $service_id, BOOKARO_SERVICE_DESCRIPTION_META, $post_update['post_content'] );
        }
        if ( count( $post_update ) > 1 ) {
            wp_update_post( $post_update );
        }

        if ( null !== $request->get_param( 'price' ) ) {
            update_post_meta( $service_id, BOOKARO_SERVICE_PRICE_META, (float) $request->get_param( 'price' ) );
        }
        if ( null !== $request->get_param( 'duration' ) ) {
            $duration = absint( $request->get_param( 'duration' ) );
            update_post_meta( $service_id, BOOKARO_SERVICE_DURATION_META, $duration );
            update_post_meta( $service_id, BOOKARO_SERVICE_DURATION_MINUTES_META, $duration );
        }
        if ( $listing_id < 1 ) {
            $listing_id = $current_listing_id;
        }
        if ( $listing_id > 0 ) {
            update_post_meta( $service_id, BOOKARO_SERVICE_LISTING_META, $listing_id );
        }
        update_post_meta( $service_id, BOOKARO_SERVICE_SCOPE_META, 'provider' );
        update_post_meta( $service_id, BOOKARO_SERVICE_PROVIDER_META, get_current_user_id() );
        update_post_meta( $service_id, BOOKARO_SERVICE_OWNER_META, 'provider' );
        update_post_meta( $service_id, BOOKARO_SERVICE_SHARED_META, 0 );
        update_post_meta( $service_id, BOOKARO_SERVICE_IS_SHARED_META, 0 );

        return rest_ensure_response( $this->serialize_service( get_post( $service_id ) ) );
    }

    public function delete_service( WP_REST_Request $request ): WP_REST_Response|WP_Error
    {
        $service_id = absint( $request->get_param( 'id' ) );
        if ( ! $service_id ) {
            return new WP_Error( 'bookaro_invalid_service', __( 'Invalid service.', 'mybookaro' ), [ 'status' => 400 ] );
        }
        $service = get_post( $service_id );
        if ( ! $service || BOOKARO_SERVICE_POST_TYPE !== $service->post_type ) {
            return new WP_Error( 'bookaro_invalid_service', __( 'Service not found.', 'mybookaro' ), [ 'status' => 404 ] );
        }
        if ( ! $this->provider_services_allowed() ) {
            return new WP_Error( 'bookaro_forbidden', __( 'Provider services are disabled.', 'mybookaro' ), [ 'status' => 403 ] );
        }
        $owner_type = sanitize_key( (string) get_post_meta( $service_id, BOOKARO_SERVICE_OWNER_META, true ) );
        if ( 'provider' !== $owner_type ) {
            return new WP_Error( 'bookaro_forbidden', __( 'You do not have permission to delete this service.', 'mybookaro' ), [ 'status' => 403 ] );
        }

        $listing_id = (int) get_post_meta( $service_id, BOOKARO_SERVICE_LISTING_META, true );
        if ( ! $listing_id || ! bookaro_is_allowed_listing( $listing_id ) ) {
            return new WP_Error( 'bookaro_invalid_listing', __( 'Listing not supported.', 'mybookaro' ), [ 'status' => 400 ] );
        }
        if ( function_exists( 'bookaro_is_lite_listing_allowed' ) && ! bookaro_is_lite_listing_allowed( $listing_id ) ) {
            return new WP_Error( 'bookaro_invalid_listing', __( 'Listing not supported.', 'mybookaro' ), [ 'status' => 403 ] );
        }
        if ( ! $this->user_owns_listing( $listing_id ) ) {
            return new WP_Error( 'bookaro_forbidden', __( 'You do not have permission to manage this listing.', 'mybookaro' ), [ 'status' => 403 ] );
        }

        $trashed = wp_trash_post( $service_id );
        if ( ! $trashed ) {
            return new WP_Error( 'bookaro_delete_failed', __( 'Unable to delete service.', 'mybookaro' ), [ 'status' => 500 ] );
        }

        return rest_ensure_response( [ 'success' => true ] );
    }

    /**
     * Build admin diagnostics for service resolution in Generic mode.
     *
     * @return array{state:string,value:string,detail:string,fix:string}
     */
    public static function get_admin_service_resolution_diagnostics( int $listing_id, int $provider_id = 0 ): array
    {
        $integration_mode = function_exists( 'bookaro_get_integration_mode' )
            ? (string) bookaro_get_integration_mode()
            : 'auto';
        if ( 'generic' !== $integration_mode ) {
            return [
                'state' => 'info',
                'value' => __( 'Not required', 'mybookaro' ),
                'detail' => __( 'Service resolution diagnostics apply only in Generic mode.', 'mybookaro' ),
                'fix' => '',
                'next_step' => '',
            ];
        }

        if ( $listing_id < 1 || ! function_exists( 'bookaro_is_allowed_listing' ) || ! bookaro_is_allowed_listing( $listing_id ) ) {
            return [
                'state' => 'error',
                'value' => __( 'Fail', 'mybookaro' ),
                'detail' => __( 'Bookaro could not find a valid sample listing for service checks. Until there is one, it cannot confirm which services customers should see.', 'mybookaro' ),
                'fix' => __( 'Select allowed listing types/pages in Settings > General and create a valid sample listing.', 'mybookaro' ),
                'next_step' => __( 'Next step: Confirm the allowed listing setup, create or select a valid sample listing, then run Generic validation again.', 'mybookaro' ),
            ];
        }

        $model = function_exists( 'bookaro_get_services_model' )
            ? sanitize_key( (string) bookaro_get_services_model() )
            : 'hybrid';
        if ( ! in_array( $model, [ 'provider_only', 'admin_only', 'hybrid' ], true ) ) {
            $model = 'hybrid';
        }
        $model_labels = [
            'provider_only' => __( 'Provider Only', 'mybookaro' ),
            'admin_only' => __( 'Admin Catalog Only', 'mybookaro' ),
            'hybrid' => __( 'Hybrid', 'mybookaro' ),
        ];
        $model_label = (string) ( $model_labels[ $model ] ?? __( 'Hybrid', 'mybookaro' ) );

        $provider_services = function_exists( 'bookaro_get_bookaro_provider_services_for_listing' )
            ? bookaro_get_bookaro_provider_services_for_listing( $listing_id )
            : [];
        $admin_listing_services = function_exists( 'bookaro_get_bookaro_admin_services_for_listing' )
            ? bookaro_get_bookaro_admin_services_for_listing( $listing_id )
            : [];
        $global_services = function_exists( 'bookaro_get_bookaro_global_services' )
            ? bookaro_get_bookaro_global_services( $listing_id )
            : [];
        $admin_services = array_merge( $admin_listing_services, $global_services );
        $public_services = function_exists( 'bookaro_get_public_services_for_listing' )
            ? bookaro_get_public_services_for_listing( $listing_id )
            : [];

        $provider_services_allowed = function_exists( 'bookaro_provider_services_allowed' )
            ? (bool) bookaro_provider_services_allowed()
            : false;
        $provider_custom_allowed = function_exists( 'bookaro_allow_provider_custom_services' )
            ? (bool) bookaro_allow_provider_custom_services()
            : false;
        $provider_override_allowed = function_exists( 'bookaro_allow_provider_override_catalog' )
            ? (bool) bookaro_allow_provider_override_catalog()
            : false;

        $provider_id = absint( $provider_id );
        if ( $provider_id < 1 && function_exists( 'bookaro_get_listing_owner_id' ) ) {
            $provider_id = (int) bookaro_get_listing_owner_id( $listing_id );
        }
        $provider_listing_match = null;
        if ( $provider_id > 0 && function_exists( 'bookaro_get_listing_id_for_provider' ) ) {
            $provider_listing_match = (int) bookaro_get_listing_id_for_provider( $provider_id );
        }

        $issues = [];
        $fix = '';
        $next_step = '';
        if ( 'provider_only' === $model && ! $provider_services_allowed ) {
            $issues[] = __( 'Services Source is Provider Only, but provider-managed services are currently disabled. Providers cannot supply any bookable services until this is turned back on.', 'mybookaro' );
            if ( '' === $fix ) {
                $fix = __( 'Open Setup Wizard > Services and either keep Provider Only with provider-managed services enabled, or choose the Services Source that matches your catalog model.', 'mybookaro' );
                $next_step = __( 'Next step: Open Setup Wizard > Services, confirm the correct Services Source, save, then run Generic validation again.', 'mybookaro' );
            }
        }
        if ( 'provider_only' === $model && empty( $provider_services ) ) {
            $issues[] = __( 'Services Source is Provider Only, but the sample listing has no provider-managed services yet. Customers would reach the booking flow with no service choices.', 'mybookaro' );
            if ( '' === $fix ) {
                $fix = __( 'Open Bookaro > Services and create or assign at least one provider-managed service for the mapped provider or listing.', 'mybookaro' );
                $next_step = __( 'Next step: Open Bookaro > Services, add a provider-managed service for this listing, then run Generic validation again.', 'mybookaro' );
            }
        }
        if ( 'admin_only' === $model && empty( $admin_services ) ) {
            $issues[] = __( 'Services Source is Admin Catalog Only, but no shared admin catalog service is available for the sample listing. Customers would reach the booking flow with no service choices.', 'mybookaro' );
            if ( '' === $fix ) {
                $fix = __( 'Open Bookaro > Services and create or assign at least one shared admin catalog service that should appear for this listing.', 'mybookaro' );
                $next_step = __( 'Next step: Open Bookaro > Services, add the shared service, then run Generic validation again.', 'mybookaro' );
            }
        }
        if ( 'hybrid' === $model && empty( $public_services ) ) {
            $issues[] = __( 'Services Source is Hybrid, but the sample listing still resolves zero customer-visible services. Customers would reach the booking flow with no service choices.', 'mybookaro' );
            if ( '' === $fix ) {
                $fix = __( 'Open Bookaro > Services and create or assign at least one provider-managed or admin catalog service that should appear for this listing.', 'mybookaro' );
                $next_step = __( 'Next step: Open Bookaro > Services, add a visible service for this listing, then run Generic validation again.', 'mybookaro' );
            }
        }
        if ( $provider_id > 0 && in_array( $model, [ 'provider_only', 'hybrid' ], true ) ) {
            if ( null !== $provider_listing_match && $provider_listing_match !== $listing_id ) {
                $issues[] = __( 'The mapped provider links back to a different listing than the sample listing. Service rules may be running against the wrong provider or listing pair.', 'mybookaro' );
                if ( '' === $fix ) {
                    $fix = __( 'Open Setup Wizard > Listings and confirm Provider Mapping and the sample listing provider data so Bookaro is checking the right provider/listing pair.', 'mybookaro' );
                    $next_step = __( 'Next step: Open Setup Wizard > Listings, confirm the provider mapping, save, then run Generic validation again.', 'mybookaro' );
                }
            }
        }

        $state = empty( $issues ) ? 'ok' : 'error';
        $value = empty( $issues ) ? __( 'Pass', 'mybookaro' ) : __( 'Fail', 'mybookaro' );
        $detail = sprintf(
            /* translators: 1: services source label, 2: listing id, 3: public services count, 4: provider services count, 5: admin/shared services count */
            __( 'Services Source is %1$s for sample listing #%2$d. Bookaro found %3$d customer-visible services, %4$d provider-managed services, and %5$d admin/shared services.', 'mybookaro' ),
            $model_label,
            $listing_id,
            count( $public_services ),
            count( $provider_services ),
            count( $admin_services )
        );

        if ( $provider_id > 0 ) {
            $detail .= ' ' . sprintf(
                /* translators: 1: provider id, 2: mapped listing id */
                __( 'Mapped provider #%1$d links back to listing #%2$d for this check.', 'mybookaro' ),
                $provider_id,
                (int) $provider_listing_match
            );
        }
        if ( ! empty( $issues ) ) {
            $detail .= ' ' . implode( ' ', $issues );
        } elseif ( 'provider_only' === $model ) {
            $detail .= ' ' . __( 'Customers can already see provider-managed services for this listing.', 'mybookaro' );
        } elseif ( 'admin_only' === $model ) {
            $detail .= ' ' . __( 'Customers can already see shared admin catalog services for this listing.', 'mybookaro' );
        } else {
            $detail .= ' ' . sprintf(
                /* translators: 1: custom services flag, 2: provider override flag */
                __( 'Customers can already see services from the combined provider/admin sources. Provider custom services are %1$s and provider overrides are %2$s.', 'mybookaro' ),
                $provider_custom_allowed ? __( 'enabled', 'mybookaro' ) : __( 'disabled', 'mybookaro' ),
                $provider_override_allowed ? __( 'enabled', 'mybookaro' ) : __( 'disabled', 'mybookaro' )
            );
        }

        return [
            'state' => $state,
            'value' => $value,
            'detail' => $detail,
            'fix' => $fix,
            'next_step' => $next_step,
        ];
    }

    private function user_owns_listing( int $listing_id ): bool
    {
        if ( current_user_can( 'manage_options' ) ) {
            return true;
        }
        $owner_id = bookaro_get_listing_owner_id( $listing_id );
        return $owner_id > 0 && $owner_id === get_current_user_id();
    }

    private function user_can_manage_provider_service( \WP_Post $service ): bool
    {
        if ( current_user_can( 'manage_options' ) ) {
            return true;
        }

        $service_id = (int) $service->ID;
        if ( $service_id < 1 ) {
            return false;
        }

        $owner_type = sanitize_key( (string) get_post_meta( $service_id, BOOKARO_SERVICE_OWNER_META, true ) );
        if ( 'provider' !== $owner_type ) {
            return false;
        }

        $current_user_id = get_current_user_id();
        if ( $current_user_id < 1 ) {
            return false;
        }

        $provider_id = (int) get_post_meta( $service_id, BOOKARO_SERVICE_PROVIDER_META, true );
        if ( $provider_id > 0 ) {
            return $provider_id === $current_user_id;
        }

        if ( (int) $service->post_author === $current_user_id ) {
            return true;
        }

        $listing_id = (int) get_post_meta( $service_id, BOOKARO_SERVICE_LISTING_META, true );
        if ( $listing_id > 0 ) {
            return $this->user_owns_listing( $listing_id );
        }

        return false;
    }

    private function get_provider_services_for_provider_context( int $provider_id ): array
    {
        $provider_id = absint( $provider_id );
        if ( $provider_id < 1 ) {
            return [];
        }

        // Bug 67: cap the per-provider service fetch. A provider listing
        // their own services almost always has a handful, but an
        // unbounded posts_per_page=-1 here means a provider (or a buggy
        // import) with thousands of service posts loads them all into
        // memory on every services-tab open. 500 is far above any sane
        // catalog size and protects against the pathological case;
        // filterable for the rare legitimate large catalog.
        $services_limit = (int) apply_filters( 'bookaro_provider_services_query_limit', 500, $provider_id );
        if ( $services_limit < 1 ) {
            $services_limit = 500;
        }
        $query = new \WP_Query( [
            'post_type'              => BOOKARO_SERVICE_POST_TYPE,
            'post_status'            => 'publish',
            'posts_per_page'         => $services_limit,
            'orderby'                => [
                'menu_order' => 'ASC',
                'title'      => 'ASC',
                'ID'         => 'ASC',
            ],
            // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
            'meta_query'             => [
                [
                    'key'     => BOOKARO_SERVICE_PROVIDER_META,
                    'value'   => (string) $provider_id,
                    'compare' => '=',
                    'type'    => 'NUMERIC',
                ],
                [
                    'key'     => BOOKARO_SERVICE_OWNER_META,
                    'value'   => 'provider',
                    'compare' => '=',
                ],
            ],
            'no_found_rows'          => true,
            'update_post_term_cache' => false,
        ] );

        $services = [];
        foreach ( $query->posts as $post ) {
            if ( ! $post instanceof \WP_Post ) {
                continue;
            }
            $listing_id = absint( get_post_meta( $post->ID, BOOKARO_SERVICE_LISTING_META, true ) );
            if ( $listing_id > 0 ) {
                if ( ! bookaro_is_allowed_listing( $listing_id ) ) {
                    continue;
                }
                if ( function_exists( 'bookaro_is_lite_listing_allowed' ) && ! bookaro_is_lite_listing_allowed( $listing_id ) ) {
                    continue;
                }
                if ( ! $this->user_owns_listing( $listing_id ) ) {
                    continue;
                }
            }

            $services[] = $this->serialize_service( $post );
        }

        return $services;
    }

    private function normalize_service_label_key( string $label ): string
    {
        if ( function_exists( 'bookaro_normalize_service_label' ) ) {
            return bookaro_normalize_service_label( $label );
        }

        return strtolower( trim( wp_strip_all_tags( $label ) ) );
    }

    private function get_provider_catalog_services_for_context( int $provider_id ): array
    {
        $catalog = function_exists( 'bookaro_get_bookaro_global_services' )
            ? bookaro_get_bookaro_global_services( 0 )
            : [];

        $provider_id = absint( $provider_id );
        if ( $provider_id < 1 ) {
            return $catalog;
        }

        foreach ( $this->get_provider_listing_ids( $provider_id ) as $listing_id ) {
            $listing_id = absint( $listing_id );
            if ( $listing_id < 1 ) {
                continue;
            }
            if ( ! bookaro_is_allowed_listing( $listing_id ) ) {
                continue;
            }
            if ( function_exists( 'bookaro_is_lite_listing_allowed' ) && ! bookaro_is_lite_listing_allowed( $listing_id ) ) {
                continue;
            }
            if ( ! $this->user_owns_listing( $listing_id ) ) {
                continue;
            }
            if ( function_exists( 'bookaro_get_bookaro_admin_services_for_listing' ) ) {
                $catalog = array_merge( $catalog, bookaro_get_bookaro_admin_services_for_listing( $listing_id ) );
            }
        }

        if ( function_exists( 'bookaro_dedupe_services_by_label' ) ) {
            return bookaro_dedupe_services_by_label( $catalog );
        }

        return $catalog;
    }

    private function is_catalog_service_label_for_provider_context( int $provider_id, string $label ): bool
    {
        $label = trim( $label );
        if ( '' === $label ) {
            return false;
        }

        $target = $this->normalize_service_label_key( $label );
        if ( '' === $target ) {
            return false;
        }

        foreach ( $this->get_provider_catalog_services_for_context( $provider_id ) as $service ) {
            if ( ! is_array( $service ) ) {
                continue;
            }
            $candidate = $this->normalize_service_label_key( (string) ( $service['title'] ?? '' ) );
            if ( '' !== $candidate && $candidate === $target ) {
                return true;
            }
        }

        return false;
    }

    private function get_provider_listing_ids( int $provider_id ): array
    {
        $provider_id = absint( $provider_id );
        if ( $provider_id < 1 ) {
            return [];
        }

        $types = function_exists( 'bookaro_get_allowed_listing_post_types' )
            ? bookaro_get_allowed_listing_post_types()
            : [];
        if ( empty( $types ) || ! is_array( $types ) ) {
            return [];
        }

        $args = [
            'post_type'      => $types,
            'post_status'    => [ 'publish', 'draft', 'pending', 'private' ],
            'posts_per_page' => 200,
            'orderby'        => 'title',
            'order'          => 'ASC',
            'fields'         => 'ids',
        ];
        $resolution_mode = function_exists( 'bookaro_get_option' )
            ? (string) bookaro_get_option( 'provider_resolution_mode', '' )
            : '';
        $resolution_mode = sanitize_key( $resolution_mode );
        $provider_meta_key = function_exists( 'bookaro_get_option' )
            ? (string) bookaro_get_option( 'provider_meta_key', '' )
            : '';
        $provider_meta_key = sanitize_key( $provider_meta_key );
        if ( $provider_meta_key === '' ) {
            $legacy_meta_key = function_exists( 'bookaro_get_option' )
                ? (string) bookaro_get_option( 'listing_provider_meta_key', '' )
                : '';
            $legacy_meta_key = sanitize_key( $legacy_meta_key );
            if ( $legacy_meta_key !== '' ) {
                $provider_meta_key = $legacy_meta_key;
            }
        }
        if ( ! in_array( $resolution_mode, [ 'author', 'meta_key' ], true ) ) {
            $resolution_mode = $provider_meta_key !== '' ? 'meta_key' : 'author';
        }
        if ( 'meta_key' === $resolution_mode && $provider_meta_key !== '' ) {
            $args['meta_query'] = [
                [
                    'key'   => $provider_meta_key,
                    'value' => $provider_id,
                    'compare' => '=',
                    'type'  => 'NUMERIC',
                ],
            ];
        } else {
            $args['author'] = $provider_id;
        }

        $args = apply_filters( 'bookaro_provider_listings_query_args', $args, $provider_id );
        $ids = get_posts( $args );
        if ( ! is_array( $ids ) ) {
            return [];
        }

        return array_values( array_filter( array_map( 'absint', $ids ) ) );
    }

    private function serialize_service( ?\WP_Post $post ): array
    {
        if ( ! $post ) {
            return [];
        }
        $listing_id = (int) get_post_meta( $post->ID, BOOKARO_SERVICE_LISTING_META, true );
        $price = (float) get_post_meta( $post->ID, BOOKARO_SERVICE_PRICE_META, true );
        $price_formatted = function_exists( 'bookaro_format_price' )
            ? bookaro_format_price( $price )
            : '';
        $scope = sanitize_key( (string) get_post_meta( $post->ID, BOOKARO_SERVICE_SCOPE_META, true ) );
        $owner_type = sanitize_key( (string) get_post_meta( $post->ID, BOOKARO_SERVICE_OWNER_META, true ) );
        if ( '' === $scope ) {
            if ( 'provider' === $owner_type ) {
                $scope = 'provider';
            } elseif ( $listing_id > 0 ) {
                $scope = 'listing';
            } else {
                $scope = 'global';
            }
        }
        $shared = absint( get_post_meta( $post->ID, BOOKARO_SERVICE_IS_SHARED_META, true ) );
        if ( $shared < 1 ) {
            $shared = absint( get_post_meta( $post->ID, BOOKARO_SERVICE_SHARED_META, true ) );
        }
        if ( 'provider' === $owner_type ) {
            $shared = 0;
        }
        if ( 'global' === $scope && $shared < 1 ) {
            $shared = 1;
        }
        return [
            'id'          => $post->ID,
            'title'       => function_exists( 'bookaro_get_service_label' )
                ? bookaro_get_service_label( $post )
                : $post->post_title,
            'description' => function_exists( 'bookaro_get_service_description' )
                ? bookaro_get_service_description( $post )
                : $post->post_content,
            'price'       => $price,
            'price_formatted' => $price_formatted,
            'duration'    => function_exists( 'bookaro_get_service_duration_minutes' )
                ? bookaro_get_service_duration_minutes( $post->ID )
                : (int) get_post_meta( $post->ID, BOOKARO_SERVICE_DURATION_META, true ),
            'listing_id'  => $listing_id,
            'scope'       => $scope,
            'shared'      => $shared,
        ];
    }

    private function provider_services_allowed(): bool
    {
        return function_exists( 'bookaro_provider_services_allowed' )
            ? bookaro_provider_services_allowed()
            : false;
    }

    private function provider_custom_services_allowed(): bool
    {
        return function_exists( 'bookaro_allow_provider_custom_services' )
            ? bookaro_allow_provider_custom_services()
            : false;
    }

    private function provider_override_allowed(): bool
    {
        return function_exists( 'bookaro_allow_provider_override_catalog' )
            ? bookaro_allow_provider_override_catalog()
            : false;
    }

    private function is_catalog_service_label( int $listing_id, string $label ): bool
    {
        $label = trim( $label );
        if ( $listing_id < 1 || $label === '' ) {
            return false;
        }
        if ( ! function_exists( 'bookaro_normalize_service_label' ) ) {
            return true;
        }
        $target = bookaro_normalize_service_label( $label );
        if ( '' === $target ) {
            return false;
        }
        $catalog = [];
        if ( function_exists( 'bookaro_get_bookaro_admin_services_for_listing' ) ) {
            $catalog = array_merge(
                bookaro_get_bookaro_admin_services_for_listing( $listing_id ),
                bookaro_get_bookaro_global_services( $listing_id )
            );
        }
        foreach ( $catalog as $service ) {
            if ( ! is_array( $service ) ) {
                continue;
            }
            $candidate = bookaro_normalize_service_label( (string) ( $service['title'] ?? '' ) );
            if ( $candidate !== '' && $candidate === $target ) {
                return true;
            }
        }
        return false;
    }
}
