<?php

use App\Mail\InvoiceMail;
use App\Models\Customer;
use App\Models\Invoice;
use App\Models\Order;
use App\Services\Billing\InvoiceRenderer;
use App\Services\Billing\IssueInvoice;
use App\Support\CompanyProfile;

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

function issuedInvoice(): Invoice
{
    $customer = Customer::factory()->create(['name' => 'Muster GmbH']);
    $orders = collect([Order::factory()->create([
        'customer_id' => $customer->id, 'amount_cents' => 1900, 'currency' => 'EUR', 'status' => 'paid',
    ])]);

    return app(IssueInvoice::class)->forOrders($customer, $orders);
}

it('attaches the invoice as a PDF named after its number', function () {
    // Filename and type only. The bytes are not asserted here and deliberately
    // not: TCPDF embeds a creation time and a document id, so two renders of
    // one invoice differ — a byte comparison would fail for a reason that has
    // nothing to do with the mail. What the renderer produces is tested where
    // the renderer is.
    $invoice = issuedInvoice();

    $attachment = (new InvoiceMail($invoice, 'Muster GmbH'))->attachments()[0];

    expect($attachment->as)->toBe($invoice->number.'.pdf')
        ->and($attachment->mime)->toBe('application/pdf');
});

it('renders a real PDF for the attachment to carry', function () {
    // The attachment is a closure, and a closure that returns nothing still
    // makes a perfectly valid mail with a nought-byte file on it. This is the
    // half that would be empty.
    $bytes = app(InvoiceRenderer::class)->forInvoice(issuedInvoice());

    expect(substr($bytes, 0, 5))->toBe('%PDF-')
        ->and(strlen($bytes))->toBeGreaterThan(10000);
});

it('renders it from the frozen document, not from today’s settings', function () {
    $invoice = issuedInvoice();

    CompanyProfile::put(['name' => 'Ein ganz anderer Name GmbH']);

    // The snapshot is what the renderer reads. The settings moved underneath
    // it and the document did not.
    expect($invoice->refresh()->snapshot['issuer']['name'])->toBe('CluPilot Cloud e.U.')
        ->and(app(InvoiceRenderer::class)->forInvoice($invoice))
        ->toBeString()->not->toBeEmpty();
});

it('names the amount and the number where somebody can read them', function () {
    // The attachment is the document; the mail still has to say what it is
    // about, because some clients only reveal an attachment once opened.
    $invoice = issuedInvoice();

    $rendered = (new InvoiceMail($invoice, 'Muster GmbH'))->render();

    expect($rendered)->toContain($invoice->number)
        ->toContain('22,80')
        ->toContain(__('mail.why_you_got_this'));
});
