<?php

declare(strict_types=1);

namespace Tests\Feature;

use App\Blog\Services\MarketPurchaseService;
use App\Models\MarketPackage;
use App\Models\Setting;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Plugins\Neatstudio\Payment\Models\Payment;
use RuntimeException;
use Tests\TestCase;

class MarketPurchaseTest extends TestCase
{
    use RefreshDatabase;

    private User $user;

    private array $item = [
        'name' => 'vendor.demo',
        'type' => 'plugin',
        'title' => '演示付费插件',
        'description' => '演示',
        'version' => '1.0.0',
        'price' => 9900,
        'download_url' => 'https://example.com/vendor.demo.zip',
    ];

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

        $this->seed();
        Setting::set('pay_sandbox', '1');

        $this->user = User::create([
            'name' => '买家',
            'email' => 'buyer@test.com',
            'password' => bcrypt('password'),
        ]);
    }

    private function service(): MarketPurchaseService
    {
        return app(MarketPurchaseService::class);
    }

    public function test_purchase_creates_order_with_payable_package(): void
    {
        $this->actingAs($this->user);

        $payment = $this->service()->purchase($this->item);

        $this->assertNotNull($payment);
        $this->assertInstanceOf(MarketPackage::class, $payment->payable);
        $this->assertSame('pending', $payment->payable->status);
        $this->assertSame(9900, $payment->amount);
        $this->assertSame('市场商品：演示付费插件', $payment->payable_label);
    }

    public function test_sandbox_payment_marks_package_paid(): void
    {
        $this->actingAs($this->user);

        $payment = $this->service()->purchase($this->item);
        $this->actingAs($this->user)->post('/pay/sandbox/'.$payment->order_no.'/confirm');

        $package = MarketPackage::query()->first();
        $this->assertTrue($package->isPaid());
        $this->assertSame($payment->id, $package->payment_id);
        $this->assertTrue($this->service()->isPurchased('vendor.demo', 'plugin'));
    }

    public function test_purchase_returns_null_when_already_paid(): void
    {
        $this->actingAs($this->user);

        $this->service()->purchase($this->item);
        $package = MarketPackage::query()->first();
        $package->markPaid($package->payment ?? Payment::first() ?? Payment::create([
            'order_no' => 'X'.uniqid(),
            'user_id' => $this->user->id,
            'subject' => '占位',
            'amount' => 0,
            'status' => 'paid',
            'paid_at' => now(),
        ]));

        $this->assertNull($this->service()->purchase($this->item));
    }

    public function test_assert_can_install_blocks_unpaid_paid_item(): void
    {
        $this->actingAs($this->user);

        $this->expectException(RuntimeException::class);
        $this->service()->assertCanInstall($this->item);
    }

    public function test_free_item_needs_no_purchase(): void
    {
        $this->actingAs($this->user);

        $free = ['name' => 'vendor.free', 'type' => 'plugin', 'title' => '免费插件', 'price' => 0];

        $this->assertFalse($this->service()->requiresPayment($free));
        $this->service()->assertCanInstall($free); // 不抛异常

        $this->assertTrue(true);
    }

    public function test_purchase_requires_payment_plugin(): void
    {
        $this->actingAs($this->user);

        app(\App\Blog\Support\PluginManager::class)->disable('neatstudio.membership');
        app(\App\Blog\Support\PluginManager::class)->disable('neatstudio.payment');

        $this->expectException(RuntimeException::class);
        $this->service()->purchase($this->item);
    }
}
