<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

class Invoice extends Model
{
    protected $fillable = [
        'tenant_id','period_type','period_start','period_end','due_date',
        'total_amount','paid_amount','status','issued_at','paid_at','notes',
    ];

    protected $casts = [
        'period_start' => 'date',
        'period_end'   => 'date',
        'due_date'     => 'date',
        'issued_at'    => 'datetime',
        'paid_at'      => 'datetime',
    ];

    public function tenant()
    {
        return $this->belongsTo(Tenant::class);
    }

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

    public function allocations()
    {
        return $this->hasMany(PaymentAllocation::class);
    }

    public function recalcTotals(): void
    {
        $total = (float) $this->items()->sum('amount');
        $paid  = (float) $this->allocations()->sum('amount_applied');

        $this->total_amount = $total;
        $this->paid_amount  = $paid;

        if ($this->status !== 'void') {
            if ($paid <= 0) {
                $this->status = 'unpaid';
            } elseif ($paid + 0.00001 < $total) {
                $this->status = 'partial';
            } else {
                $this->status = 'paid';
                $this->paid_at = $this->paid_at ?? now();
            }
        }
    }

    // =======================
    // SCOPES (untuk KPI)
    // =======================

    public function scopeNotVoid(Builder $q): Builder
    {
        return $q->where('status', '!=', 'void');
    }

    public function scopeUnpaidOrPartial(Builder $q): Builder
    {
        return $q->whereIn('status', ['unpaid', 'partial']);
    }

    public function scopeDueBetween(Builder $q, $start, $end): Builder
    {
        return $q->whereBetween('due_date', [$start, $end]);
    }

    public function scopeIssuedBetween(Builder $q, $start, $end): Builder
    {
        return $q->whereBetween('issued_at', [$start, $end]);
        // kalau issued_at sering null, ganti ke created_at:
        // return $q->whereBetween('created_at', [$start, $end]);
    }

    public function scopeOverdue(Builder $q): Builder
    {
        return $q->whereDate('due_date', '<', now()->toDateString())
            ->unpaidOrPartial();
    }

    public function scopePaidBetween(Builder $q, $start, $end): Builder
    {
        return $q->whereBetween('paid_at', [$start, $end])
            ->where('status', 'paid');
    }

    // agregasi untuk ->value('agg')
    public function scopeOutstandingSum(Builder $q): Builder
    {
        return $q->selectRaw('COALESCE(SUM(total_amount - paid_amount), 0) as agg');
    }

    public function scopeTotalSum(Builder $q): Builder
    {
        return $q->selectRaw('COALESCE(SUM(total_amount), 0) as agg');
    }

    public function scopePaidSum(Builder $q): Builder
    {
        return $q->selectRaw('COALESCE(SUM(paid_amount), 0) as agg');
    }
}
