<?php

namespace App\Livewire\LicenseTokens;

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

/**
 * Quitar un producto de una licencia, diciendo antes qué se corta.
 *
 * **Lo que había.** Un interruptor por producto en la ficha de la licencia: un clic y
 * `products()->detach()`. Eso hacía tres cosas mal a la vez:
 *
 * 1. **Cortaba sin avisar.** En la siguiente llamada a `products` ese slug ya no viaja,
 *    el plugin lo pinta como «sin licencia» y deja de funcionar **en todos los entornos
 *    de la licencia a la vez**. Sin confirmación y sin decir a cuántos sitios afecta.
 * 2. **Borraba el histórico.** `detach()` es un DELETE de verdad: se iban las fechas, el
 *    `observation`, el `mode` y el `assigned_by`. Y eso pese a que la tabla
 *    `license_token_product` **tiene `deleted_at`** y su modelo tiene `SoftDeletes`: el
 *    borrado en blando estaba diseñado y el código lo tiraba.
 * 3. **No dejaba rastro.** Ni quién, ni cuándo, ni qué producto.
 *
 * **Y ofrece lo que el modelo ya soportaba y la interfaz no.** El middleware respeta
 * `license_token_product.end_at`, así que «quitar cuando acabe el periodo pagado» era
 * posible en los datos e imposible en la pantalla. Es lo que pide un cliente que ha
 * pagado hasta diciembre y no renueva.
 */
class ProductRemovalModal extends ModalComponent
{
    public LicenseToken $licenseToken;
    public Product $product;

    public function mount(int $licenseTokenId, int $productId): void
    {
        // El permiso de la ruta no se reaplica en /livewire/update (MGR-005), y esto
        // corta servicio.
        $this->authorize('admin.license-tokens.edit');

        $this->licenseToken = LicenseToken::findOrFail($licenseTokenId);
        // Acotado a los productos de ESTA licencia: el id llega del navegador.
        $this->product = $this->licenseToken->products()->findOrFail($productId);
    }

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

    /** La fila del pivote, incluida si ya estuviera quitada. */
    private function fila(): LicenseTokenProduct
    {
        return LicenseTokenProduct::withTrashed()
            ->where('license_token_id', $this->licenseToken->id)
            ->where('product_id', $this->product->id)
            ->firstOrFail();
    }

    /**
     * Cuándo acaba el periodo pagado.
     *
     * La del producto si la tiene y es futura; si no, la de la licencia. Sin ninguna de
     * las dos no se puede ofrecer «al final del periodo», y la pantalla lo dice en vez de
     * poner un botón que no sabría qué fecha usar.
     */
    public function finDelPeriodo(): ?\Carbon\Carbon
    {
        $pivot = $this->fila();

        $delProducto = $pivot->end_at;
        $deLaLicencia = $this->licenseToken->end_at;

        if ($delProducto && $delProducto->isFuture()) {
            return $delProducto->copy();
        }

        return $deLaLicencia && $deLaLicencia->isFuture() ? $deLaLicencia->copy() : null;
    }

    public function quitarAhora(): void
    {
        $this->authorize('admin.license-tokens.edit');

        // Borrado EN BLANDO, con el modelo del pivote: la fila se queda con sus fechas y
        // su `assigned_by`, y la relación la filtra por `deleted_at`, así que la API deja
        // de servir el producto igual que antes.
        $this->fila()->delete();

        $this->registrar('quitado ahora: deja de funcionar en la siguiente petición');

        session()->flash('warning', $this->product->name . ' ya no está en esta licencia: '
            . 'deja de funcionar en los ' . $this->licenseToken->environments->count()
            . ' entorno(s) en la siguiente petición.');

        $this->closeModalWithEvents(['licenceProductsChanged']);
    }

    public function quitarAlFinal(): void
    {
        $this->authorize('admin.license-tokens.edit');

        $fin = $this->finDelPeriodo();

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

        // No se borra: se le pone fecha de fin. El middleware ya la respeta, así que el
        // producto sigue funcionando hasta ese día y se apaga solo.
        $fila = $this->fila();
        $fila->end_at = $fin;
        $fila->save();

        $this->registrar('con fecha de fin ' . $fin->format('d/m/Y'));

        session()->flash('success', $this->product->name . ' seguirá funcionando hasta el '
            . $fin->format('d/m/Y') . ' y se apagará solo.');

        $this->closeModalWithEvents(['licenceProductsChanged']);
    }

    private function registrar(string $comoSeQuita): void
    {
        MonitoringLog::db(
            'warning',
            '16021',
            'Producto ' . $this->product->name . ' quitado de la licencia '
            . ($this->licenseToken->name ?? 'sin nombre')
            . ' (' . ($this->licenseToken->client?->name ?? 'sin cliente') . '), '
            . $comoSeQuita . '. Afecta a ' . $this->licenseToken->environments->count() . ' entorno(s)',
            'LicenseToken',
            (string) $this->licenseToken->id
        );
    }

    public function render()
    {
        return view('livewire.license-tokens.product-removal-modal', [
            'entornos' => $this->licenseToken->environments,
            'finDelPeriodo' => $this->finDelPeriodo(),
        ]);
    }
}
