<?php

namespace Modules\Order\Models;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Modules\Discount\Models\Discount;
use Modules\Loyalty\Models\LoyaltyGift;
use Modules\Order\Enums\OrderDiscountType;
use Modules\Support\Eloquent\Model;
use Modules\Support\Money;
use Modules\Voucher\Models\Voucher;

/**
 * @property int $id
 * @property-read string $name
 * @property int $order_id
 * @property-read Order $order
 * @property int|null $loyalty_gift_id
 * @property-read LoyaltyGift|null $gift
 * @property int $discountable_id
 * @property string $discountable_type
 * @property-read Discount|Voucher $discountable
 * @property OrderDiscountType $type
 * @property string $currency
 * @property float $currency_rate
 * @property Money $amount
 * @property Carbon|null $created_at
 * @property Carbon|null $updated_at
 */
class OrderDiscount extends Model
{
    /**
     * The attributes that are mass assignable.
     */
    protected $fillable = [
        "order_id",
        "discountable_id",
        "discountable_type",
        "loyalty_gift_id",
        "currency",
        "currency_rate",
        "amount",
        "type"
    ];

    /**
     * The relations to eager load on every query.
     *
     * @var array
     */
    protected $with = ['discountable'];

    /**
     * Get discountable
     *
     * @return MorphTo
     */
    public function discountable(): MorphTo
    {
        return $this->morphTo()
            ->withOutGlobalBranchPermission()
            ->withoutGlobalActive()
            ->withTrashed();
    }

    /**
     * Get order
     *
     * @return BelongsTo<Order,static>
     */
    public function order(): BelongsTo
    {
        return $this->belongsTo(Order::class);
    }

    /**
     * Get amount
     *
     * @return Attribute
     */
    public function amount(): Attribute
    {
        return Attribute::get(fn($amount) => new Money($amount, $this->currency));
    }

    /**
     * Get the order discountable name.
     *
     * @return Attribute
     */
    public function name(): Attribute
    {
        return Attribute::get(get: fn() => $this->relationLoaded('discountable')
            ? ($this->discountable_type == Voucher::class ? $this->discountable->code : $this->discountable->name)
            : 'Unknown Discount'
        );
    }

    /**
     * Get loyalty gift
     *
     * @return BelongsTo
     */
    public function gift(): BelongsTo
    {
        return $this->belongsTo(LoyaltyGift::class, 'loyalty_gift_id');
    }
}
