<?php

namespace App\Livewire\Environments;

use App\Models\Clients\Client;
use App\Models\Environments\Environment;
use App\Models\Environments\Type;
use App\Rules\UniqueEnvironmentDomain;
use Livewire\Component;
use Livewire\WithPagination;

class CreateWizard extends Component
{
    use WithPagination;

    public int $currentStep = 1;
    public ?int $selectedClientId = null;
    public string $searchQuery = '';
    public array $formData = [];
    public ?int $createdEnvironmentId = null;

    protected $paginationTheme = 'tailwind';

    public function mount()
    {
        // El permiso de la ruta no se reaplica en /livewire/update (MGR-005). Abrir un
        // asistente que no se va a poder terminar es una pantalla que engaña.
        $this->authorize('admin.environments.create');

        $this->currentStep = 1;
        $this->formData = [
            'name' => '',
            'domain' => '',
            'description' => null,
            'version' => '',
            'env' => 'local',
            'type_id' => null,
        ];
    }

    public function selectClient($clientId)
    {
        $this->selectedClientId = $clientId;
        $this->formData['client_id'] = $clientId;
    }

    public function updatedSelectedClientId()
    {
        // Cuando se selecciona un cliente, actualizar formData
        if ($this->selectedClientId) {
            $this->formData['client_id'] = $this->selectedClientId;
        }
    }

    public function nextStep()
    {
        if ($this->currentStep === 1) {
            // Validar que se haya seleccionado un cliente
            if (!$this->selectedClientId) {
                session()->flash('error', 'Por favor, selecciona un cliente.');
                return;
            }
            $this->currentStep = 2;
        }

        // **Del paso 2 no se avanza con esto.** Había una rama que validaba y no hacía
        // nada más, alimentando un «Siguiente» en la cabecera que parecía la acción
        // principal del paso: pulsarlo o pintaba errores o no pasaba nada. El paso 2 se
        // termina enviando el formulario (`saveEnvironment`), y su botón lo dice.
    }

    /**
     * El cliente elegido en el paso 1.
     *
     * Para poder **nombrarlo** en el paso 2: decir «para el cliente seleccionado» sin
     * decir cuál obliga a volver atrás para confirmarlo, y es justo lo que no se quiere
     * después de haber buscado y paginado.
     */
    public function clienteElegido(): ?Client
    {
        return $this->selectedClientId ? Client::find($this->selectedClientId) : null;
    }

    public function previousStep()
    {
        if ($this->currentStep > 1) {
            $this->currentStep--;
        }
    }

    protected function validateStep2()
    {
        $this->validate([
            'formData.name' => 'required|string|max:255',
            'formData.domain' => ['required', 'string', 'max:255', new UniqueEnvironmentDomain($this->formData['env'] ?? null)],
            'formData.description' => 'nullable|string',
            'formData.version' => 'required|string|max:50',
            // La lista vive en el modelo (MGR-010).
            'formData.env' => Environment::reglaDeEnv(),
            'formData.type_id' => 'nullable|exists:types,id',
        ], [], [
            'formData.name' => 'nombre',
            'formData.domain' => 'dominio',
            'formData.version' => 'versión',
            'formData.env' => 'desarrollo',
            'formData.type_id' => 'tipo de entorno',
        ]);
    }

    public function updatedFormData()
    {
        // Resetear errores cuando se actualiza el formulario
    }

    public function saveEnvironment()
    {
        // Ver known-issues MGR-005: el gate de la ruta no basta como única defensa.
        $this->authorize('admin.environments.create');

        $this->validateStep2();

        $data = $this->formData;
        $data['client_id'] = $this->selectedClientId;
        $data['active'] = true;

        $environment = Environment::create($data);
        $this->createdEnvironmentId = $environment->id;
        $this->currentStep = 3;
    }

    public function updatedSearchQuery()
    {
        // Resetear paginación cuando cambia la búsqueda
        $this->resetPage();
    }

    public function getClientsProperty()
    {
        $query = Client::query();

        if (!empty($this->searchQuery)) {
            $query->where(function($q) {
                $q->where('name', 'like', '%' . $this->searchQuery . '%')
                  ->orWhere('shortname', 'like', '%' . $this->searchQuery . '%');
            });
        }

        $clients = $query->orderBy('name')->paginate(10);

        // Agregar environments_count a cada cliente
        $clients->getCollection()->transform(function ($client) {
            $client->environments_count = $client->environments()->count();
            return $client;
        });

        return $clients;
    }

    public function render()
    {
        return view('livewire.environments.create-wizard', [
            // El catálogo lo pasa el componente. Son cuatro filas, así que no es una
            // cuestión de coste: es que una consulta dentro de un Blade no se ve
            // desde el componente ni se puede probar. Ver MGR-098.
            'types' => Type::orderBy('name')->get(),
        ])->layout('layouts.clean');
    }
}

