<?php

namespace App\Models;

use App\Traits\BelongsToVendor;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Transaction extends Model
{
    use BelongsToVendor, SoftDeletes;

    /**
     * The accessors to append to the model's array form.
     */
    protected $appends = [
        'from_customer_id',
        'to_customer_id',
        'from_customer',
        'to_customer',
    ];

    protected $fillable = [
        'vendor_id',
        'transaction_number',
        'from_user_id',
        'to_user_id',
        'order_id',
        'amount',
        'transaction_date',
        'method',
        'reference',
        'attachment',
        'status',
        'notes',
        'verified_at',
        'verified_by',
        'submitted_at',
        'submitted_by',
        'settled_at',
        'settled_by',
        'created_by',
    ];

    protected $casts = [
        'transaction_date' => 'datetime',
        'amount' => 'decimal:2',
        'verified_at' => 'datetime',
        'submitted_at' => 'datetime',
        'settled_at' => 'datetime',
    ];

    /**
     * Get the from_customer_id attribute (alias for from_user_id).
     */
    public function getFromCustomerIdAttribute(): ?int
    {
        return $this->from_user_id;
    }

    /**
     * Get the to_customer_id attribute (alias for to_user_id).
     */
    public function getToCustomerIdAttribute(): ?int
    {
        return $this->to_user_id;
    }

    /**
     * Get the from_customer attribute (alias for fromUser relationship).
     */
    public function getFromCustomerAttribute()
    {
        return $this->relationLoaded('fromUser') ? $this->fromUser : null;
    }

    /**
     * Get the to_customer attribute (alias for toUser relationship).
     */
    public function getToCustomerAttribute()
    {
        return $this->relationLoaded('toUser') ? $this->toUser : null;
    }

    /**
     * Get the user who paid (from).
     */
    public function fromUser(): BelongsTo
    {
        return $this->belongsTo(User::class, 'from_user_id');
    }

    /**
     * Get the user who received (to).
     */
    public function toUser(): BelongsTo
    {
        return $this->belongsTo(User::class, 'to_user_id');
    }

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

    /**
     * Alias for fromUser() to maintain backwards compatibility.
     */
    public function fromCustomer(): BelongsTo
    {
        return $this->fromUser();
    }

    /**
     * Alias for toUser() to maintain backwards compatibility.
     */
    public function toCustomer(): BelongsTo
    {
        return $this->toUser();
    }

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

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

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

    /**
     * Check if transaction is settled/confirmed.
     */
    public function isSettled(): bool
    {
        return in_array($this->status, ['SETTLED', 'CONFIRMED']);
    }

    /**
     * Check if transaction is submitted.
     */
    public function isSubmitted(): bool
    {
        return $this->status === 'SUBMITTED';
    }

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

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

    // ================== Query Scopes ==================

    /**
     * Scope for draft transactions.
     */
    public function scopeDraft($query)
    {
        return $query->where('status', 'DRAFT');
    }

    /**
     * Scope for submitted transactions.
     */
    public function scopeSubmitted($query)
    {
        return $query->whereIn('status', ['SUBMITTED', 'IN_PROGRESS']);
    }

    /**
     * Scope for settled/confirmed transactions.
     */
    public function scopeSettled($query)
    {
        return $query->whereIn('status', ['SETTLED', 'CONFIRMED']);
    }

    public function scopeConfirmed($query)
    {
        return $query->where('status', 'CONFIRMED');
    }

    /**
     * Scope for transactions from a user.
     */
    public function scopeFromUser($query, int $userId)
    {
        return $query->where('from_user_id', $userId);
    }

    /**
     * Scope for transactions to a user.
     */
    public function scopeToUser($query, int $userId)
    {
        return $query->where('to_user_id', $userId);
    }

    /**
     * Scope for transactions involving a user (from or to).
     */
    public function scopeInvolvingUser($query, int $userId)
    {
        return $query->where(function ($q) use ($userId) {
            $q->where('from_user_id', $userId)
              ->orWhere('to_user_id', $userId);
        });
    }

    /**
     * Scope for transactions in date range.
     */
    public function scopeDateBetween($query, string $from, string $to)
    {
        return $query->whereDate('transaction_date', '>=', $from)
                     ->whereDate('transaction_date', '<=', $to);
    }

    /**
     * Scope for transactions today.
     */
    public function scopeToday($query)
    {
        return $query->whereDate('transaction_date', today());
    }

    /**
     * Scope for transactions this month.
     */
    public function scopeThisMonth($query)
    {
        return $query->whereMonth('transaction_date', now()->month)
                     ->whereYear('transaction_date', now()->year);
    }

    /**
     * Scope for transactions with minimum amount.
     */
    public function scopeMinAmount($query, float $amount)
    {
        return $query->where('amount', '>=', $amount);
    }

    /**
     * Scope for transactions with maximum amount.
     */
    public function scopeMaxAmount($query, float $amount)
    {
        return $query->where('amount', '<=', $amount);
    }

    /**
     * Scope with users loaded.
     */
    public function scopeWithUsers($query)
    {
        return $query->with(['fromUser', 'toUser']);
    }

    /**
     * Scope with all relations loaded.
     */
    public function scopeWithDetails($query)
    {
        return $query->with(['fromUser', 'toUser', 'allocations']);
    }
}
