<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Wildside\Userstamps\Userstamps;
use Illuminate\Database\Eloquent\SoftDeletes;

class Invoice extends Model
{
    use HasFactory, Userstamps, SoftDeletes;

    protected $table = 'invoices';
    protected $guarded = [];

    protected $casts = [
        'invoice_date' => 'date',
        'due_date' => 'date',
        'paid_at' => 'datetime',
        'cancelled_at' => 'datetime',
        'room_total' => 'decimal:2',
        'services_total' => 'decimal:2',
        'subtotal' => 'decimal:2',
        'discount_amount' => 'decimal:2',
        'tax_rate' => 'decimal:2',
        'tax_amount' => 'decimal:2',
        'grand_total' => 'decimal:2',
    ];

    // Relationships
    public function metodePembayaran()
    {
        return $this->belongsTo(MetodePembayaran::class, 'metode_pembayaran_id');
    }
    public function booking()
    {
        return $this->belongsTo(Booking::class);
    }

    public function createdBy()
    {
        return $this->belongsTo(User::class, 'created_by');
    }

    // Accessors
    public function getFormattedRoomTotalAttribute()
    {
        return 'Rp ' . number_format($this->room_total, 0, ',', '.');
    }

    public function getFormattedServicesTotalAttribute()
    {
        return 'Rp ' . number_format($this->services_total, 0, ',', '.');
    }

    public function getFormattedSubtotalAttribute()
    {
        return 'Rp ' . number_format($this->subtotal, 0, ',', '.');
    }

    public function getFormattedDiscountAmountAttribute()
    {
        return 'Rp ' . number_format($this->discount_amount, 0, ',', '.');
    }

    public function getFormattedTaxAmountAttribute()
    {
        return 'Rp ' . number_format($this->tax_amount, 0, ',', '.');
    }

    public function getFormattedGrandTotalAttribute()
    {
        return 'Rp ' . number_format($this->grand_total, 0, ',', '.');
    }

    public function getInvoiceDateFormattedAttribute()
    {
        return $this->invoice_date ? $this->invoice_date->format('d/m/Y') : null;
    }

    public function getDueDateFormattedAttribute()
    {
        return $this->due_date ? $this->due_date->format('d/m/Y') : null;
    }

    public function getPaidAtFormattedAttribute()
    {
        return $this->paid_at ? $this->paid_at->format('d/m/Y H:i') : null;
    }

    public function getStatusBadgeAttribute()
    {
        switch ($this->status) {
            case 'pending':
                return '<span class="badge badge-warning">Pending</span>';
            case 'paid':
                return '<span class="badge badge-success">Paid</span>';
            case 'cancelled':
                return '<span class="badge badge-danger">Cancelled</span>';
            case 'overdue':
                return '<span class="badge badge-danger">Overdue</span>';
            default:
                return '<span class="badge badge-secondary">Unknown</span>';
        }
    }

    public function getStatusColorAttribute()
    {
        switch ($this->status) {
            case 'pending':
                return 'warning';
            case 'paid':
                return 'success';
            case 'cancelled':
                return 'danger';
            case 'overdue':
                return 'danger';
            default:
                return 'secondary';
        }
    }

    // Scopes
    public function scopePending($query)
    {
        return $query->where('status', 'pending');
    }

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

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

    public function scopeOverdue($query)
    {
        return $query->where('status', 'pending')
                    ->where('due_date', '<', now());
    }

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

    public function scopeByDateRange($query, $startDate, $endDate)
    {
        return $query->whereBetween('invoice_date', [$startDate, $endDate]);
    }

    // Methods
    public function isPaid()
    {
        return $this->status === 'paid';
    }

    public function isPending()
    {
        return $this->status === 'pending';
    }

    public function isCancelled()
    {
        return $this->status === 'cancelled';
    }

    public function isOverdue()
    {
        return $this->status === 'pending' && $this->due_date < now();
    }

    public function canBePaid()
    {
        return $this->status === 'pending';
    }

    public function canBeCancelled()
    {
        return $this->status === 'pending';
    }

    public function getDaysUntilDue()
    {
        if ($this->status !== 'pending') {
            return null;
        }

        return now()->diffInDays($this->due_date, false);
    }

    public function getDaysOverdue()
    {
        if (!$this->isOverdue()) {
            return 0;
        }

        return now()->diffInDays($this->due_date);
    }

    // Boot method to handle automatic status updates
    protected static function boot()
    {
        parent::boot();

        // Automatically update overdue status
        static::saving(function ($invoice) {
            if ($invoice->status === 'pending' && $invoice->due_date < now()) {
                $invoice->status = 'overdue';
            }
        });

    }

    // Accessors & Mutators
    public function getStatusLabelAttribute()
    {
        $labels = [
            'pending' => 'Pending',
            'paid' => 'Lunas',
            'cancelled' => 'Dibatalkan',
            'overdue' => 'Jatuh Tempo',
        ];

        return $labels[$this->status] ?? ucfirst($this->status);
    }
     public function getFormattedInvoiceDateAttribute()
    {
        return $this->invoice_date ? $this->invoice_date->format('d M Y') : '-';
    }

    public function getFormattedDueDateAttribute()
    {
        return $this->due_date ? $this->due_date->format('d M Y') : '-';
    }



    public function getIsOverdueAttribute()
    {
        return $this->due_date && $this->due_date->isPast() && $this->status === 'pending';
    }

    public static function getTotalRevenue($startDate = null, $endDate = null)
    {
        $query = static::where('status', '!=', 'cancelled');

        if ($startDate && $endDate) {
            $query->betweenDates($startDate, $endDate);
        }

        return $query->sum('grand_total');
    }
     public static function getMonthlyRevenue($year = null)
    {
        $year = $year ?? now()->year;

        return static::selectRaw('MONTH(invoice_date) as month, SUM(grand_total) as total')
                    ->whereYear('invoice_date', $year)
                    ->where('status', '!=', 'cancelled')
                    ->groupBy('month')
                    ->orderBy('month')
                    ->get();
    }


    public function scopeThisYear($query)
    {
        return $query->whereYear('invoice_date', now()->year);
    }

    public function scopeBetweenDates($query, $startDate, $endDate)
    {
        return $query->whereBetween('invoice_date', [$startDate, $endDate]);
    }

}
