<?php

namespace App\Models\Scss;

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

class ScssVersion extends Model
{
    use HasFactory;

    protected $table = 'scss_versions';

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

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

    /**
     * Producto al que pertenece la versión SCSS
     */
    public function product()
    {
        return $this->belongsTo(Product::class);
    }

    /**
     * Archivos SCSS de esta versión
     */
    public function files()
    {
        return $this->hasMany(ScssFile::class, 'scss_version_id');
    }

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

    /**
     * Usuario que editó por última vez la versión
     */
    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 la versión compatible de SCSS 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 ScssVersion|null
     */
    public static function findCompatibleVersion($product, string $productVersion): ?ScssVersion
    {
        $productId = $product instanceof Product ? $product->id : $product;
        $productVersionInt = (int) $productVersion;

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

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

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

        // 2. Buscar versiones compatibles (versionScss <= versionProduct)
        $compatibleVersions = $versions->filter(function ($version) use ($productVersionInt) {
            $versionInt = (int) $version->version;
            return $versionInt <= $productVersionInt;
        });

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

        // 3. Seleccionar la mayor versión compatible
        return $compatibleVersions->sortByDesc(function ($version) {
            return (int) $version->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 la versión y todos sus archivos
     *
     * @param string|null $newVersion Versión específica o null para auto-generar
     * @return ScssVersion Nueva versión duplicada
     */
    public function duplicate(?string $newVersion = null): ScssVersion
    {
        // 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 nueva versión
        $newVersionModel = 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) {
            $newFile = ScssFile::create([
                'scss_version_id' => $newVersionModel->id,
                'filename' => $file->filename,
                'content' => $file->content,
                'created_by' => auth()->id(),
                'updated_by' => auth()->id(),
            ]);

            // Copiar archivo físico
            \App\Services\Scss\ScssStorageService::saveFile(
                $this->product,
                $newVersionModel,
                $file->filename,
                $file->content
            );
        }

        return $newVersionModel;
    }
}
