<?php

namespace App\Models\Support;

use App\Models\Environments\Environment;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Support extends Model
{
    use HasFactory, SoftDeletes;

    const EXPIRED_DAYS = 30;

    const STATUS = [
        0 => 'Sin Soporte',
        1 => 'Sin fechas',
        2 => 'Sin comenzar',
        3 => 'Caducado',
        4 => 'Próximo a caducar',
        5 => 'Activado',
        6 => 'Desactivado',
    ];

    protected $fillable = [
        'name',
        'shortname',
        'description',
    ];

    protected $casts = [
        'description' => 'string',
    ];

    /**
     * Entornos que tienen este soporte
     */
    public function environments()
    {
        return $this->belongsToMany(Environment::class, 'environment_support')
            ->withPivot(['comment', 'start_at', 'end_at'])
            ->withTimestamps();
    }

    /* ============================================================
     |   LOGICA LEGACY (manteniéndola pero limpiando bordes)
     * ============================================================
     */

    /**
     * Determina el estado del soporte según fechas.
     *
     * **Estaba roto y devolvía «Caducado» para todo**, incluido un soporte que acabase
     * en 2027. La causa: en Carbon 3 `diffInDays` va **con signo**, así que
     * `$end->diffInDays($now)` da negativo cuando el fin está en el futuro —y el código
     * lo interpretaba como días agotados—. Es la tercera vez que esta trampa muerde en
     * este proyecto; ver MGR-030.
     *
     * No se notó porque **ninguna pantalla usaba esto**: los accesores `supportstatus` y
     * compañía del entorno no se pintan en ningún sitio. El aviso de soportes que
     * caducan sí depende de ello, así que aquí se arregla.
     */
    public static function get_status_support(Carbon $start, Carbon $end, $can_activate = true): int
    {
        $now = Carbon::now();

        // El sujeto es AHORA y el objeto el fin: así "quedan N días" es positivo y
        // "venció hace N" es negativo, que es como lo lee el resto del método.
        //
        // Y se compara por **días de calendario**, no por marcas de tiempo: `end_at` es
        // una fecha (00:00), así que restando timestamps un soporte que acaba mañana da
        // 0,99 días → 0 → "caducado". Peor aún, el estado dependería de la hora a la
        // que se ejecute la tarea diaria.
        $remaining = (int) $now->copy()->startOfDay()->diffInDays($end->copy()->startOfDay(), false);

        // Aún no ha comenzado
        if ($now < $start) {
            return 2;
        }

        // Caducado (hoy o ya pasado)
        if ($remaining < 1) {
            return 3;
        }

        // Próximo a caducar (< 30 días)
        if ($remaining < self::EXPIRED_DAYS) {
            return 4;
        }

        // Activo / desactivado
        return $can_activate ? 5 : 6;
    }

    /**
     * Comprueba si una versión es más nueva que otra.
     */
    public static function has_updated(string $current, string $new): bool
    {
        $a = self::map_version(explode('.', $current));
        $b = self::map_version(explode('.', $new));

        return $b > $a;
    }

    /**
     * Convierte "4.3.2" en [4, 3, 2] para comparación.
     */
    public static function map_version(array $ver): array
    {
        return [
            (int) ($ver[0] ?? 0),
            (int) ($ver[1] ?? 0),
            (int) ($ver[2] ?? 0),
        ];
    }

    /**
     * Determina si el soporte está aún activo (útil en listados).
     */
    public static function is_enabled($environment_support): bool
    {
        if (!$environment_support?->start_at || !$environment_support?->end_at) {
            return false;
        }

        $start = Carbon::parse($environment_support->start_at);
        $end   = Carbon::parse($environment_support->end_at);

        // Estaba como `< 4`, y eso contaba el 3 (Caducado) como activo: exactamente al
        // revés. Activo es 5, y 4 es "próximo a caducar", que también lo está.
        return in_array(self::get_status_support($start, $end), [4, 5], true);
    }
}

