<?php

namespace App\Models;

use App\Models\Concerns\HasUuid;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;

/**
 * An issued invoice, frozen.
 *
 * `snapshot` holds everything the document says — issuer, customer, lines, rate,
 * totals — as it was on the day it was issued. The PDF is rendered from that and
 * never stored, so an address changed in 2028 cannot rewrite an invoice from
 * 2026. Nothing here is ever edited: a wrong invoice is corrected by issuing a
 * cancellation and a new one, which is the only lawful way to correct one.
 */
class Invoice extends Model
{
    use HasUuid;

    protected $fillable = [
        'invoice_series_id', 'customer_id', 'order_id', 'subscription_id', 'stripe_invoice_id',
        'number', 'number_year', 'number_sequence',
        'issued_on', 'due_on', 'snapshot', 'net_cents', 'tax_cents', 'gross_cents', 'currency',
        'cancels_invoice_id', 'sent_at',
    ];

    protected function casts(): array
    {
        return [
            'snapshot' => 'array',
            'issued_on' => 'date',
            'due_on' => 'date',
            'sent_at' => 'datetime',
            'net_cents' => 'integer',
            'tax_cents' => 'integer',
            'gross_cents' => 'integer',
        ];
    }

    public function series(): BelongsTo
    {
        return $this->belongsTo(InvoiceSeries::class, 'invoice_series_id');
    }

    public function customer(): BelongsTo
    {
        return $this->belongsTo(Customer::class);
    }

    public function order(): BelongsTo
    {
        return $this->belongsTo(Order::class);
    }

    /**
     * The contract this document billed a term of.
     *
     * Set on a renewal, which has no order behind it — nobody buys a month
     * rolling over. Null on a purchase, where `order` is what it is for.
     */
    public function subscription(): BelongsTo
    {
        return $this->belongsTo(Subscription::class);
    }

    /** Where this document has been copied to, and where it has not. */
    public function exports(): HasMany
    {
        return $this->hasMany(InvoiceExport::class);
    }

    /** What this document cancels, if it is a cancellation. */
    public function cancels(): BelongsTo
    {
        return $this->belongsTo(Invoice::class, 'cancels_invoice_id');
    }
}
