<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Support\Facades\Cache;
use App\Traits\Auditable;

class Receta extends Model
{
    use Auditable;

    protected $fillable = [
        'nombre', 'porciones', 'costo_esperado',
        'preparacion', 'activa', 'user_id',
    ];

    protected function casts(): array
    {
        return [
            'costo_esperado' => 'decimal:2',
            'activa'         => 'boolean',
        ];
    }

    // ─── Relaciones ───────────────────────────────────────────────

    public function creadaPor(): BelongsTo
    {
        return $this->belongsTo(User::class, 'user_id');
    }

    public function ingredientes(): HasMany
    {
        return $this->hasMany(RecetaIngrediente::class);
    }

    public function ingredientesPrincipales(): HasMany
    {
        return $this->hasMany(RecetaIngrediente::class)->where('tipo', 'principal');
    }

    public function ingredientesAccesorios(): HasMany
    {
        return $this->hasMany(RecetaIngrediente::class)->where('tipo', 'accesorio');
    }

    public function nutricion(): HasOne
    {
        return $this->hasOne(RecetaNutricion::class);
    }

    public function programaciones(): HasMany
    {
        return $this->hasMany(ProgramacionPlato::class);
    }

    // ─── Accessors calculados ─────────────────────────────────────

    /**
     * Costo real total de la receta (suma cantidad × costo_unitario de cada ingrediente).
     * Se cachea 1 hora y se invalida cuando un insumo cambia de precio.
     */
    protected function costoReal(): Attribute
    {
        return Attribute::make(
            get: function () {
                return Cache::remember("receta_costo_{$this->id}", 3600, function () {
                    return $this->ingredientes->sum(
                        fn($i) => $i->cantidad * ($i->insumo?->getCostoPorUso() ?? 0)
                    );
                });
            }
        );
    }

    /** Costo real por porción */
    protected function costoRealPorcion(): Attribute
    {
        return Attribute::make(
            get: fn() => $this->porciones > 0
                ? round($this->costo_real / $this->porciones, 4)
                : 0
        );
    }

    /** Variación porcentual entre costo real y esperado */
    protected function variacionPorcentual(): Attribute
    {
        return Attribute::make(
            get: function () {
                if ($this->costo_esperado <= 0) return 0;
                return round((($this->costo_real_porcion - $this->costo_esperado) / $this->costo_esperado) * 100, 2);
            }
        );
    }

    /** Invalida el caché del costo (llamar tras actualizar un insumo relacionado) */
    public function invalidarCacheCosto(): void
    {
        Cache::forget("receta_costo_{$this->id}");
    }
 
    public function scopeActivas($query)
    {
        return $query->where('activa', true);
    }
}