<?php

use App\Livewire\Billing;
use App\Models\Customer;
use App\Models\Instance;
use App\Models\Order;
use App\Models\User;
use Livewire\Livewire;

function billingSetup(string $plan = 'start'): array
{
    $user = User::factory()->create(['email' => 'k@billing.test', 'is_admin' => false]);
    $customer = Customer::factory()->create(['email' => 'k@billing.test']);
    $order = Order::factory()->create(['customer_id' => $customer->id, 'plan' => $plan]);
    Instance::factory()->create(['customer_id' => $customer->id, 'order_id' => $order->id, 'plan' => $plan, 'status' => 'active']);

    // Several of these tests call Billing::purchase(), which since Task 5
    // refuses outright without a Stripe key for the active mode.
    withStripeSecret();

    return compact('user', 'customer');
}

it('gates billing to authenticated users', function () {
    $this->get(route('billing'))->assertRedirect('/login');
});

it('shows the current plan and offers upgrades', function () {
    ['user' => $user] = billingSetup('start');

    Livewire::actingAs($user)->test(Billing::class)
        ->assertSee(__('billing.plan.start'))
        ->assertSee(__('billing.plan.team'))       // upgrade card
        ->assertSee(__('billing.storage_title'));
});

it('records an upgrade purchase intent', function () {
    ['user' => $user, 'customer' => $customer] = billingSetup('start');

    Livewire::actingAs($user)->test(Billing::class)->call('purchase', 'upgrade', 'team');

    $order = Order::query()->where('customer_id', $customer->id)->where('type', 'upgrade')->first();
    expect($order)->not->toBeNull()
        ->and($order->plan)->toBe('team')
        ->and($order->status)->toBe('pending')
        ->and($order->amount_cents)->toBe(7900);
});

it('records a storage and an addon purchase intent', function () {
    ['user' => $user, 'customer' => $customer] = billingSetup('start');

    Livewire::actingAs($user)->test(Billing::class)->call('purchase', 'storage');
    Livewire::actingAs($user)->test(Billing::class)->call('purchase', 'addon', 'priority_support');

    expect(Order::query()->where('customer_id', $customer->id)->where('type', 'storage')->exists())->toBeTrue();
    $addon = Order::query()->where('customer_id', $customer->id)->where('type', 'addon')->first();
    expect($addon?->addon_key)->toBe('priority_support');
});

it('rejects a downgrade disguised as an upgrade', function () {
    ['user' => $user, 'customer' => $customer] = billingSetup('business');

    Livewire::actingAs($user)->test(Billing::class)->call('purchase', 'upgrade', 'start');

    expect(Order::query()->where('customer_id', $customer->id)->where('type', 'upgrade')->exists())->toBeFalse();
});

it('rejects an unknown addon key', function () {
    ['user' => $user, 'customer' => $customer] = billingSetup('start');

    Livewire::actingAs($user)->test(Billing::class)->call('purchase', 'addon', 'ghost');

    expect(Order::query()->where('customer_id', $customer->id)->where('type', 'addon')->exists())->toBeFalse();
});
