<?php

namespace Modules\Accounts\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use App\Models\User;
use Illuminate\Database\Eloquent\Builder;
use Modules\Accounts\Models\Traits\HasAccountingPeriod;
use Modules\Accounts\Models\Traits\HasFiscalYear;
use Modules\Billing\Models\Traits\HasBillingPayments;
use Modules\Core\Traits\AuditableTrait;
use Modules\Employee\Models\Project;

class AccountVoucher extends Model
{
    use HasBillingPayments,
        HasFiscalYear,
        HasAccountingPeriod,
        AuditableTrait;

    protected $fillable = [
        'fiscal_year_id',
        'accounting_period_id',
        'voucher_no',
        'voucher_date',
        'voucher_type',
        'project_id',
        'reference',
        'reference_type',
        'reference_id',
        'is_posted',
        'status',
        'reversed_from',
        'is_reversal',
        'posted_by',
        'posted_at',
        'created_by',
        'updated_by',
    ];

    protected function casts(): array
    {
        return [
            'voucher_date' => 'date',
            'project_id' => 'integer',
            'reversed_from' => 'integer',
            'is_reversal' => 'boolean',
            'is_posted' => 'boolean',
            'posted_by' => 'integer',
            'posted_at' => 'datetime',
            'created_by' => 'integer',
        ];
    }

    public function lines(): HasMany
    {
        return $this->hasMany(AccountVoucherLine::class, 'voucher_id')->orderBy('sl_no')->orderBy('id');
    }

    public function transactions(): HasMany
    {
        return $this->hasMany(AccountTransaction::class, 'voucher_id');
    }

    public function project(): BelongsTo
    {
        return $this->belongsTo(Project::class, 'project_id');
    }

    public function reversalOf(): BelongsTo
    {
        return $this->belongsTo(self::class, 'reversed_from');
    }

    public function reversals(): HasMany
    {
        return $this->hasMany(self::class, 'reversed_from');
    }

    public function postedBy(): BelongsTo
    {
        return $this->belongsTo(User::class, 'posted_by');
    }

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

    public function scopeStatus(Builder $query, null $status): Builder
    {
        if ($status === null) {
            return $query;
        }

        return $query->where('status', $status);
    }
}
