<?php

namespace App\Livewire\Traits;

use App\Livewire\Products\BorrarElementoModal;
use App\Livewire\Products\BorrarVersionModal;
use App\Support\VersionBorrable;
use Illuminate\Database\Eloquent\Model;
use Livewire\Attributes\On;

/**
 * Abrir las modales de borrado de una versión de contenido y de sus elementos.
 *
 * Lo usan **las tres pantallas** donde una versión se puede borrar, y son tres porque son
 * tres sitios distintos donde se mira:
 *
 * - `HasVersionIndex` — el **listado** de versiones de un tipo. Es donde se ve el histórico
 *   completo y donde uno va a retirar una vieja, así que es el sitio principal.
 * - `MuestraVersionDeElementos` — la ficha de una versión de Funcionalidades, Tutoriales o
 *   Recursos.
 * - `MuestraVersionDeArchivos` — la de SCSS y JS.
 *
 * El borrado es idéntico en los cinco tipos: lo que cambia son el modelo y las palabras, y
 * eso vive en `VersionBorrable` (PRODSECU-198).
 *
 * **El tipo sale de la ficha de cada pantalla** (`clave`), que ya existía para el selector,
 * así que no hay que declararlo dos veces. Y `ScssCdn` usa el trait del listado sin estar
 * en `VersionBorrable`: `puedeBorrarLaVersion()` devuelve `false` y no se pinta nada, que es
 * lo correcto —los bundles tienen su propio ciclo—.
 */
trait BorraVersionesDeContenido
{
    /**
     * La clave del tipo de contenido de esta pantalla.
     *
     * Cada pantalla la tiene en un sitio distinto —`ficha()` en el listado,
     * `fichaDeLaVersion()` en las dos de detalle—, así que se resuelve aquí en vez de
     * obligar a las tres a implementar un método igual.
     */
    protected function claveDelContenido(): ?string
    {
        if (method_exists($this, 'fichaDeLaVersion')) {
            return $this->fichaDeLaVersion()['clave'] ?? null;
        }

        if (method_exists($this, 'ficha')) {
            return $this->ficha()['clave'] ?? null;
        }

        return null;
    }

    /**
     * La versión que se está mirando, si la pantalla mira una sola.
     *
     * En el listado no hay una: allí el id llega como argumento del botón de cada fila.
     */
    protected function versionEnPantalla(): ?Model
    {
        if (method_exists($this, 'fichaDeLaVersion')) {
            return $this->fichaDeLaVersion()['version'] ?? null;
        }

        return null;
    }

    /**
     * ¿Este tipo tiene borrado de versión, y quien mira puede usarlo?
     *
     * Las dos cosas juntas porque la vista pregunta una sola: un tipo que no está en
     * `VersionBorrable` no tiene ni permiso que comprobar.
     */
    public function puedeBorrarLaVersion(): bool
    {
        $clave = $this->claveDelContenido();

        if ($clave === null || ! in_array($clave, VersionBorrable::claves(), true)) {
            return false;
        }

        return (bool) auth()->user()?->can(VersionBorrable::de($clave)['permisoVersion']);
    }

    /**
     * @param  int|null  $versionId  el id, cuando se llama desde una fila del listado; nulo
     *                               en las pantallas que miran una sola versión
     */
    public function abrirBorrarVersion(?int $versionId = null): void
    {
        $clave = $this->claveDelContenido();
        $tipo = VersionBorrable::de($clave);

        $this->authorize($tipo['permisoVersion']);

        $id = $versionId ?? $this->versionEnPantalla()?->id;

        if ($id === null) {
            return;
        }

        $this->dispatch('openModal',
            component: BorrarVersionModal::class,
            arguments: [
                'tipo' => $clave,
                'productId' => $this->product->id,
                'versionId' => $id,
            ]
        );
    }

    public function abrirBorrarElemento(int $elementoId): void
    {
        $clave = $this->claveDelContenido();
        $tipo = VersionBorrable::de($clave);

        $this->authorize($tipo['permisoElemento']);

        $version = $this->versionEnPantalla();

        if ($version === null) {
            return;
        }

        $this->dispatch('openModal',
            component: BorrarElementoModal::class,
            arguments: [
                'tipo' => $clave,
                'versionId' => $version->id,
                'elementoId' => $elementoId,
            ]
        );
    }

    /**
     * La pantalla se repinta cuando la modal ha borrado algo.
     *
     * **Sin esto la modal funcionaba y parecía que no.** Borraba de verdad, se cerraba, y la
     * fila seguía a la vista porque el componente de detrás no se había vuelto a renderizar:
     * desde el navegador es indistinguible de un botón roto. Lo reportó el usuario con esas
     * palabras —«no me deja borrar ningún features»— y estaba borrando bien.
     *
     * El cuerpo está vacío a propósito: escuchar el evento **ya provoca el render**, que es
     * todo lo que hace falta. Y de paso el mensaje de la sesión aparece en ese render.
     */
    #[On('contenidoBorrado')]
    public function repintarTrasBorrar(): void
    {
        //
    }
}
