<?php

namespace App\Models;

use App\Models\BankDetail;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;

class Loan extends Model
{
    use HasFactory;

    protected $fillable = [
        'user_id',
        'emi_card_id',
        'loan_type_id',
        'loan_details',

        'loan_number',
        'loan_amount',

        'interest_rate',
        'tenure_months',

        'processing_fee',
        'processing_fee_paid_at',
        'processing_fee_paid_by',

        'interest_amount',
        'total_payable',
        'emi_amount',

        'disbursed_amount',
        'outstanding_amount',

        'applied_at',
        'approved_at',
        'disbursed_at',

        'first_emi_date',
        'completed_at',
        'closed_at',

        'approved_by',
        'closed_by',

        'status',

        'rejection_reason',
        'admin_notes',
        'close_reason',
    ];

    protected function casts(): array
    {
        return [
            'loan_amount' => 'decimal:2',
            'interest_rate' => 'decimal:2',
            'loan_details' => 'array',

            'processing_fee' => 'decimal:2',
            'processing_fee_paid_at' => 'datetime',

            'interest_amount' => 'decimal:2',
            'total_payable' => 'decimal:2',
            'emi_amount' => 'decimal:2',

            'disbursed_amount' => 'decimal:2',
            'outstanding_amount' => 'decimal:2',

            'applied_at' => 'datetime',
            'approved_at' => 'datetime',
            'disbursed_at' => 'datetime',
            'first_emi_date' => 'date',
            'completed_at' => 'date',
            'closed_at' => 'datetime',
        ];
    }

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

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

    /**
     * Loan category/type.
     *
     * Example:
     * Digital Product Loan, Gold Loan, Personal Loan, Vehicle Loan.
     */
    public function loanType(): BelongsTo
    {
        return $this->belongsTo(
            LoanType::class,
            'loan_type_id'
        );
    }

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

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

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

    public function installments(): HasMany
    {
        return $this->hasMany(
            LoanInstallment::class
        );
    }

    /**
     * Type-specific loan information.
     *
     * Keeps loan type/details separate from the existing loans table.
     */
    public function loanDetail(): HasOne
    {
        return $this->hasOne(
            LoanDetail::class,
            'loan_id'
        );
    }

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

    public function isApproved(): bool
    {
        return $this->status === 'approved';
    }

    public function isDisbursed(): bool
    {
        return $this->status === 'disbursed';
    }

    public function isActive(): bool
    {
        return $this->status === 'active';
    }

    public function isCompleted(): bool
    {
        return $this->status === 'completed';
    }

    public function isOverdue(): bool
    {
        return $this->status === 'overdue';
    }

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

    public function isClosed(): bool
    {
        return $this->status === 'closed';
    }

    public function isRejected(): bool
    {
        return $this->status === 'rejected';
    }

    public function isProcessingFeePaid(): bool
    {
        return !is_null($this->processing_fee_paid_at);
    }

    /**
     * EMI payable amount.
     *
     * Processing fee is NOT included.
     */
    public function calculateTotalPayable(): float
    {
        return round(
            (float) $this->loan_amount
            + (float) $this->interest_amount,
            2
        );
    }

    /**
     * Calculate EMI.
     *
     * Processing fee is NOT included.
     */
    public function calculateEmiAmount(): float
    {
        if (
            !$this->tenure_months ||
            $this->tenure_months <= 0
        ) {
            return 0;
        }

        return round(
            $this->calculateTotalPayable()
            / $this->tenure_months,
            2
        );
    }

    public function calculateOutstanding(): float
    {
        $paid = (float) $this->installments()
            ->sum('paid_amount');

        return max(
            0,
            round(
                (float) $this->total_payable - $paid,
                2
            )
        );
    }
}
