<?php

namespace App\Domain\Payroll\Models;

use App\Domain\HR\Models\Employee;
use App\Domain\Payroll\Enums\LoanStatus;
use App\Support\Concerns\HasUuid;
use App\Support\Money\Money;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

/** A loan recovered through payroll (§55). */
class EmployeeLoan extends Model
{
    use HasUuid;

    protected $guarded = ['id', 'uuid'];

    protected function casts(): array
    {
        return [
            'status' => LoanStatus::class,
            'principal_amount' => 'integer',
            'installment_amount' => 'integer',
            'recovered_amount' => 'integer',
            'installment_count' => 'integer',
            'requested_on' => 'date',
            'first_deduction_on' => 'date',
            'disbursed_on' => 'date',
            'approved_at' => 'datetime',
        ];
    }

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

    public function outstanding(): Money
    {
        return Money::of(max(0, $this->principal_amount - $this->recovered_amount), $this->currency);
    }

    /**
     * What comes off this month's pay: the installment, or whatever is left if
     * that is less. Never more than the loan.
     */
    public function nextInstallment(): Money
    {
        $remaining = $this->outstanding();

        return $remaining->minorUnits < $this->installment_amount
            ? $remaining
            : Money::of((int) $this->installment_amount, $this->currency);
    }

    public function scopeRecovering(Builder $query): Builder
    {
        return $query->where('status', LoanStatus::Disbursed->value)
            ->whereColumn('recovered_amount', '<', 'principal_amount');
    }
}
