<?php

namespace App\Services\Store;

use App\Jobs\SendEmailJob;
use App\Models\Client;
use App\Models\ClientProduct;
use App\Models\ClientProductTrial;
use App\Models\Product;

/**
 * Trial / deneme iş mantığının tek noktası (PRC-536).
 * Uygunluk kontrolü, trial kaydı, post-trial periyot çözümü, paid indirim.
 */
class TrialService
{
    /** Client bu üründe daha önce (free veya paid) trial kullanmadıysa true. */
    public function isEligible(?Client $client, Product $product): bool
    {
        if ($product->trial_mode === 'none') {
            return false;
        }
        if (! $client) {
            return true; // misafir — checkout'ta login + tekrar kontrol
        }

        return ! ClientProductTrial::where('client_id', $client->id)
            ->where('product_id', $product->id)
            ->exists();
    }

    /** Trial kaydı oluştur (checkout'ta çağrılır). */
    public function recordTrial(Client $client, Product $product, ClientProduct $clientProduct, string $mode): ClientProductTrial
    {
        $trial = ClientProductTrial::create([
            'client_id' => $client->id,
            'product_id' => $product->id,
            'client_product_id' => $clientProduct->id,
            'trial_mode' => $mode,
            'started_at' => now(),
            'ends_at' => $mode === 'free' ? $clientProduct->trial_ends_at : null,
            // paid trial deferred değil — indirim checkout'ta uygulanır, kayıt
            // anında 'converted'. free trial ilk ödemeye kadar 'active' kalır.
            'status' => $mode === 'paid' ? 'converted' : 'active',
        ]);

        // PRC-539 — trial_started email yalnız free trial için; paid trial
        // anında 'converted' sayılır, o ayrı event'ten bildirim alır.
        if ($mode === 'free') {
            try {
                $clientProduct->loadMissing(['product', 'client']);
                $currencyCode = $client->currency?->code ?? 'USD';
                SendEmailJob::dispatch(
                    'Trial Started',
                    'client_product',
                    $clientProduct->id,
                    [
                        'CLIENT_NAME'       => trim($client->first_name . ' ' . $client->last_name),
                        'PRODUCT_NAME'      => $product->name,
                        'TRIAL_ENDS_AT'     => $clientProduct->trial_ends_at
                            ? $clientProduct->trial_ends_at->format('Y-m-d')
                            : '—',
                        'TRIAL_DAYS'        => $product->trial_period_days ?? '—',
                        'RECURRING_AMOUNT'  => number_format((float) $clientProduct->recurring_amount, 2) . ' ' . $currencyCode,
                        'RECURRING_CYCLE'   => $clientProduct->billingcycle ?? 'monthly',
                    ]
                );
            } catch (\Throwable $e) {
                \Log::warning('PRC-539 trial_started email gönderilemedi', [
                    'client_product_id' => $clientProduct->id,
                    'error' => $e->getMessage(),
                ]);
            }
        }

        return $trial;
    }

    /** Trial sonrası geçilecek billing cycle — müşteri seçimi > ürün varsayılanı. */
    public function resolvePostTrialPeriod(Product $product, ?string $customerChoice): string
    {
        return $customerChoice
            ?: $product->trial_default_period
            ?: 'monthly';
    }

    /**
     * Paid trial: tutara tek-seferlik indirim uygulanmış halini döndürür.
     *
     * PRC-544 — $periodMonths verilirse `trial_paid_discount_periods` listesine
     * göre filtrelenir. Liste NULL ise tüm periyotlar geçerli (geri-uyumlu).
     */
    public function applyPaidTrialDiscount(Product $product, float $amount, ?int $periodMonths = null): float
    {
        if ($product->trial_mode !== 'paid' || ! $product->trial_paid_discount_percent) {
            return $amount;
        }

        if ($periodMonths !== null && ! $this->paidDiscountAppliesToPeriod($product, $periodMonths)) {
            return $amount;
        }

        // trial_paid_discount_percent 'decimal:2' cast'li → string döner;
        // (float) cast'i zorunlu, kaldırma.
        return round($amount * (1 - (float) $product->trial_paid_discount_percent / 100), 2);
    }

    /**
     * Paid trial indirimi verilen periyotta (ay cinsinden) geçerli mi?
     *
     * PRC-544 — `trial_paid_discount_periods` NULL ise tüm periyotlar geçerli
     * (geri-uyumlu); dizi ise sadece içerdiği period (int, ay) değerleri.
     */
    public function paidDiscountAppliesToPeriod(Product $product, int $periodMonths): bool
    {
        $allowedPeriods = $product->trial_paid_discount_periods;
        if ($allowedPeriods === null) {
            return true; // NULL = geri-uyumlu: tüm periyotlar
        }
        if (! is_array($allowedPeriods) || empty($allowedPeriods)) {
            return false; // boş dizi = paid trial fiilen kapalı
        }

        return in_array($periodMonths, array_map('intval', $allowedPeriods), true);
    }
}
