<?php

namespace Tests\Unit;

use App\Models\CheckoutSession;
use App\Models\Coupon;
use App\Models\CouponRedemption;
use App\Models\Package;
use App\Models\Tenant;
use App\Models\User;
use App\Services\Coupons\CouponRedemptionService;
use App\Services\GiftVouchers\GiftVoucherService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Str;
use Tests\TestCase;

class CouponRedemptionServiceTest extends TestCase
{
    use RefreshDatabase;

    public function test_records_request_context_and_fraud_snapshot(): void
    {
        config()->set('checkout.fraud.window_hours', 12);

        $tenant = Tenant::factory()->create();
        $user = User::factory()->for($tenant)->create();
        $package = Package::factory()->create([
            'price' => 120,
        ]);
        $coupon = Coupon::factory()->create([
            'code' => 'SAVE10',
            'paddle_discount_id' => 'dsc_123',
        ]);
        $coupon->packages()->attach($package);

        $session = CheckoutSession::create([
            'id' => (string) Str::uuid(),
            'user_id' => $user->id,
            'tenant_id' => $tenant->id,
            'package_id' => $package->id,
            'package_snapshot' => [
                'id' => $package->id,
                'name' => $package->name,
                'type' => $package->type,
                'price' => (float) $package->price,
                'currency' => $package->currency ?? 'EUR',
                'features' => $package->features,
                'limits' => $package->limits,
            ],
            'coupon_id' => $coupon->id,
            'coupon_code' => $coupon->code,
            'coupon_snapshot' => [
                'coupon' => [
                    'id' => $coupon->id,
                    'code' => $coupon->code,
                    'type' => $coupon->type?->value,
                ],
                'pricing' => [
                    'subtotal' => 120,
                    'discount' => 12,
                    'total' => 108,
                ],
            ],
            'status' => CheckoutSession::STATUS_PROCESSING,
            'provider' => CheckoutSession::PROVIDER_PADDLE,
            'currency' => 'EUR',
            'amount_subtotal' => 120,
            'amount_total' => 108,
            'amount_discount' => 12,
            'ip_address' => '203.0.113.10',
            'device_id' => 'device-123',
            'user_agent' => 'Mozilla/5.0',
        ]);

        $giftVouchers = $this->createMock(GiftVoucherService::class);
        $giftVouchers->expects($this->once())
            ->method('markRedeemed')
            ->with($this->callback(fn (Coupon $provided) => $provided->is($coupon)), 'txn_123');

        $service = new CouponRedemptionService($giftVouchers);
        $service->recordSuccess($session, ['id' => 'txn_123']);

        $this->assertDatabaseHas('coupon_redemptions', [
            'coupon_id' => $coupon->id,
            'checkout_session_id' => $session->id,
            'ip_address' => '203.0.113.10',
            'device_id' => 'device-123',
            'user_agent' => 'Mozilla/5.0',
            'status' => CouponRedemption::STATUS_SUCCESS,
        ]);

        $redemption = CouponRedemption::query()
            ->where('checkout_session_id', $session->id)
            ->first();

        $this->assertNotNull($redemption);
        $this->assertSame(12, $redemption->metadata['fraud']['window_hours'] ?? null);
        $this->assertSame('203.0.113.10', $redemption->metadata['fraud']['ip']['value'] ?? null);
        $this->assertSame('device-123', $redemption->metadata['fraud']['device']['value'] ?? null);
    }
}
