<?php

namespace App\Livewire\Products;

use App\Models\Products\Product;
use Livewire\Component;

/**
 * Ficha de un producto.
 *
 * Implementa `Productos.dc.html` del sistema de diseño (Claude Design).
 *
 * **Lo que había** eran 647 líneas con **siete pestañas** —Setups, SCSS, JS, SCSS CDN,
 * Features, Recursos, Tutoriales—, construidas como si cada producto tuviera contenido en
 * todas. En la base real hay **dos filas en total** entre los cinco productos: seis de las
 * siete pestañas están vacías siempre, y había que pulsarlas una a una para descubrirlo.
 *
 * El diseño lo cambia por **dos listas agrupadas por lo que el contenido es**: lo que
 * configura el Moodle (setups, SCSS, JS, bundles CDN) y lo que lee el usuario final
 * (features, recursos, tutoriales). Cada fila dice su última versión y su fecha, o que
 * está vacía, sin tener que pulsar nada.
 *
 * Los siete listados de gestión **siguen siendo pantallas propias**: esta ficha enseña y
 * enlaza, no edita.
 */
class Show extends Component
{
    public Product $product;

    public function mount(Product $product)
    {
        $this->product = $product->load([
            'tokens.client',
            'tokens.environments',
        ]);
    }

    /**
     * Los siete cajones con lo que hay publicado en cada uno.
     *
     * Se apoya en `Index::cajones()` y `Index::publicado()` para que el listado y la
     * ficha **cuenten lo mismo**: dos consultas distintas para el mismo número acaban
     * dando números distintos.
     *
     * @return array<string, array<int, array<string, mixed>>>  familia => filas
     */
    public function contenidoPorFamilia(): array
    {
        $publicado = Index::publicado()[$this->product->id] ?? [];
        $familias = ['config' => [], 'contenido' => []];

        foreach (Index::cajones() as $clave => $cajon) {
            $datos = $publicado[$clave] ?? null;

            $familias[$cajon['familia']][] = [
                'clave' => $clave,
                'nombre' => $cajon['nombre'],
                'ruta' => $cajon['ruta'],
                'permiso' => $cajon['permiso'],
                'tiene' => $datos !== null,
                'n' => $datos['n'] ?? 0,
                'version' => $datos['version'] ?? null,
                'fecha' => $datos['fecha'] ?? null,
            ];
        }

        return $familias;
    }

    /**
     * ¿Hay algo publicado en algún cajón?
     *
     * Es el caso de 4 de 5 productos, y cambia lo que la ficha tiene que decir: un
     * producto sin nada publicado responde a la API con la validación de licencia y sin
     * contenido, y eso hay que decirlo.
     */
    public function sinPublicar(): bool
    {
        return (Index::publicado()[$this->product->id] ?? []) === [];
    }

    /**
     * Los entornos donde está instalado, con su estado de sincronización.
     *
     * Se derivan de las licencias que incluyen el producto. **Tres estados y no dos**,
     * igual que en Entornos, Clientes y Licencias.
     *
     * @return array<int, array<string, mixed>>
     */
    public function entornos(): array
    {
        return $this->product->environmentsQuery()
            ->with('type')
            ->orderBy('domain')
            ->get()
            ->map(function ($entorno) {
                $sincronizado = $entorno->refresh_at !== null;

                return [
                    'id' => $entorno->id,
                    'nombre' => $entorno->name,
                    'dominio' => $entorno->domain,
                    'env' => $entorno->env,
                    'version' => $entorno->version,
                    'tipo' => $entorno->type?->name,
                    'nunca' => ! $sincronizado,
                    'sinSenal' => $sincronizado
                        && $entorno->refresh_at->copy()->startOfDay()->diffInDays(now()->startOfDay()) >= 3,
                    'dias' => $sincronizado
                        ? (int) $entorno->refresh_at->copy()->startOfDay()->diffInDays(now()->startOfDay())
                        : null,
                    'fecha' => $entorno->refresh_at?->diffForHumans(),
                ];
            })
            ->all();
    }

    public function render()
    {
        return view('livewire.products.show', [
            'familias' => $this->contenidoPorFamilia(),
            'sinPublicar' => $this->sinPublicar(),
            'entornos' => $this->entornos(),
        ])->layout('layouts.app');
    }
}
