<?php

namespace App\Domain\Accounting\Models;

use App\Domain\Agents\Models\Agent;
use App\Domain\Applicants\Models\Applicant;
use App\Support\Concerns\HasUuid;
use App\Support\Money\Money;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use RuntimeException;

/** One side of a journal entry (§34). */
class JournalLine extends Model
{
    use HasUuid;

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

    protected function casts(): array
    {
        return [
            'debit' => 'integer',
            'credit' => 'integer',
        ];
    }

    protected static function booted(): void
    {
        static::saving(function (self $line) {
            // A line that is both, or neither, is not a bookkeeping entry.
            if (($line->debit > 0) === ($line->credit > 0)) {
                throw new RuntimeException('A journal line must be either a debit or a credit, not both.');
            }
        });
    }

    public function entry(): BelongsTo
    {
        return $this->belongsTo(JournalEntry::class, 'journal_entry_id');
    }

    public function account(): BelongsTo
    {
        return $this->belongsTo(LedgerAccount::class, 'ledger_account_id');
    }

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

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

    public function amount(): Money
    {
        return Money::of($this->debit > 0 ? $this->debit : $this->credit, $this->currency);
    }

    public function isDebit(): bool
    {
        return $this->debit > 0;
    }
}
