<?php

namespace App\Livewire\Products;

use App\Models\Products\Product;
use App\Support\LimiteDeSubida;
use Illuminate\Support\Facades\Storage;
use Livewire\Component;
use Livewire\WithFileUploads;

class Edit extends Component
{
    use WithFileUploads;

    public Product $product;
    public string $slug = '';
    public string $name = '';
    public ?string $summary = null;
    public ?string $description = null;
    public ?string $tech = null;
    public ?string $type = null;
    public ?string $metadata = null;
    public bool $actived = false;
    public bool $enabled = false;

    /** El icono. Ver el motivo en `Products\Create::$image`. */
    public $image = null;

    public function mount(Product $product)
    {
        $this->product = $product;
        $this->slug = $product->slug ?? '';
        $this->name = $product->name ?? '';
        $this->summary = $product->summary;
        $this->description = $product->description;
        $this->tech = $product->tech;
        $this->type = $product->type;
        $this->metadata = $product->metadata ? json_encode($product->metadata, JSON_PRETTY_PRINT) : null;
        $this->actived = $product->actived ?? false;
        $this->enabled = $product->enabled ?? false;
    }

    protected function rules()
    {
        return [
            'slug' => 'required|string|max:200|unique:products,slug,' . $this->product->id,
            'name' => 'required|string|max:200',
            'summary' => 'required|string',
            'description' => 'nullable|string',
            // Opcional por lo mismo: **no lo lee nadie**. `isMoodle()` e
            // `isWordPress()` existen en el modelo y no se llaman desde ningún sitio,
            // así que exigirlo era pedir un dato que no se usa.
            'tech' => 'nullable|string|max:50',
            // **Opcional**, como la columna. Un producto que no es un plugin de Moodle
            // no tiene tipo, y obligarlo solo conseguía que se pusiera uno falso.
            'type' => 'nullable|string|max:50',
            'metadata' => 'nullable|string',
            'actived' => 'nullable|boolean',
            'enabled' => 'nullable|boolean',
            'image' => ['nullable', 'file', 'mimes:jpeg,jpg,png,webp', 'max:' . LimiteDeSubida::enKb()],
        ];
    }

    protected function messages(): array
    {
        return [
            'image.mimes' => 'El icono debe ser jpg, png o webp. El SVG no se acepta: puede llevar código y se serviría desde el propio dominio del panel.',
        ];
    }

    /**
     * Quita el icono y deja el de reserva.
     *
     * Va aparte del guardado porque **un campo de fichero vacío significa «no lo cambies»,
     * no «bórralo»**: sin este botón, poner un icono sería irreversible.
     */
    public function quitarIcono(): void
    {
        $this->authorize('admin.products.edit');

        $this->borrarIconoAnterior();

        $this->product->update(['image' => null]);
        $this->image = null;

        session()->flash('success', 'Icono quitado. El producto vuelve a salir con el de reserva.');
    }

    /**
     * Borra del disco el icono que hubiera.
     *
     * **No toca `images_static/`**: ahí viven los iconos que vienen con la aplicación, que
     * comparten varios productos y no son de nadie en particular. Es la misma cautela que
     * en los tipos de entorno.
     */
    private function borrarIconoAnterior(): void
    {
        $anterior = $this->product->image;

        if (! $anterior || str_starts_with($anterior, 'images_static/')) {
            return;
        }

        if (Storage::disk('public')->exists($anterior)) {
            Storage::disk('public')->delete($anterior);
        }
    }

    public function update()
    {
        $this->authorize('admin.products.edit');
        
        $validated = $this->validate();

        // Procesar metadata JSON
        if (!empty($validated['metadata'])) {
            $decoded = json_decode($validated['metadata'], true);
            $validated['metadata'] = json_last_error() === JSON_ERROR_NONE ? $decoded : null;
        } else {
            $validated['metadata'] = null;
        }

        foreach (['type', 'tech'] as $campo) {
            if (($validated[$campo] ?? '') === '') {
                $validated[$campo] = null;
            }
        }

        if ($this->image) {
            $this->borrarIconoAnterior();
            $validated['image'] = $this->image->store('images/products', 'public');
        } else {
            // **Sin esto, editar cualquier otro campo borraría el icono.** El campo de
            // fichero llega vacío en cada guardado normal, y `validate()` devuelve la
            // clave con null: un `update` con `image => null` deja el producto sin icono
            // sin que nadie lo haya pedido. Para quitarlo está `quitarIcono()`.
            unset($validated['image']);
        }

        $this->product->update($validated);

        session()->flash('success', 'Producto actualizado.');

        return $this->redirect(route('products.index'), navigate: true);
    }

    public function render()
    {
        return view('livewire.products.edit', [
            // Las sugerencias de los dos campos libres: los valores de siempre más los que
            // ya se hayan usado. Ver `Product::tiposSugeridos()`.
            'tipos' => Product::tiposSugeridos(),
            'tecnologias' => Product::tecnologiasSugeridas(),
        ])->layout('layouts.app');
    }
}

