<?php

namespace FleekDash\Controllers\License;

use WP_Error;

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

/**
 * License API Client
 *
 * Handles all communication with Supabase License API
 *
 * @package FleekDash\Controllers\License
 * @since 2.2.0
 */
class LicenseAPIClient
{
    private const MIME_JSON = 'application/json';

    private const UUID_PATTERN = '/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i';

    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;
    }

    /**
     * Fetch license data from Supabase
     *
     * @return array<string, mixed>|WP_Error License data or error
     */
    public function fetchLicense(string $licenseKey): array|WP_Error
    {
        fleekdash_log_debug('FleekDash V2: Attempting to fetch license: ' . $licenseKey);

        if ($this->supabaseUrl === '' || $this->supabaseKey === '') {
            fleekdash_log_debug(
                'FleekDash V2: Supabase configuration: URL=' . $this->supabaseUrl . ', Key=' . substr($this->supabaseKey, 0, 10) . '...',
            );

            return new WP_Error(
                'supabase_config_missing',
                'Supabase configuration is missing',
                ['status' => 500],
            );
        }

        $trimmedKey = trim($licenseKey);
        $formatError = $this->validateLicenseUuid($trimmedKey);
        if ($formatError !== null) {
            return $formatError;
        }

        return $this->executeVerifyLicenseRpc($trimmedKey);
    }

    /**
     * @return WP_Error|null Null when the key format is valid.
     */
    private function validateLicenseUuid(string $licenseKey): ?WP_Error
    {
        if (preg_match(self::UUID_PATTERN, $licenseKey) === 1) {
            return null;
        }

        return new WP_Error(
            'invalid_license_format',
            'Invalid license key format. Please enter a valid license key.',
            ['status' => 400],
        );
    }

    /**
     * @return array<string, mixed>|WP_Error
     */
    private function executeVerifyLicenseRpc(string $licenseKey): array|WP_Error
    {
        $url = $this->supabaseUrl . '/rest/' . $this->apiVersion . '/rpc/verify_license';
        fleekdash_log_debug('FleekDash V2: Calling verify_license function: ' . $url);

        $response = \wp_remote_post($url, [
            'headers' => [
                'apikey' => $this->supabaseKey,
                'Authorization' => 'Bearer ' . $this->supabaseKey,
                'Content-Type' => self::MIME_JSON,
                'Accept' => self::MIME_JSON,
                'Prefer' => 'return=representation',
            ],
            'body' => \wp_json_encode(['p_license_key' => $licenseKey]),
            'timeout' => 30,
            'sslverify' => false,
        ]);

        $cacheKey = 'fleekdash_v2_license_' . md5($licenseKey);

        if (\is_wp_error($response)) {
            fleekdash_log_error('FleekDash V2: License verification error: ' . $response->get_error_message());

            $cached_result = \get_transient($cacheKey);
            $has_cache = $cached_result !== false;
            if ($has_cache) {
                fleekdash_log_info('FleekDash V2: Using cached result due to connection error');

                return $cached_result;
            }

            return new WP_Error(
                'license_fetch_failed',
                'Failed to verify license: ' . $response->get_error_message(),
                ['status' => 500],
            );
        }

        return $this->buildVerifyLicenseSuccessOrError($response, $cacheKey);
    }

    /**
     * @param array<string, mixed> $response Successful wp_remote_post response
     * @return array<string, mixed>|WP_Error
     */
    private function buildVerifyLicenseSuccessOrError(array $response, string $cacheKey): array|WP_Error
    {
        $body = json_decode(\wp_remote_retrieve_body($response), true);
        $status_code = \wp_remote_retrieve_response_code($response);

        fleekdash_log_debug('FleekDash V2: License verification response: ' . print_r([
            'status' => $status_code,
            'body' => $body,
        ], true));

        $response_ok = $status_code === 200 && \is_array($body) && isset($body['valid']);
        if (!$response_ok) {
            return new WP_Error(
                'invalid_response',
                'Invalid response from license server',
                ['status' => 500],
            );
        }

        if (!$body['valid']) {
            return new WP_Error(
                'license_invalid',
                $body['message'] ?? 'License is not valid',
                ['status' => 403],
            );
        }

        $payload = [
            'valid' => true,
            'license' => $body['license'],
            'instances' => $body['instances'] ?? [],
            'message' => 'License is valid and active',
        ];
        \set_transient($cacheKey, $payload, 3600);

        return $payload;
    }

    /**
     * Fetch tier data from Supabase.
     *
     * Accepts numeric IDs and UUID-like IDs because historical datasets may
     * store deal_tier_id as string.
     *
     * @param int|string $tierId
     * @return array<string, mixed>|null Tier data or null on error
     */
    public function fetchTierData($tierId): ?array
    {
        $tier = null;

        if ($this->supabaseUrl !== '' && $this->supabaseKey !== '') {
            try {
                $tier = $this->requestTierPayload($tierId);
            } catch (\Exception $e) {
                fleekdash_log_error('FleekDash V2: Exception fetching tier data: ' . $e->getMessage());
            }
        }

        return $tier;
    }

    /**
     * @param int|string $tierId
     * @return array<string, mixed>|null
     */
    private function requestTierPayload($tierId): ?array
    {
        $url = $this->supabaseUrl . '/rest/' . $this->apiVersion . '/deal_tiers';
        $tierFilterValue = rawurlencode((string) $tierId);

        $response = \wp_remote_get($url . '?id=eq.' . $tierFilterValue . '&select=*,deals(title)', [
            'headers' => [
                'apikey' => $this->supabaseKey,
                'Authorization' => 'Bearer ' . $this->supabaseKey,
                'Accept' => self::MIME_JSON,
            ],
            'timeout' => 15,
            'sslverify' => false,
        ]);

        if (\is_wp_error($response)) {
            fleekdash_log_error('FleekDash V2: Failed to fetch tier data: ' . $response->get_error_message());

            return null;
        }

        $body = json_decode(\wp_remote_retrieve_body($response), true);

        $has_row = !empty($body) && \is_array($body) && isset($body[0]);
        if (!$has_row) {
            return null;
        }

        $tier = $body[0];

        $tier['billing_type'] = 'lifetime';
        if ($tier['billing_cycle'] == 12) {
            $tier['billing_type'] = 'annual';
        } elseif ($tier['billing_cycle'] == 1) {
            $tier['billing_type'] = 'monthly';
        } elseif ($tier['billing_cycle'] && $tier['billing_cycle'] != 12) {
            $tier['billing_type'] = $tier['billing_cycle'] . '_months';
        }

        if (isset($tier['deals']['title'])) {
            $tier['deal_title'] = $tier['deals']['title'];
        }

        fleekdash_log_info('FleekDash V2: Successfully fetched tier data: ' . print_r($tier, true));

        $tier['_cached_at'] = time();
        \update_option('fleekdash_v2_tier_data', $tier);

        return $tier;
    }
}
