<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
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\Support\Str;

class Invoice extends Model
{
    use HasFactory;

    protected $fillable = [
        'user_id',
        'client_id',
        'invoice_number',
        'status',
        'issue_date',
        'due_date',
        'subtotal',
        'vat_rate',
        'vat_amount',
        'discount',
        'total',
        'notes',
        'public_token',
        'sent_at',
        'viewed_at',
        'paid_at',
    ];

    protected function casts(): array
    {
        return [
            'issue_date'  => 'date',
            'due_date'    => 'date',
            'sent_at'     => 'datetime',
            'viewed_at'   => 'datetime',
            'paid_at'     => 'datetime',
            'subtotal'    => 'decimal:2',
            'vat_rate'    => 'decimal:2',
            'vat_amount'  => 'decimal:2',
            'discount'    => 'decimal:2',
            'total'       => 'decimal:2',
        ];
    }

    // ─────────────────────────────────────────
    // BOOT — auto-generate public_token
    // ─────────────────────────────────────────

    protected static function boot(): void
    {
        parent::boot();

        static::creating(function (Invoice $invoice) {
            if (empty($invoice->public_token)) {
                $invoice->public_token = Str::random(48);
            }
        });
    }

    // ─────────────────────────────────────────
    // RELATIONSHIPS
    // ─────────────────────────────────────────

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

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

    public function items(): HasMany
    {
        return $this->hasMany(InvoiceItem::class)->orderBy('sort_order');
    }

    public function payment(): HasOne
    {
        return $this->hasOne(Payment::class)->latestOfMany();
    }

    public function payments(): HasMany
    {
        return $this->hasMany(Payment::class);
    }

    public function reminders(): HasMany
    {
        return $this->hasMany(Reminder::class);
    }

    // ─────────────────────────────────────────
    // SCOPES
    // ─────────────────────────────────────────

    public function scopeDraft($query)
    {
        return $query->where('status', 'draft');
    }

    public function scopeSent($query)
    {
        return $query->where('status', 'sent');
    }

    public function scopePaid($query)
    {
        return $query->where('status', 'paid');
    }

    public function scopeOverdue($query)
    {
        return $query->where('status', 'overdue');
    }

    public function scopeUnpaid($query)
    {
        return $query->whereIn('status', ['sent', 'viewed', 'overdue']);
    }

    public function scopeThisMonth($query)
    {
        return $query->whereYear('created_at', now()->year)
                     ->whereMonth('created_at', now()->month);
    }

    // ─────────────────────────────────────────
    // STATUS HELPERS
    // ─────────────────────────────────────────

    public function isDraft(): bool   { return $this->status === 'draft'; }
    public function isSent(): bool    { return $this->status === 'sent'; }
    public function isViewed(): bool  { return $this->status === 'viewed'; }
    public function isPaid(): bool    { return $this->status === 'paid'; }
    public function isOverdue(): bool { return $this->status === 'overdue'; }
    public function isCancelled(): bool { return $this->status === 'cancelled'; }

    public function isEditable(): bool
    {
        return $this->status === 'draft';
    }

    public function canBeSent(): bool
    {
        return in_array($this->status, ['draft', 'sent', 'viewed', 'overdue']);
    }

    public function canBeMarkedPaid(): bool
    {
        return in_array($this->status, ['sent', 'viewed', 'overdue']);
    }

    // ─────────────────────────────────────────
    // STATUS BADGE (Bootstrap class + label)
    // ─────────────────────────────────────────

    public function getStatusBadgeAttribute(): array
    {
        return match ($this->status) {
            'draft'     => ['class' => 'secondary', 'label' => 'Draft'],
            'sent'      => ['class' => 'primary',   'label' => 'Sent'],
            'viewed'    => ['class' => 'info',       'label' => 'Viewed'],
            'paid'      => ['class' => 'success',    'label' => 'Paid'],
            'overdue'   => ['class' => 'danger',     'label' => 'Overdue'],
            'cancelled' => ['class' => 'dark',       'label' => 'Cancelled'],
            default     => ['class' => 'secondary',  'label' => ucfirst($this->status)],
        };
    }

    // ─────────────────────────────────────────
    // FINANCIAL HELPERS
    // ─────────────────────────────────────────

    /**
     * Recalculate subtotal, VAT, and total from line items.
     * Call this after saving/updating invoice items.
     */
    public function recalculate(): void
    {
        $subtotal   = $this->items()->sum(\DB::raw('quantity * unit_price'));
        $vatAmount  = round($subtotal * ($this->vat_rate / 100), 2);
        $total      = $subtotal + $vatAmount - (float) $this->discount;

        $this->update([
            'subtotal'   => $subtotal,
            'vat_amount' => $vatAmount,
            'total'      => max(0, $total),
        ]);
    }

    // ─────────────────────────────────────────
    // URL HELPERS
    // ─────────────────────────────────────────

    public function getPublicUrlAttribute(): string
    {
        return route('invoices.public', ['token' => $this->public_token]);
    }
}
