<?php

namespace Tests\Feature\Packages;

use App\Models\Package;
use App\Models\PackagePurchase;
use App\Models\Tenant;
use App\Models\TenantPackage;
use App\Services\Checkout\CheckoutAssignmentService;
use App\Services\Checkout\CheckoutSessionService;
use App\Services\Checkout\CheckoutWebhookService;
use App\Services\Coupons\CouponRedemptionService;
use App\Services\GiftVouchers\GiftVoucherService;
use App\Services\Paddle\PaddleSubscriptionService;
use Carbon\Carbon;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Mockery;
use Tests\TestCase;

class PackageSoftDeleteTest extends TestCase
{
    use RefreshDatabase;

    protected function tearDown(): void
    {
        parent::tearDown();

        Mockery::close();
        Carbon::setTestNow();
    }

    public function test_soft_deleted_package_remains_accessible_via_purchase_relations(): void
    {
        $tenant = Tenant::factory()->create();
        $package = Package::factory()->reseller()->create([
            'max_events_per_year' => 5,
        ]);

        $tenantPackage = TenantPackage::factory()
            ->for($tenant)
            ->for($package)
            ->create([
                'used_events' => 1,
                'active' => true,
            ]);

        $purchase = PackagePurchase::factory()
            ->for($tenant)
            ->for($package)
            ->create([
                'type' => 'reseller_subscription',
            ]);

        $package->delete();

        $this->assertNull(Package::find($package->id));
        $this->assertTrue(Package::onlyTrashed()->where('id', $package->id)->exists());

        $tenantPackage->refresh()->load('package');
        $this->assertNotNull($tenantPackage->package);
        $this->assertTrue($tenantPackage->package->is($package));

        $purchase->refresh()->load('package');
        $this->assertNotNull($purchase->package);
        $this->assertTrue($purchase->package->is($package));

        $tenant->refresh();
        $activePackage = $tenant->getActiveResellerPackage();
        $this->assertNotNull($activePackage);
        $this->assertTrue($activePackage->is($tenantPackage));
    }

    public function test_paddle_subscription_event_handles_soft_deleted_package(): void
    {
        $tenant = Tenant::factory()->create();
        $package = Package::factory()->reseller()->create([
            'price' => 29.00,
        ]);

        $package->delete();

        $sessionService = Mockery::mock(CheckoutSessionService::class);
        $assignmentService = Mockery::mock(CheckoutAssignmentService::class);
        $subscriptionService = Mockery::mock(PaddleSubscriptionService::class);
        $couponRedemptions = Mockery::mock(CouponRedemptionService::class);
        $giftVouchers = Mockery::mock(GiftVoucherService::class);

        $service = new CheckoutWebhookService(
            $sessionService,
            $assignmentService,
            $subscriptionService,
            $couponRedemptions,
            $giftVouchers
        );

        Carbon::setTestNow(now());

        $event = [
            'event_type' => 'subscription.updated',
            'data' => [
                'id' => 'sub_123',
                'status' => 'active',
                'custom_data' => [
                    'tenant_id' => $tenant->id,
                    'package_id' => $package->id,
                ],
                'next_billing_date' => now()->addMonth()->toIso8601String(),
                'customer_id' => 'cus_456',
            ],
        ];

        $this->assertTrue($service->handlePaddleEvent($event));

        $tenantPackage = TenantPackage::where('tenant_id', $tenant->id)
            ->where('package_id', $package->id)
            ->first();

        $this->assertNotNull($tenantPackage);
        $this->assertNotNull($tenantPackage->package);
        $this->assertTrue($tenantPackage->package->is($package));
        $this->assertSame('sub_123', $tenantPackage->paddle_subscription_id);
        $this->assertTrue($tenantPackage->active);

        $tenant->refresh();
        $this->assertSame('active', $tenant->subscription_status);
        $this->assertSame('cus_456', $tenant->paddle_customer_id);
    }
}
