<?php

namespace Licenzo\Modules\EDD;

use Licenzo\Helper\Settings;
use Licenzo\Model\Product;
use Licenzo\Model\ProductVariation;
use Licenzo\Services\Integrations\ProviderAliasService;

if (!defined('ABSPATH')) {
    exit;
}

class EddStripeCompatibilityService
{
    /**
     * @var array<string,bool>
     */
    private $recurringProductCache = [];

    public function register(): void
    {
        if (!$this->isEddStripeAvailable()) {
            return;
        }

        add_filter('edds_create_payment_intent_args', [$this, 'forceSetupFutureUsage'], 20, 2);
    }

    /**
     * Force setup_future_usage=off_session when checkout contains a recurring Licenzo product.
     */
    public function forceSetupFutureUsage(array $intentArgs, $eddPaymentData): array
    {
        if (!$this->isStripeAutoRenewEnabled()) {
            return $intentArgs;
        }

        if (!$this->paymentDataHasRecurringLicenzoProduct($eddPaymentData)) {
            return $intentArgs;
        }

        $intentArgs['setup_future_usage'] = 'off_session';

        $intentArgs['metadata'] = isset($intentArgs['metadata']) && is_array($intentArgs['metadata'])
            ? $intentArgs['metadata']
            : [];
        $intentArgs['metadata']['licenzo_subscription'] = '1';
        $intentArgs['metadata']['save_payment_method'] = 'true';

        return $intentArgs;
    }

    public function paymentDataHasRecurringLicenzoProduct($paymentData): bool
    {
        $downloads = is_array($paymentData) ? ($paymentData['downloads'] ?? []) : [];
        if (!is_array($downloads)) {
            return false;
        }

        foreach ($downloads as $download) {
            $downloadId = (int) ($download['id'] ?? 0);
            $priceId = isset($download['options']['price_id']) ? (int) $download['options']['price_id'] : null;

            if ($this->isRecurringMappedProduct($downloadId, $priceId)) {
                return true;
            }
        }

        return false;
    }

    public function isRecurringMappedProductInLicenzo(int $downloadId, ?int $priceId): bool
    {
        return $this->isRecurringMappedProduct($downloadId, $priceId);
    }

    public function cartHasRecurringLicenzoSubscriptionItems(): bool
    {
        $cart = edd_get_cart_contents() ?: [];

        if (!is_array($cart)) {
            return false;
        }

        foreach ($cart as $cartItem) {
            $downloadId = (int) ($cartItem['id'] ?? 0);
            $priceId = isset($cartItem['options']['price_id']) ? (int) $cartItem['options']['price_id'] : null;

            if ($this->isRecurringMappedProduct($downloadId, $priceId)) {
                return true;
            }
        }

        return false;
    }

    private function isRecurringMappedProduct(int $downloadId, ?int $priceId): bool
    {
        if ($downloadId <= 0) {
            return false;
        }

        $cacheKey = $downloadId . ':' . ($priceId ?? 'null');
        if (array_key_exists($cacheKey, $this->recurringProductCache)) {
            return $this->recurringProductCache[$cacheKey];
        }

        $mapped = Product::whereIn('provider', ProviderAliasService::eddAliases())
            ->where(function ($q) use ($downloadId, $priceId) {
                $q->where('provider_id', (string) $downloadId);
                if ($priceId !== null) {
                    $q->orWhereHas('variations', function ($vq) use ($priceId) {
                        $vq->where('provider_id', (string) $priceId);
                    });
                }
            })
            ->with('variations')
            ->first();

        if (!$mapped) {
            return $this->recurringProductCache[$cacheKey] = false;
        }

        $variation = $priceId !== null
            ? $mapped->variations->firstWhere('provider_id', (string) $priceId)
            : $mapped->variations->first();

        if (!$variation) {
            return $this->recurringProductCache[$cacheKey] = false;
        }

        $cycle = $variation->billing_cycle ?? null;

        return $this->recurringProductCache[$cacheKey] = $this->isRecurringCycle($cycle);
    }

    private function isRecurringCycle(?string $cycle): bool
    {
        $nonRecurringCycles = [ProductVariation::PRICE_CYCLE_ONETIME, ProductVariation::PRICE_CYCLE_LIFETIME, ''];
        return !in_array((string) $cycle, $nonRecurringCycles, true);
    }

    private function isEddStripeAvailable(): bool
    {
        return defined('EDD_STRIPE_VERSION') || class_exists('EDD_Stripe');
    }

    private function isStripeAutoRenewEnabled(): bool
    {
        $settings = Settings::getSubscriptionSettings();
        return (($settings['stripe_auto_renew'] ?? 'yes') === 'yes');
    }
}
