<?php

namespace App\Livewire\Clients;

use App\Models\Clients\Client;
use Livewire\Component;
use Livewire\WithPagination;

class Index extends Component
{
    use WithPagination;

    public string $search = '';

    /**
     * alta | baja | todos.
     *
     * Por defecto **alta**: el listado es la herramienta de trabajo del día a día, y
     * los clientes que se han ido solo estorban ahí. Pero tienen que poder
     * encontrarse, que es lo que no pasaba: no se veía el estado ni había forma de
     * filtrar por él.
     */
    public string $estado = 'alta';

    protected $queryString = ['search', 'estado' => ['except' => 'alta']];

    public function updatingEstado(): void
    {
        $this->resetPage();
    }

    public function updatingSearch()
    {
        $this->resetPage();
    }

    /**
     * Los tres números de la cabecera.
     *
     * `sinActividad` es el que da la medida del problema: en la base de desarrollo son
     * **18 de 20**, clientes dados de alta sin una sola licencia ni un solo entorno. Se
     * dice en la cabecera porque un listado que los pinta igual que a los demás hace
     * pensar que hay 20 clientes trabajando.
     *
     * @return array{total:int, alta:int, baja:int, sinActividad:int}
     */
    private function resumen(): array
    {
        $alta = Client::where('actived', true)->count();

        return [
            'total' => Client::count(),
            'alta' => $alta,
            'baja' => Client::where('actived', false)->count(),
            'sinActividad' => Client::where('actived', true)
                ->whereDoesntHave('tokens')
                ->whereDoesntHave('environments')
                ->count(),
        ];
    }

    public function render()
    {
        $resumen = $this->resumen();

        $clients = Client::query()
            ->with(['tokens', 'deactivatedBy'])
            // Los contadores van con subconsulta agregada y no iterando los modelos:
            // serializar un entorno cuesta 16 consultas (MGR-015) y aquí hay 15 filas
            // por página.
            ->withCount([
                'tokens',
                'environments',
                // Sin señal: **han** sincronizado y llevan 3 días o más sin hacerlo. El
                // `whereNotNull` es lo que separa la avería del alta sin terminar, y es
                // la misma definición que usa el listado de Entornos y el Dashboard: si
                // cada pantalla la calculara a su manera, dirían números distintos del
                // mismo parque.
                'environments as sin_senal_count' => fn ($q) => $q->where('active', true)
                    ->whereNotNull('refresh_at')
                    ->where('refresh_at', '<', now()->subDays(3)),
                'environments as sin_sincronizar_count' => fn ($q) => $q->where('active', true)
                    ->whereNull('refresh_at'),
            ])
            ->when($this->estado === 'alta', fn ($q) => $q->where('actived', true))
            ->when($this->estado === 'baja', fn ($q) => $q->where('actived', false))
            ->when($this->search !== '', function ($query) {
                // **El paréntesis es el arreglo de un error.** Los cinco `orWhere` iban
                // sueltos al mismo nivel que el `where('actived', …)` de la pestaña, y
                // `AND` liga más fuerte que `OR`: la condición acababa siendo
                // «(de alta Y coincide el nombre) O coincide el shortname O …», así que
                // buscando desde la pestaña «De alta» salían también los de baja.
                $query->where(function ($sub) {
                    $termino = '%' . $this->search . '%';

                    $sub->where('name', 'like', $termino)
                        ->orWhere('shortname', 'like', $termino)
                        ->orWhere('crm_id', 'like', $termino)
                        ->orWhere('cif', 'like', $termino)
                        ->orWhere('razon_social', 'like', $termino);
                });
            })
            // **Por actividad y no alfabético.** La pregunta que trae a esta pantalla es
            // «qué pasa con mis clientes», y con 18 de 20 vacíos el orden alfabético
            // entierra a los que tienen algo. Los entornos pesan doble porque son el
            // servicio en marcha; una licencia sin entorno es un contrato sin usar.
            // El nombre entra como segundo criterio para que el orden sea estable.
            ->orderByRaw('(environments_count * 2 + tokens_count) desc')
            ->orderBy('name')
            ->paginate(15);

        return view('livewire.clients.index', [
            'clients' => $clients,
            'resumen' => $resumen,
        ])->layout('layouts.app');
    }
}
