<?php

namespace App\Models\Promotions;

use App\Models\Concerns\Auditable;
use App\Models\Concerns\BelongsToTenant;
use App\Models\Lookups\DiscountType;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Str;

/**
 * A cart-value ("Spend & Save") promotion: while the rule is live, any
 * checkout whose cart value meets min_cart_value automatically gets a
 * discount (percentage of the cart, or a flat amount) — capped at
 * max_discount_amount when set.
 *
 * Unlike Deals this is an ORDER-level discount, not a per-line one: it is
 * evaluated once per invoice in InvoiceService::create() against the same
 * eligible base vouchers use (net subtotal + VAT), and the applied amount is
 * snapshotted onto the invoice (cart_discount_amount / cart_discount_name)
 * so receipts can name it. When several rules are live, the highest
 * satisfied threshold wins (ties → lowest id) — see CartDiscountService.
 */
class CartDiscount extends Model
{
    use Auditable, BelongsToTenant, SoftDeletes;

    protected $fillable = [
        'uuid', 'name', 'description', 'is_active',
        'starts_at', 'ends_at', 'min_cart_value',
        'discount_type_id', 'discount_value', 'max_discount_amount',
        'created_by', 'updated_by',
    ];

    protected function casts(): array
    {
        return [
            'is_active' => 'boolean',
            'starts_at' => 'datetime',
            'ends_at' => 'datetime',
            'min_cart_value' => 'decimal:2',
            'discount_value' => 'decimal:2',
            'max_discount_amount' => 'decimal:2',
        ];
    }

    protected static function booted(): void
    {
        static::creating(function (self $rule): void {
            if (! $rule->uuid) {
                $rule->uuid = (string) Str::ulid();
            }
        });
    }

    public function discountType(): BelongsTo
    {
        return $this->belongsTo(DiscountType::class, 'discount_type_id');
    }

    /**
     * The single gate every consumer uses — the POS payload, the checkout
     * estimate and the authoritative InvoiceService evaluation all ask "is
     * this rule live right now?" through this one method: switched on AND
     * inside its validity window (inclusive on both ends, same convention as
     * ProductBundle / Deal).
     */
    public function isCurrentlyActive(): bool
    {
        if (! $this->is_active) {
            return false;
        }
        $now = now();
        if ($this->starts_at && $now->lt($this->starts_at)) {
            return false;
        }

        return ! ($this->ends_at && $now->gt($this->ends_at));
    }
}
