<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\SoftDeletes;

class Invoice extends Model
{
    use SoftDeletes;

    protected $fillable = [
        'invoice_number',
        'public_token',
        'customer_id',
        'issue_date',
        'due_date',
        'status',
        'subtotal',
        'tax_amount',
        'discount_amount',
        'discount_type',
        'total',
        'paid_amount',
        'balance',
        'currency',
        'template',
        'exchange_rate',
        'notes',
        'terms',
        'payment_method',
        'recurring_invoice_id',
        'created_by',
        'sent_at',
        'viewed_at',
    ];

    protected function casts(): array
    {
        return [
            'issue_date' => 'date',
            'due_date' => 'date',
            'subtotal' => 'decimal:2',
            'tax_amount' => 'decimal:2',
            'discount_amount' => 'decimal:2',
            'total' => 'decimal:2',
            'paid_amount' => 'decimal:2',
            'balance' => 'decimal:2',
            'exchange_rate' => 'decimal:4',
            'sent_at' => 'datetime',
            'viewed_at' => 'datetime',
        ];
    }

    /**
     * Get the customer that owns the invoice
     */
    public function customer(): BelongsTo
    {
        return $this->belongsTo(Customer::class);
    }

    /**
     * Get the user who created the invoice
     */
    public function creator(): BelongsTo
    {
        return $this->belongsTo(User::class, 'created_by');
    }

    /**
     * Get the recurring invoice if this was generated from one
     */
    public function recurringInvoice(): BelongsTo
    {
        return $this->belongsTo(RecurringInvoice::class);
    }

    /**
     * Get all items for this invoice
     */
    public function items(): HasMany
    {
        return $this->hasMany(InvoiceItem::class)->orderBy('sort_order');
    }

    /**
     * Get all payments for this invoice
     */
    public function payments(): HasMany
    {
        return $this->hasMany(Payment::class);
    }

    /**
     * Get all reminders for this invoice
     */
    public function reminders(): HasMany
    {
        return $this->hasMany(InvoiceReminder::class);
    }

    /**
     * Smart billing reminder / email notification audit log
     */
    public function reminderLogs(): HasMany
    {
        return $this->hasMany(ReminderLog::class);
    }

    /**
     * Credit notes issued against this invoice
     */
    public function creditNotes(): HasMany
    {
        return $this->hasMany(CreditNote::class);
    }

    /**
     * Get the receipt for this invoice
     */
    public function receipt(): HasOne
    {
        return $this->hasOne(Receipt::class);
    }

    /**
     * Check if invoice is overdue
     */
    public function isOverdue(): bool
    {
        return $this->due_date < now() && $this->status !== 'paid' && $this->balance > 0;
    }

    /**
     * Check if invoice is fully paid
     */
    public function isPaid(): bool
    {
        return $this->status === 'paid' || $this->balance <= 0;
    }

    /**
     * Get or generate public token for invoice
     */
    public function getPublicToken(): string
    {
        if (empty($this->public_token)) {
            $this->public_token = \Illuminate\Support\Str::random(32);
            $this->save();
        }

        return $this->public_token;
    }

    /**
     * Get public invoice URL
     */
    public function getPublicUrl(): string
    {
        $token = $this->getPublicToken();

        return route('invoice.public', ['token' => $token]);
    }
}
