<?php

namespace App\Livewire\Products;

use App\Models\Monitoring\Log as MonitoringLog;
use App\Models\Products\Product;
use Illuminate\Support\Facades\Auth;
use LivewireUI\Modal\ModalComponent;

/**
 * Borrar un producto del catálogo.
 *
 * **Lo que había: nada.** El método `delete()` existía en el componente del listado y
 * **ninguna de las dos pantallas de producto pintaba un botón**, así que no se podía
 * borrar un producto desde el panel. Es el mismo patrón que el purgado de logs (MGR-039)
 * y la tercera vez que aparece: código sin punto de entrada.
 *
 * **Y no se puede borrar si alguien lo tiene.** Es la regla, y la razón es una cadena que
 * no se ve venir:
 *
 * 1. El borrado es lógico (`SoftDeletes`), así que el producto desaparece de las
 *    consultas pero **las filas del pivote `license_token_product` se quedan**.
 * 2. La API resuelve el producto por `slug` con `Product::where('slug', …)`, que con
 *    `SoftDeletes` **ya no lo encuentra**.
 * 3. Responde «Plugin not found» con código `X001`.
 * 4. Y `X001` está en la lista `CODES_NO_LICENCE` del plugin, así que el Moodle del
 *    cliente **le enseña la promoción de «contrata este producto»**… a un cliente que ya
 *    lo tiene pagado.
 *
 * O sea que borrar un producto licenciado no da un error: **le ofrece comprar otra vez lo
 * que ya compró**. Por eso se bloquea en lugar de avisar.
 */
class ProductDeleteModal extends ModalComponent
{
    public Product $product;

    public function mount(int $productId): void
    {
        // El permiso de la ruta no se reaplica en /livewire/update. Ver MGR-005.
        $this->authorize('admin.products.destroy');

        $this->product = Product::withCount('tokens')->findOrFail($productId);
    }

    public static function modalMaxWidth(): string
    {
        return '2xl';
    }

    /**
     * A quién afectaría.
     *
     * `tokens` cuenta **todas** las licencias que lo incluyen, vivas o apagadas: una
     * licencia apagada se puede volver a encender, y entonces el producto tendría que
     * seguir estando.
     *
     * @return array{licencias:int, entornos:int, clientes:int, contenido:int}
     */
    public function impacto(): array
    {
        $licencias = $this->product->tokens()->get();

        return [
            'licencias' => $licencias->count(),
            'clientes' => $licencias->pluck('client_id')->filter()->unique()->count(),
            'entornos' => $this->product->environmentsQuery()->count(),
            // El contenido publicado no impide borrar —se va con el producto— pero
            // conviene decir cuánto trabajo se está archivando.
            'contenido' => collect(Index::publicado()[$this->product->id] ?? [])
                ->sum(fn ($cajon) => $cajon['n']),
        ];
    }

    /** ¿Lo tiene alguien? Entonces no se borra. */
    public function estaEnUso(): bool
    {
        $impacto = $this->impacto();

        return $impacto['licencias'] > 0 || $impacto['entornos'] > 0;
    }

    public function borrar(): void
    {
        $this->authorize('admin.products.destroy');

        // Se vuelve a comprobar aquí: esconder el botón no es protegerlo (MGR-005), y
        // entre abrir la modal y confirmar alguien puede haber licenciado el producto.
        //
        // **Y la modal no se cierra.** Cerrándola, el aviso iba por `session()->flash()` y
        // la pantalla de detrás no se vuelve a pintar —no hay evento que la despierte—,
        // así que el mensaje no llegaba: se veía cerrarse la modal y el producto seguir en
        // el listado, sin explicación. Dejándola abierta, `render()` recalcula `enUso` y
        // la modal pasa a la variante de bloqueo, que dice a cuántas licencias afecta.
        if ($this->estaEnUso()) {
            return;
        }

        $nombre = $this->product->name;
        $slug = $this->product->slug;
        $contenido = $this->impacto()['contenido'];

        // Lógico siempre: un producto borrado se puede recuperar, y su contenido
        // versionado sigue en la base por si hubo que borrarlo por error.
        $this->product->delete();

        MonitoringLog::db(
            'warning',
            '16024',
            'Producto borrado del catálogo: ' . $nombre . ' (' . $slug . ')'
            . ($contenido > 0 ? ' — con ' . $contenido . ' versión(es) de contenido publicadas' : ' — sin contenido publicado')
            . ' (por ' . (Auth::user()?->name ?? 'desconocido') . ')',
            'Product',
            (string) $this->product->id
        );

        session()->flash('success', '«' . $nombre . '» ya no está en el catálogo. El borrado es '
            . 'lógico: su contenido publicado sigue guardado y un administrador puede recuperarlo.');

        // Clave numérica: el paquete hace `[$event, $params] = $event` cuando el valor es
        // un array, así que `['evento' => []]` revienta con "Undefined array key 0".
        $this->closeModalWithEvents(['productsChanged']);
    }

    public function render()
    {
        return view('livewire.products.product-delete-modal', [
            'impacto' => $this->impacto(),
            'enUso' => $this->estaEnUso(),
        ]);
    }
}
