<?php

namespace App\Models\Concerns;

use App\Services\AuditLogger;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;

/**
 * Registra en {@see AuditLogger} las operaciones CRUD del modelo que use este trait.
 *
 * Requiere definir en el modelo: `protected static string $auditModule = 'nombre_modulo';`
 */
// TODO(regiticket): Añadir `restored` / `forceDeleted` si se usan soft deletes en estos modelos.
trait Auditable
{
    public static function bootAuditable(): void
    {
        static::created(static function (Model $model): void {
            if (! $model instanceof static) {
                return;
            }
            app(AuditLogger::class)->recordModelCreated(
                $model,
                $model->auditModule(),
                $model->getAttributes(),
            );
        });

        static::updated(static function (Model $model): void {
            if (! $model instanceof static) {
                return;
            }
            $changes = $model->getChanges();
            if ($changes === []) {
                return;
            }
            if (count($changes) === 1 && array_key_exists('updated_at', $changes)) {
                return;
            }
            $keys = array_keys($changes);
            $old = Arr::only($model->getOriginal(), $keys);
            app(AuditLogger::class)->recordModelUpdated($model, $model->auditModule(), $old, $changes);
        });

        static::deleted(static function (Model $model): void {
            if (! $model instanceof static) {
                return;
            }
            app(AuditLogger::class)->recordModelDeleted($model, $model->auditModule());
        });
    }

    /**
     * Nombre lógico del módulo para filtrar en el listado de auditoría.
     */
    public function auditModule(): string
    {
        /** @phpstan-ignore-next-line */
        return static::$auditModule ?? 'models';
    }
}
