<?php

namespace App\Models;

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

class Transfer extends Model
{
    /**
     * The attributes that are mass assignable.
     *
     * @var array<string>
     */
    protected $fillable = [
        'user_id',
        'from_account_id',
        'to_account_id',
        'amount',
        'to_amount',
        'exchange_rate',
        'fee',
        'date',
        'time',
        'description',
        'notes',
    ];

    /**
     * The attributes that should be cast.
     *
     * @return array<string, string>
     */
    protected function casts(): array
    {
        return [
            'amount' => 'decimal:2',
            'to_amount' => 'decimal:2',
            'exchange_rate' => 'decimal:8',
            'fee' => 'decimal:2',
            'date' => 'date',
        ];
    }

    /**
     * Boot the model.
     */
    protected static function boot()
    {
        parent::boot();

        // Update account balances when transfer is created
        static::created(function ($transfer) {
            $transfer->updateAccountBalances();
        });

        // Update account balances when transfer is updated
        static::updated(function ($transfer) {
            if ($transfer->wasChanged(['amount', 'to_amount', 'fee', 'from_account_id', 'to_account_id'])) {
                // Recalculate old accounts if changed
                if ($transfer->wasChanged('from_account_id')) {
                    Account::find($transfer->getOriginal('from_account_id'))?->recalculateBalance();
                }
                if ($transfer->wasChanged('to_account_id')) {
                    Account::find($transfer->getOriginal('to_account_id'))?->recalculateBalance();
                }
                $transfer->updateAccountBalances();
            }
        });

        // Update account balances when transfer is deleted
        static::deleted(function ($transfer) {
            $transfer->fromAccount->recalculateBalance();
            $transfer->toAccount->recalculateBalance();
        });
    }

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

    /**
     * Get the source account.
     */
    public function fromAccount(): BelongsTo
    {
        return $this->belongsTo(Account::class, 'from_account_id');
    }

    /**
     * Get the destination account.
     */
    public function toAccount(): BelongsTo
    {
        return $this->belongsTo(Account::class, 'to_account_id');
    }

    /**
     * Update both account balances.
     */
    protected function updateAccountBalances(): void
    {
        $this->fromAccount->recalculateBalance();
        $this->toAccount->recalculateBalance();
    }

    /**
     * Check if this is a cross-currency transfer.
     */
    public function isCrossCurrency(): bool
    {
        return $this->fromAccount->currency_id !== $this->toAccount->currency_id;
    }

    /**
     * Get formatted amount from source account.
     */
    public function getFormattedAmountAttribute(): string
    {
        return $this->fromAccount->currency->format($this->amount);
    }

    /**
     * Get formatted amount to destination account.
     */
    public function getFormattedToAmountAttribute(): string
    {
        return $this->toAccount->currency->format($this->to_amount);
    }

    /**
     * Get formatted fee.
     */
    public function getFormattedFeeAttribute(): string
    {
        return $this->fromAccount->currency->format($this->fee);
    }

    /**
     * Get total amount deducted from source (amount + fee).
     */
    public function getTotalFromAmountAttribute(): float
    {
        return $this->amount + $this->fee;
    }

    /**
     * Calculate exchange rate from amounts.
     */
    public function calculateExchangeRate(): float
    {
        if ($this->amount <= 0) {
            return 1;
        }

        return $this->to_amount / $this->amount;
    }
}
