<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;

class Account extends Model
{
    use SoftDeletes;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<string>
     */
    protected $fillable = [
        'user_id',
        'currency_id',
        'name',
        'type',
        'initial_balance',
        'current_balance',
        'icon',
        'color',
        'institution',
        'account_number',
        'credit_limit',
        'billing_day',
        'description',
        'include_in_total',
        'is_active',
        'sort_order',
    ];

    /**
     * The attributes that should be cast.
     *
     * @return array<string, string>
     */
    protected function casts(): array
    {
        return [
            'initial_balance' => 'decimal:2',
            'current_balance' => 'decimal:2',
            'credit_limit' => 'decimal:2',
            'include_in_total' => 'boolean',
            'is_active' => 'boolean',
        ];
    }

    /**
     * Account type labels.
     */
    public const TYPE_LABELS = [
        'cash' => 'Tunai',
        'bank' => 'Rekening Bank',
        'e_wallet' => 'E-Wallet',
        'credit_card' => 'Kartu Kredit',
        'investment' => 'Investasi',
        'loan' => 'Pinjaman',
        'other' => 'Lainnya',
    ];

    /**
     * Account type icons (default).
     */
    public const TYPE_ICONS = [
        'cash' => '💵',
        'bank' => '🏦',
        'e_wallet' => '📱',
        'credit_card' => '💳',
        'investment' => '📈',
        'loan' => '💸',
        'other' => '💰',
    ];

    /**
     * Get the user that owns this account.
     */
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    /**
     * Get the currency for this account.
     */
    public function currency(): BelongsTo
    {
        return $this->belongsTo(Currency::class);
    }

    /**
     * Get transactions for this account.
     */
    public function transactions(): HasMany
    {
        return $this->hasMany(Transaction::class);
    }

    /**
     * Get transfers from this account.
     */
    public function transfersOut(): HasMany
    {
        return $this->hasMany(Transfer::class, 'from_account_id');
    }

    /**
     * Get transfers to this account.
     */
    public function transfersIn(): HasMany
    {
        return $this->hasMany(Transfer::class, 'to_account_id');
    }

    /**
     * Get recurring transactions for this account.
     */
    public function recurringTransactions(): HasMany
    {
        return $this->hasMany(RecurringTransaction::class);
    }

    /**
     * Scope to get active accounts.
     */
    public function scopeActive($query)
    {
        return $query->where('is_active', true);
    }

    /**
     * Scope to get accounts included in total.
     */
    public function scopeIncludedInTotal($query)
    {
        return $query->where('include_in_total', true);
    }

    /**
     * Scope to get accounts by type.
     */
    public function scopeOfType($query, string $type)
    {
        return $query->where('type', $type);
    }

    /**
     * Get the type label.
     */
    public function getTypeLabelAttribute(): string
    {
        return self::TYPE_LABELS[$this->type] ?? $this->type;
    }

    /**
     * Get the default icon for this account type.
     */
    public function getDefaultIconAttribute(): string
    {
        return self::TYPE_ICONS[$this->type] ?? '💰';
    }

    /**
     * Get the display icon (custom or default).
     */
    public function getDisplayIconAttribute(): string
    {
        return $this->icon ?? $this->default_icon;
    }

    /**
     * Recalculate the current balance based on transactions.
     */
    public function recalculateBalance(): void
    {
        $income = $this->transactions()->where('type', 'income')->sum('amount');
        $expense = $this->transactions()->where('type', 'expense')->sum('amount');
        $transfersIn = $this->transfersIn()->sum('to_amount');
        $transfersOut = $this->transfersOut()->sum('amount');

        $this->current_balance = $this->initial_balance + $income - $expense + $transfersIn - $transfersOut;
        $this->save();
    }

    /**
     * Format the current balance with currency.
     */
    public function getFormattedBalanceAttribute(): string
    {
        return $this->currency->format($this->current_balance);
    }

    /**
     * Check if this is a credit card.
     */
    public function isCreditCard(): bool
    {
        return $this->type === 'credit_card';
    }

    /**
     * Get available credit for credit cards.
     */
    public function getAvailableCreditAttribute(): ?float
    {
        if (!$this->isCreditCard() || !$this->credit_limit) {
            return null;
        }

        return $this->credit_limit + $this->current_balance; // balance is negative for credit used
    }
}
