<?php

namespace App\Support;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Str;

/**
 * Genera códigos únicos (slug) a partir del nombre para catálogos.
 */
final class CatalogCodeGenerator
{
    /**
     * @param  class-string<Model>  $modelClass
     */
    public static function fromName(
        string $name,
        string $modelClass,
        string $column = 'code',
        string $fallback = 'item',
        int $maxLen = 64,
        ?string $prefix = null,
    ): string {
        $slug = Str::slug($name, '_');
        if ($slug === '') {
            $slug = $fallback;
        }

        $base = $prefix !== null && $prefix !== ''
            ? rtrim($prefix, '_').'_'.$slug
            : $slug;
        $base = substr($base, 0, $maxLen);

        $code = $base;
        $n = 2;
        while (self::exists($modelClass, $column, $code)) {
            $suffix = '_'.$n;
            $trim = max(1, $maxLen - strlen($suffix));
            $code = substr($base, 0, $trim).$suffix;
            $n++;
        }

        return $code;
    }

    /**
     * @param  class-string<Model>  $modelClass
     */
    public static function resolve(
        ?string $provided,
        string $name,
        string $modelClass,
        string $column = 'code',
        string $fallback = 'item',
        int $maxLen = 64,
        ?string $prefix = null,
    ): string {
        $code = trim((string) $provided);

        return $code !== ''
            ? $code
            : self::fromName($name, $modelClass, $column, $fallback, $maxLen, $prefix);
    }

    /**
     * @param  class-string<Model>  $modelClass
     */
    private static function exists(string $modelClass, string $column, string $code): bool
    {
        $query = $modelClass::query()->where($column, $code);

        if (in_array(SoftDeletes::class, class_uses_recursive($modelClass), true)) {
            $query->withTrashed();
        }

        return $query->exists();
    }
}
