<?php

namespace App\Models\ScssCdn;

use App\Models\Auth\User;
use App\Models\Products\Product;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class ScssCdnBundle extends Model
{
    use HasFactory;

    protected $table = 'scss_cdn_bundles';

    protected $fillable = [
        'product_id',
        'version',
        'description',
        'created_by',
        'updated_by',
    ];

    /* -----------------------------
       Relaciones
    ------------------------------*/

    /**
     * Producto al que pertenece el bundle
     */
    public function product()
    {
        return $this->belongsTo(Product::class);
    }

    /**
     * Archivos SCSS de este bundle
     */
    public function files()
    {
        return $this->hasMany(ScssCdnFile::class, 'scss_cdn_bundle_id');
    }

    /**
     * Usuario que creó el bundle
     */
    public function creator()
    {
        return $this->belongsTo(User::class, 'created_by');
    }

    /**
     * Usuario que editó por última vez el bundle
     */
    public function updater()
    {
        return $this->belongsTo(User::class, 'updated_by');
    }

    /* -----------------------------
       Scopes
    ------------------------------*/

    /**
     * Scope para filtrar por producto
     */
    public function scopeForProduct($query, $product)
    {
        $productId = $product instanceof Product ? $product->id : $product;
        return $query->where('product_id', $productId);
    }

    /**
     * Scope para filtrar por versión
     */
    public function scopeForVersion($query, string $version)
    {
        return $query->where('version', $version);
    }

    /* -----------------------------
       Métodos estáticos
    ------------------------------*/

    /**
     * Encuentra el bundle compatible de SCSS CDN para un producto y versión dados
     *
     * @param Product|int $product Producto o ID del producto
     * @param string $productVersion Versión del producto (formato YYYYMMDDXX)
     * @return ScssCdnBundle|null
     */
    public static function findCompatibleVersion($product, string $productVersion): ?ScssCdnBundle
    {
        $productId = $product instanceof Product ? $product->id : $product;
        $productVersionInt = (int) $productVersion;

        // Buscar bundles para este producto
        $bundles = self::forProduct($productId)->get();

        if ($bundles->isEmpty()) {
            return null;
        }

        // 1. Buscar coincidencia exacta
        $exactMatch = $bundles->firstWhere('version', $productVersion);
        if ($exactMatch) {
            return $exactMatch;
        }

        // 2. Buscar bundles compatibles (versionBundle <= versionProduct)
        $compatibleBundles = $bundles->filter(function ($bundle) use ($productVersionInt) {
            $versionInt = (int) $bundle->version;
            return $versionInt <= $productVersionInt;
        });

        if ($compatibleBundles->isEmpty()) {
            return null;
        }

        // 3. Seleccionar el mayor bundle compatible
        return $compatibleBundles->sortByDesc(function ($bundle) {
            return (int) $bundle->version;
        })->first();
    }

    /* -----------------------------
       Métodos de instancia
    ------------------------------*/

    /**
     * Genera la siguiente versión disponible para este producto
     *
     * @return string Nueva versión en formato YYYYMMDDXX
     */
    public function generateNextVersion(): string
    {
        $currentVersion = (int) $this->version;
        $productId = $this->product_id;

        // Intentar incrementar el último dígito
        $attempts = 0;
        $maxAttempts = 100; // Límite de seguridad

        do {
            $newVersion = $currentVersion + 1;
            $newVersionStr = str_pad((string) $newVersion, 10, '0', STR_PAD_LEFT);

            // Verificar que no exista ya esta versión para este producto
            $exists = self::where('product_id', $productId)
                ->where('version', $newVersionStr)
                ->exists();

            if (!$exists) {
                return $newVersionStr;
            }

            $currentVersion = $newVersion;
            $attempts++;
        } while ($attempts < $maxAttempts);

        // Si llegamos aquí, algo está mal (demasiadas versiones)
        throw new \RuntimeException('No se pudo generar una nueva versión. Demasiadas versiones existentes.');
    }

    /**
     * Duplica el bundle y todos sus archivos
     *
     * @param string|null $newVersion Versión específica o null para auto-generar
     * @return ScssCdnBundle Nuevo bundle duplicado
     */
    public function duplicate(?string $newVersion = null): ScssCdnBundle
    {
        // Asegurar que las relaciones estén cargadas
        if (!$this->relationLoaded('product')) {
            $this->load('product');
        }
        if (!$this->relationLoaded('files')) {
            $this->load('files');
        }

        if (!$newVersion) {
            $newVersion = $this->generateNextVersion();
        }

        // Verificar que la nueva versión no exista
        $exists = self::where('product_id', $this->product_id)
            ->where('version', $newVersion)
            ->exists();

        if ($exists) {
            throw new \RuntimeException("La versión {$newVersion} ya existe para este producto.");
        }

        // Crear nuevo bundle
        $newBundle = self::create([
            'product_id' => $this->product_id,
            'version' => $newVersion,
            'description' => $this->description ? "Duplicado de {$this->version}: {$this->description}" : "Duplicado de {$this->version}",
            'created_by' => auth()->id(),
            'updated_by' => auth()->id(),
        ]);

        // Duplicar todos los archivos
        foreach ($this->files as $file) {
            // Leer contenido desde storage
            $fileContent = $file->getContent();
            
            if ($fileContent === null) {
                continue; // Saltar si no se puede leer el archivo
            }

            $newFile = ScssCdnFile::create([
                'scss_cdn_bundle_id' => $newBundle->id,
                'relative_path' => $file->relative_path,
                'filename' => $file->filename,
                'is_servable' => $file->is_servable,
                'secure_token' => \Illuminate\Support\Str::random(32),
                'created_by' => auth()->id(),
                'updated_by' => auth()->id(),
            ]);

            // Copiar archivo físico
            \App\Services\ScssCdn\ScssCdnStorageService::saveFile(
                $this->product,
                $newBundle,
                $file->relative_path,
                $fileContent
            );
        }

        return $newBundle;
    }
}

