<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\SoftDeletes;

class Transaction extends Model
{
    use HasFactory, SoftDeletes;

    protected $fillable = [
        'transaction_number',
        'type',
        'direction',
        'amount',
        'related_type',
        'related_id',
        'payment_method',
        'account_id',
        'category_id',
        'party_type',
        'party_id',
        'transaction_date',
        'reference_number',
        'status',
        'description',
        'notes',
        'attachments',
        'is_reconciled',
        'reconciled_date',
        'created_by',
    ];

    protected $casts = [
        'transaction_date' => 'date',
        'reconciled_date' => 'date',
        'amount' => 'decimal:2',
        'attachments' => 'array',
        'is_reconciled' => 'boolean',
    ];

    /**
     * Polymorphic relation to any related model (Order, Purchase, etc.)
     */
    public function related(): MorphTo
    {
        return $this->morphTo();
    }

    /**
     * The account this transaction belongs to
     */
    public function account(): BelongsTo
    {
        return $this->belongsTo(Account::class);
    }

    /**
     * The category of this transaction
     */
    public function category(): BelongsTo
    {
        return $this->belongsTo(TransactionCategory::class);
    }

    /**
     * User who created the transaction
     */
    public function creator(): BelongsTo
    {
        return $this->belongsTo(User::class, 'created_by');
    }

    /**
     * Get the party (customer/supplier) dynamically
     */
    public function party()
    {
        if ($this->party_type === 'customer') {
            return Customer::find($this->party_id);
        } elseif ($this->party_type === 'supplier') {
            return Supplier::find($this->party_id);
        } elseif ($this->party_type === 'employee') {
            return User::find($this->party_id);
        }
        return null;
    }

    /**
     * Scope for credits (money IN)
     */
    public function scopeCredits($query)
    {
        return $query->where('direction', 'credit');
    }

    /**
     * Scope for debits (money OUT)
     */
    public function scopeDebits($query)
    {
        return $query->where('direction', 'debit');
    }

    /**
     * Scope for completed transactions
     */
    public function scopeCompleted($query)
    {
        return $query->where('status', 'completed');
    }

    /**
     * Scope for date range
     */
    public function scopeDateRange($query, $startDate, $endDate)
    {
        return $query->whereBetween('transaction_date', [$startDate, $endDate]);
    }

    /**
     * Scope for specific account
     */
    public function scopeForAccount($query, $accountId)
    {
        return $query->where('account_id', $accountId);
    }

    /**
     * Scope for specific type
     */
    public function scopeOfType($query, $type)
    {
        return $query->where('type', $type);
    }

    /**
     * Generate next transaction number
     */
    public static function generateTransactionNumber(): string
    {
        $lastTransaction = self::latest('id')->first();
        $number = $lastTransaction ? $lastTransaction->id + 1 : 1;
        return 'TXN-' . str_pad($number, 6, '0', STR_PAD_LEFT);
    }

    /**
     * Helper: Is this a credit (money in)?
     */
    public function isCredit(): bool
    {
        return $this->direction === 'credit';
    }

    /**
     * Helper: Is this a debit (money out)?
     */
    public function isDebit(): bool
    {
        return $this->direction === 'debit';
    }

    /**
     * Boot method to auto-generate transaction number
     */
    protected static function boot()
    {
        parent::boot();

        static::creating(function ($transaction) {
            if (empty($transaction->transaction_number)) {
                $transaction->transaction_number = self::generateTransactionNumber();
            }
        });
    }
}
