<?php

declare(strict_types=1);

namespace CliqThemes\StoreLocator\REST;

defined('ABSPATH') || exit;

use WP_REST_Response;

/**
 * Response and input conventions shared by the endpoints a visitor can reach.
 *
 * Both live here because both must be applied consistently: a cache header that
 * one controller sets and another forgets makes caching unpredictable, and text
 * arriving from an unauthenticated request has to be narrowed the same way
 * whichever endpoint received it.
 */
trait RespondsToRest
{
    /** Mark a response cacheable by proxies for a bounded time. */
    private function cacheable(WP_REST_Response $response, int $maxAge = 300): WP_REST_Response
    {
        $response->header('Cache-Control', 'public, max-age=' . $maxAge);

        return $response;
    }

    /**
     * A single line of plain text, or '' for anything that is not a string.
     *
     * Deliberately no wp_unslash(): these values arrive as a JSON request body,
     * which WordPress does not slash, so unslashing would eat a legitimate
     * backslash out of a store name or an address.
     */
    private function sanitizeText(mixed $value): string
    {
        if (! is_string($value)) {
            return '';
        }

        return sanitize_text_field($value);
    }

    /**
     * A request's JSON body, falling back to its query/route parameters.
     *
     * @return array<string, mixed>
     */
    private function body(\WP_REST_Request $request): array
    {
        $json = $request->get_json_params();
        if (is_array($json) && $json !== []) {
            return $json;
        }

        return $request->get_params();
    }

    private function ok(mixed $data, int $status = 200): WP_REST_Response
    {
        return new WP_REST_Response($data, $status);
    }

    private function notFound(): WP_REST_Response
    {
        return new WP_REST_Response(['message' => __('Not found.', 'cliq-store-locator')], 404);
    }

    /**
     * Honour a `lang` parameter for this request.
     *
     * A REST URL carries no language prefix, so a multilingual plugin cannot
     * infer the language the page was rendered in — the caller passes it and any
     * endpoint returning author-entered text has to apply it.
     */
    private function applyRequestLanguage(\WP_REST_Request $request): void
    {
        $lang = $request->get_param('lang');
        if ($lang !== null && $lang !== '') {
            \CliqThemes\StoreLocator\I18n\Multilingual::setOverride((string) $lang);
        }
    }
}
