<?php

namespace onespace\tools\activeApi\behaviors;

use Ulid\Ulid as Ulid;
use yii\base\Behavior;
use yii\db\BaseActiveRecord;

/**
 * UlidBehavior automatically generates a ULID for the specified attribute.
 *
 * - Generates a ULID before validation if the attribute is empty.
 * - Always regenerates a fresh ULID before insertion (unless configured otherwise).
 *
 * Example usage:
 * ```
 * public function behaviors()
 * {
 *     return [
 *         'ulid' => [
 *             'class' => \onespace\tools\activeApi\behaviors\UlidBehavior::class,
 *             'attribute' => 'id',
 *             'alwaysNewOnInsert' => true,
 *         ],
 *     ];
 * }
 * ```
 *
 * @author Gareth Palmer <gareth@one-space.co.za>
 */
class UlidBehavior extends Behavior {
    /**
     * @var string the attribute that should receive the ULID
     */
    public string $attribute = 'id';

    /**
     * @var bool whether to always generate a new ULID on insert
     * (if false, keeps an existing value if one was manually assigned)
     */
    public bool $alwaysNewOnInsert = true;

    /**
     * {@inheritDoc}
     */
    #[\Override]
    public function events(): array {
        return [
            BaseActiveRecord::EVENT_BEFORE_VALIDATE => 'beforeValidate',
            BaseActiveRecord::EVENT_BEFORE_INSERT   => 'beforeInsert',
        ];
    }

    /**
     * Assign ULID before validation (only if empty)
     */
    public function beforeValidate($event): void {
        $model = $this->owner;
        $attr = $this->attribute;

        if (empty($model->$attr)) {
            $model->$attr = (string) Ulid::generate();
        }
    }

    /**
     * Assign ULID before insertion (optionally always regenerate)
     */
    public function beforeInsert($event): void {
        $model = $this->owner;
        $attr = $this->attribute;

        if ($this->alwaysNewOnInsert || empty($model->$attr)) {
            $model->$attr = (string) Ulid::generate();
        }
    }
}
