<?php

namespace App\Models\Promotions;

use App\Models\Catalog\Product;
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\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Str;

/**
 * An item-level promotional engine: while a deal is active, every sale of
 * its target products gets an automatic per-line discount (percentage or
 * fixed amount), independent of any cashier-applied discount.
 *
 * This is a new feature of the Filament app (the source Inertia app has no
 * deal engine) — see docs/migration-plan.md Decisions Log entry for the
 * design decisions and the authoritative evaluation point in
 * InvoiceService::create().
 */
class Deal extends Model
{
    use Auditable, BelongsToTenant, SoftDeletes;

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

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

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

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

    public function products(): BelongsToMany
    {
        return $this->belongsToMany(Product::class, 'deal_products')->withTimestamps();
    }

    /**
     * The single gate every consumer uses — the POS product payload, the
     * checkout estimate and the authoritative InvoiceService repricing all
     * ask "is this deal live right now?" through this one method:
     * switched on AND inside its validity window (inclusive on both ends).
     */
    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));
    }
}
