<?php

namespace FleekDash\Controllers\License;

use WP_Error;

if (!\function_exists('fleekdash_log_debug')) {
    require_once FLEEKDASH_PLUGIN_DIR . 'includes/Core/debug-helpers.php';
}

/**
 * Remote Activation Service
 *
 * Handles remote license activation checking and synchronization
 *
 * @package FleekDash\Controllers\License
 * @since 2.2.0
 */
class RemoteActivationService
{
    private const HTTP_OK = 200;
    private const REMOTE_CHECK_INTERVAL_SECONDS = 3600;

    private string $supabaseUrl;
    private string $supabaseKey;
    private string $apiVersion;

    public function __construct(string $supabaseUrl, string $supabaseKey, string $apiVersion = 'v1')
    {
        $this->supabaseUrl = $supabaseUrl;
        $this->supabaseKey = $supabaseKey;
        $this->apiVersion = $apiVersion;
    }

    /**
     * Check for remote activation for this site
     *
     * @return array|WP_Error Activation data or error
     */
    public function checkRemoteActivation()
    {
        $configError = $this->validateSupabaseConfig();
        if ($configError instanceof WP_Error) {
            return $configError;
        }

        $siteUrl = \get_site_url();
        fleekdash_log_debug('FleekDash V2: Checking for remote activation for site: ' . $siteUrl);

        $response = $this->callFindSiteActivationRpc($siteUrl);

        return $this->parseFindSiteActivationResponse($response);
    }

    /**
     * Check if remote activation should be checked based on interval
     *
     * @return bool Whether remote activation check should run
     */
    public function shouldCheckRemoteActivation(): bool
    {
        // Honor user intent: never auto re-activate after explicit deactivation while the guard is set.
        if ((int) \get_option('fleekdash_v2_user_deactivated_at', 0) > 0) {
            return false;
        }

        $localStatus = \get_option('fleekdash_v2_license_status');
        $localKey = \get_option('fleekdash_v2_license_key');
        $alreadyActiveLocally = $localStatus === 'active' && !empty($localKey);
        $shouldCheck = false;

        if (!$alreadyActiveLocally) {
            $lastRemoteCheck = (int) \get_option('fleekdash_v2_last_remote_check', 0);
            if ((time() - $lastRemoteCheck) > self::REMOTE_CHECK_INTERVAL_SECONDS) {
                fleekdash_log_debug('FleekDash V2: Should check remote activation. Site URL: ' . \get_site_url());
                \update_option('fleekdash_v2_last_remote_check', time());
                $shouldCheck = true;
            }
        }

        return $shouldCheck;
    }

    private function validateSupabaseConfig(): ?WP_Error
    {
        if (empty($this->supabaseUrl) || empty($this->supabaseKey)) {
            fleekdash_log_error('FleekDash V2: Supabase configuration missing');
            return new WP_Error(
                'supabase_config_missing',
                'Supabase configuration is missing',
                ['status' => 500],
            );
        }
        return null;
    }

    /**
     * Call the find_site_activation RPC. Returns the raw wp_remote_post result (array|WP_Error).
     *
     * @return array|WP_Error
     */
    private function callFindSiteActivationRpc(string $siteUrl)
    {
        $siteUrlNoSlash = rtrim($siteUrl, '/');
        $siteUrlWithSlash = $siteUrlNoSlash . '/';
        fleekdash_log_debug('FleekDash V2: Also checking URLs: ' . $siteUrlNoSlash . ' and ' . $siteUrlWithSlash);

        $url = $this->supabaseUrl . '/rest/' . $this->apiVersion . '/rpc/find_site_activation';

        return \wp_remote_post($url, [
            'headers' => [
                'apikey' => $this->supabaseKey,
                'Authorization' => 'Bearer ' . $this->supabaseKey,
                'Content-Type' => 'application/json',
                'Accept' => 'application/json',
                'Prefer' => 'return=representation',
            ],
            'body' => json_encode([
                'p_site_url' => $siteUrlNoSlash,
                'p_site_url_alt' => $siteUrlWithSlash,
            ]),
            'timeout' => 30,
            'sslverify' => false,
        ]);
    }

    /**
     * Convert the wp_remote_post result of find_site_activation into either
     * activation data array or a WP_Error describing the failure.
     *
     * @param array|WP_Error $response
     * @return array|WP_Error
     */
    private function parseFindSiteActivationResponse($response)
    {
        if (\is_wp_error($response)) {
            fleekdash_log_error('FleekDash V2: Remote activation check error: ' . $response->get_error_message());
            return new WP_Error(
                'remote_activation_check_failed',
                'Failed to check remote activation: ' . $response->get_error_message(),
                ['status' => 500],
            );
        }

        $body = json_decode(\wp_remote_retrieve_body($response), true);
        $statusCode = (int) \wp_remote_retrieve_response_code($response);
        fleekdash_log_debug('FleekDash V2: Remote activation check response: ' . print_r([
            'status' => $statusCode,
            'body' => $body,
        ], true));

        $payloadError = $this->classifyFindSiteActivationPayload($statusCode, $body);
        if ($payloadError instanceof WP_Error) {
            return $payloadError;
        }

        fleekdash_log_info('FleekDash V2: Remote activation found! ' . print_r($body, true));
        return [
            'license_key' => $body['license_key'],
            'instance_id' => $body['instance_id'],
            'label' => $body['label'],
            'status' => $body['status'],
            'created_at' => $body['created_at'],
        ];
    }

    /**
     * Returns a WP_Error when the payload represents a non-success outcome
     * (HTTP non-200 or `found` flag missing/false). Returns null for valid hits.
     *
     * @param mixed $body Decoded JSON body (typically array, but can be null/scalar on bad responses).
     */
    private function classifyFindSiteActivationPayload(int $statusCode, $body): ?WP_Error
    {
        $error = null;

        if ($statusCode !== self::HTTP_OK) {
            fleekdash_log_error('FleekDash V2: Invalid response from license server: ' . $statusCode);
            $error = new WP_Error(
                'invalid_response',
                'Invalid response from license server',
                ['status' => 500],
            );
        } elseif (!\is_array($body) || empty($body['found'])) {
            fleekdash_log_debug('FleekDash V2: No remote activation found for this site');
            $error = new WP_Error(
                'no_remote_activation',
                'No remote activation found for this site',
                ['status' => 404],
            );
        }

        return $error;
    }
}
