<?php

namespace PloverCRM\Modules\PushNotifications\Services;

use PloverCRM\Common\LicenseChecker;

/**
 * Relays mobile notification registration and sends through the hub.
 *
 * The client plugin never talks to the Cloudflare Worker directly anymore.
 * It authenticates to the hub with the site activation token, and the hub
 * performs the worker request with its own shared secret.
 */
class HubPushGateway
{
    private const API_NAMESPACE = '/wp-json/plovercrm-hub/v1';

    public static function syncInstallation(array $payload)
    {
        return self::request('/mobile-push/register-installation', $payload, 'mobile-installation-sync');
    }

    public static function unlinkInstallation(string $installationId)
    {
        return self::request('/mobile-push/unlink-installation', [
            'installation_id' => sanitize_text_field($installationId),
        ], 'mobile-installation-unlink');
    }

    public static function sendOperational(array $notification)
    {
        return self::request('/mobile-push/send-operational', [
            'notification' => $notification,
        ], 'operational-push');
    }

    public static function sendDailySummary(array $notification)
    {
        return self::request('/mobile-push/send-daily-summary', [
            'notification' => $notification,
        ], 'daily-summary-push');
    }

    private static function request(string $path, array $payload, string $service)
    {
        $license = LicenseChecker::getLicense();
        $token = sanitize_text_field((string) ($license['token'] ?? ''));

        if ($token === '') {
            return new \WP_Error('license_inactive', 'A valid hub activation is required before mobile notifications can sync.');
        }

        $hubUrl = untrailingslashit(LicenseChecker::getHubUrl()) . self::API_NAMESPACE . $path;
        $body = wp_json_encode($payload);

        if ($body === false) {
            return new \WP_Error('json_encode_failed', 'Failed to encode the hub notification payload.');
        }

        $response = wp_remote_post($hubUrl, [
            'timeout' => 15,
            'headers' => [
                'Content-Type' => 'application/json',
                'Accept' => 'application/json',
                'X-PloverCRM-Token' => $token,
                'X-PloverCRM-Service' => sanitize_key($service),
            ],
            'body' => $body,
            'data_format' => 'body',
        ]);

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

        $status = (int) wp_remote_retrieve_response_code($response);
        $decoded = json_decode((string) wp_remote_retrieve_body($response), true);
        $message = sanitize_text_field((string) ($decoded['message'] ?? $decoded['error'] ?? ''));

        if ($status < 200 || $status >= 300) {
            $errorCode = 'hub_request_failed';
            $errorStatus = $status;
            $errorMessage = $message !== '' ? $message : 'The hub request failed.';

            if ($status === 401 || $status === 403) {
                $errorCode = 'hub_mobile_push_auth_failed';
                $errorStatus = 503;
                $errorMessage = 'The hub rejected this site\'s mobile push relay request.';
            } elseif ($status === 404) {
                $errorCode = 'hub_mobile_push_unavailable';
                $errorStatus = 503;
                $errorMessage = 'The hub mobile push relay is not available.';
            } elseif ($status >= 500) {
                $errorCode = 'hub_mobile_push_unavailable';
                $errorStatus = 503;
                $errorMessage = $message !== '' ? $message : 'The hub mobile push relay is unavailable right now.';
            }

            return new \WP_Error(
                $errorCode,
                $errorMessage,
                [
                    'status' => $errorStatus,
                    'hub_status' => $status,
                    'response' => $decoded,
                ]
            );
        }

        return is_array($decoded) ? $decoded : [
            'success' => true,
            'data' => [],
        ];
    }
}
