<?php

use App\Livewire\Admin\Customers;
use App\Models\Customer;
use App\Models\Host;
use App\Models\Instance;
use App\Models\Operator;
use App\Models\PlanFamily;
use App\Models\Subscription;
use App\Models\User;
use Livewire\Livewire;

/**
 * The console reports what customers actually pay. Their contract is the only
 * thing that knows it — the catalogue describes what we would sell someone new.
 */
function customerOnPlan(string $plan, string $term = 'monthly'): Customer
{
    $customer = Customer::factory()->create();
    $instance = Instance::factory()->create([
        'customer_id' => $customer->id,
        'host_id' => Host::factory()->active()->create()->id,
        'plan' => $plan,
        'status' => 'active',
    ]);
    Subscription::factory()->plan($plan, $term)->create([
        'customer_id' => $customer->id,
        'instance_id' => $instance->id,
    ]);

    return $customer;
}

/** The console row for one customer — the factories leave others lying around. */
function mrrOf(Customer $customer): string
{
    $admin = Operator::factory()->role()->create();
    $rows = Livewire::actingAs($admin, 'operator')->test(Customers::class)->viewData('rows');

    return collect($rows)->firstWhere('uuid', $customer->uuid)['mrr'];
}

it('reports a yearly contract as what it costs per month', function () {
    $customer = customerOnPlan('team', 'yearly');

    // The contract stores 10 × 79 € — ten paid months for a year. Reporting the
    // whole of it in a monthly column would show this customer as worth twelve
    // times what they are.
    expect(mrrOf($customer))->toContain('65,83')
        ->and(mrrOf($customer))->not->toContain('790,00');
});

it('reports what a grandfathered customer pays, not today\'s price', function () {
    $customer = customerOnPlan('team');
    Subscription::query()->where('customer_id', $customer->id)->update(['price_cents' => 9900]);

    expect(mrrOf($customer))->toContain('99,00');
});

it('shows a yearly customer their monthly rate on the portal too', function () {
    $customer = customerOnPlan('team', 'yearly');
    $user = User::factory()->create(['email' => $customer->email]);

    // Both pages label the figure per month, and the contract holds a year.
    $card = Livewire::actingAs($user)->test(App\Livewire\Billing::class)->viewData('current');
    $cloud = Livewire::actingAs($user)->test(App\Livewire\Cloud::class)->viewData('instance');

    // 790,00 € im Jahr sind 65,83 € im Monat — die Wolkenseite rundet das auf
    // ganze Euro, die Karte nennt die Cents. '66' allein ist eine zweistellige
    // Teilzeichenkette, die im Lauf einer Suite auch eine ID trifft; mit dem
    // Einheitenzeichen davor ist sie eindeutig, wie schon '65,83' oben.
    expect($card['price_cents'])->toBe(6583)
        ->and($cloud['plan'])->toContain('66 €/Monat')
        ->and($cloud['plan'])->not->toContain('790');
});

it('keeps customers on a withdrawn plan in the distribution', function () {
    customerOnPlan('team');
    PlanFamily::query()->where('key', 'team')->update(['sales_enabled' => false]);

    $admin = Operator::factory()->role()->create();
    $chart = Livewire::actingAs($admin, 'operator')->test(Customers::class)->viewData('plansChart');

    // They are still running, still paying, and still ours to count.
    expect($chart['data']['labels'])->toContain(__('billing.plan.team'));
});
