<?php

use App\Livewire\Admin\Invoices;
use App\Models\Customer;
use App\Models\Invoice;
use App\Models\Order;
use App\Models\User;
use App\Services\Billing\IssueInvoice;
use App\Support\CompanyProfile;
use Livewire\Livewire;

beforeEach(function () {
    CompanyProfile::put([
        'name' => 'CluPilot Cloud e.U.', 'address' => 'Dreherstraße 66/1/8',
        'postcode' => '1110', 'city' => 'Wien', 'vat_id' => 'ATU00000000',
    ]);
});

function invoiceFor(string $customerName): Invoice
{
    $customer = Customer::factory()->create(['name' => $customerName]);

    return app(IssueInvoice::class)->forOrders($customer, collect([
        Order::factory()->create(['customer_id' => $customer->id, 'amount_cents' => 1900, 'currency' => 'EUR', 'status' => 'paid']),
    ]));
}

it('lists issued invoices with no way to edit or delete one', function () {
    // The absence is the feature. A wrong invoice is corrected by cancelling it
    // and issuing another, which is the only lawful way to correct one — so
    // there is no button here whose absence needs explaining.
    $invoice = invoiceFor('Muster GmbH');

    Livewire::actingAs(operator('Owner'), 'operator')
        ->test(Invoices::class)
        ->assertSee($invoice->number)
        ->assertSee('Muster GmbH')
        ->assertDontSee(__('datacenters.edit'))
        ->assertDontSee(__('datacenters.delete'));
});

it('finds an invoice by its number and by the customer on it', function () {
    invoiceFor('Muster GmbH');
    $other = invoiceFor('Andere AG');

    Livewire::actingAs(operator('Owner'), 'operator')
        ->test(Invoices::class)
        ->set('search', 'Andere')
        ->assertSee($other->number)
        ->assertDontSee('Muster GmbH');
});

it('serves the PDF from the frozen document', function () {
    $invoice = invoiceFor('Muster GmbH');

    $response = $this->actingAs(operator('Owner'), 'operator')
        ->get(route('admin.invoices.pdf', $invoice->uuid));

    $response->assertOk()
        ->assertHeader('content-type', 'application/pdf');

    expect(substr($response->streamedContent(), 0, 5))->toBe('%PDF-');
});

it('does not hand the PDF to an operator without the capability', function () {
    $invoice = invoiceFor('Muster GmbH');

    $this->actingAs(operator('Support'), 'operator')
        ->get(route('admin.invoices.pdf', $invoice->uuid))
        ->assertForbidden();
});

it('does not hand the PDF to a customer', function () {
    // Its own test, and the guard named explicitly. Both matter: actingAs()
    // calls Auth::shouldUse(), so a second actingAs() in the same test with no
    // guard lands on whichever guard the FIRST one named — putting a User on
    // the operator guard, where EnsureAdmin calls isActive() on it and the
    // 403 becomes a 500. The trap is written up in CLAUDE.md and I walked into
    // it anyway.
    $invoice = invoiceFor('Muster GmbH');

    $this->actingAs(User::factory()->create(), 'web')
        ->get(route('admin.invoices.pdf', $invoice->uuid))
        ->assertForbidden();
});
