<?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\SoftDeletes;
use Illuminate\Support\Str;

class GiftVoucher extends Model
{
    /** @use HasFactory<\Database\Factories\GiftVoucherFactory> */
    use HasFactory;

    use SoftDeletes;

    public const STATUS_ISSUED = 'issued';

    public const STATUS_REDEEMED = 'redeemed';

    public const STATUS_REFUNDED = 'refunded';

    public const STATUS_EXPIRED = 'expired';

    protected $fillable = [
        'code',
        'amount',
        'currency',
        'status',
        'purchaser_email',
        'recipient_email',
        'recipient_name',
        'message',
        'paddle_transaction_id',
        'paddle_checkout_id',
        'paddle_price_id',
        'coupon_id',
        'expires_at',
        'redeemed_at',
        'refunded_at',
        'recipient_delivery_scheduled_at',
        'recipient_delivery_sent_at',
        'metadata',
    ];

    protected $casts = [
        'amount' => 'decimal:2',
        'expires_at' => 'datetime',
        'redeemed_at' => 'datetime',
        'refunded_at' => 'datetime',
        'recipient_delivery_scheduled_at' => 'datetime',
        'recipient_delivery_sent_at' => 'datetime',
        'metadata' => 'array',
    ];

    protected static function booted(): void
    {
        static::saving(function (self $voucher): void {
            if ($voucher->code) {
                $voucher->code = Str::upper($voucher->code);
            }

            if ($voucher->currency) {
                $voucher->currency = Str::upper($voucher->currency);
            }
        });
    }

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

    public function isRedeemed(): bool
    {
        return $this->status === self::STATUS_REDEEMED;
    }

    public function isRefunded(): bool
    {
        return $this->status === self::STATUS_REFUNDED;
    }

    public function isExpired(): bool
    {
        return $this->status === self::STATUS_EXPIRED || ($this->expires_at && $this->expires_at->isPast());
    }

    public function canBeRedeemed(): bool
    {
        return ! $this->isRedeemed() && ! $this->isRefunded() && ! $this->isExpired();
    }

    public function canBeRefunded(): bool
    {
        return ! $this->isRedeemed() && ! $this->isRefunded();
    }
}
