<?php

/*
 * -------------------------------------------------------------------------
 * SISTEMA: Nouderg Technology - Adobe Presentaciones
 * ARCHIVO: NouRotacionService.php
 * AUTOR: Leonardo Argueta
 * FECHA: 2026-05-25
 * DESCRIPCION: Controla la cola de videos por pantalla.
 *              Cada pantalla tiene su propia lista de todos los videos
 *              de la biblioteca. Los va marcando como reproducidos uno
 *              por uno. Cuando no quedan videos sin reproducir, recarga
 *              la lista completa y empieza de nuevo. Nunca dos pantallas
 *              activas muestran el mismo video al mismo tiempo.
 * -------------------------------------------------------------------------
 */

namespace App\Services;

use App\Models\NouPantallaVideo;
use App\Models\NouPantallaRotacion;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class NouRotacionService
{
    /**
     * Retorna el siguiente video pendiente de la cola de una pantalla.
     * Si la cola esta vacia o no existe, la recarga con todos los videos
     * de la biblioteca en orden aleatorio.
     * Nunca asigna un video que este en uso en otra pantalla activa,
     * a menos que no haya otra opcion.
     *
     * @param int $nou_var_pantalla_id ID de la pantalla que solicita el video.
     * @return NouPantallaVideo|null
     */
    public function Nou_fun_siguiente_video(int $nou_var_pantalla_id): ?NouPantallaVideo
    {
        // Videos en uso actualmente en OTRAS pantallas
        $nou_arr_en_uso = DB::table('Nou_tbl_pant_rotacion')
            ->where('id_pantalla', '!=', $nou_var_pantalla_id)
            ->whereNotNull('id_video_actual')
            ->pluck('id_video_actual')
            ->toArray();

        // Busca el siguiente video pendiente en la cola de esta pantalla
        // que no este en uso en otra pantalla
        $nou_var_siguiente = DB::table('Nou_tbl_pant_cola_pantalla')
            ->where('id_pantalla', $nou_var_pantalla_id)
            ->where('reproducido', false)
            ->when(!empty($nou_arr_en_uso), fn($q) =>
                $q->whereNotIn('id_video', $nou_arr_en_uso)
            )
            ->orderBy('id_cola_pantalla')
            ->first();

        // Si no hay videos pendientes disponibles, recarga la cola
        if (!$nou_var_siguiente)
        {
            $this->Nou_fun_recargar_cola($nou_var_pantalla_id);

            // Busca de nuevo despues de recargar
            $nou_var_siguiente = DB::table('Nou_tbl_pant_cola_pantalla')
                ->where('id_pantalla', $nou_var_pantalla_id)
                ->where('reproducido', false)
                ->when(!empty($nou_arr_en_uso), fn($q) =>
                    $q->whereNotIn('id_video', $nou_arr_en_uso)
                )
                ->orderBy('id_cola_pantalla')
                ->first();
        }

        // Si todos los disponibles estan en uso en otras pantallas,
        // toma cualquier pendiente sin importar si esta en uso
        if (!$nou_var_siguiente)
        {
            $nou_var_siguiente = DB::table('Nou_tbl_pant_cola_pantalla')
                ->where('id_pantalla', $nou_var_pantalla_id)
                ->where('reproducido', false)
                ->orderBy('id_cola_pantalla')
                ->first();
        }

        if (!$nou_var_siguiente)
        {
            Log::warning('[NouRotacion] Cola vacia para pantalla ' . $nou_var_pantalla_id);
            return null;
        }

        // Marca el video como reproducido en la cola
        DB::table('Nou_tbl_pant_cola_pantalla')
            ->where('id_cola_pantalla', $nou_var_siguiente->id_cola_pantalla)
            ->update(['reproducido' => true, 'updated_at' => now()]);

        // Registra el video actual en la tabla de rotacion
        NouPantallaRotacion::updateOrCreate(
            ['id_pantalla' => $nou_var_pantalla_id],
            [
                'id_video_anterior' => DB::table('Nou_tbl_pant_rotacion')
                    ->where('id_pantalla', $nou_var_pantalla_id)
                    ->value('id_video_actual'),
                'id_video_actual' => $nou_var_siguiente->id_video,
            ]
        );

        $nou_var_video = NouPantallaVideo::find($nou_var_siguiente->id_video);

        Log::info('[NouRotacion] Video asignado', [
            'pantalla' => $nou_var_pantalla_id,
            'video'    => $nou_var_siguiente->id_video,
            'titulo'   => $nou_var_video?->titulo,
        ]);

        return $nou_var_video;
    }

    /**
     * Retorna el video actualmente asignado a una pantalla.
     * Si no tiene video asignado, toma el siguiente de la cola.
     *
     * @param int $nou_var_pantalla_id ID de la pantalla.
     * @return NouPantallaVideo|null
     */
    public function Nou_fun_video_actual(int $nou_var_pantalla_id): ?NouPantallaVideo
    {
        $nou_var_rotacion = NouPantallaRotacion::where('id_pantalla', $nou_var_pantalla_id)->first();

        if ($nou_var_rotacion?->id_video_actual)
        {
            $nou_var_video = NouPantallaVideo::find($nou_var_rotacion->id_video_actual);
            if ($nou_var_video) { return $nou_var_video; }
        }

        return $this->Nou_fun_siguiente_video($nou_var_pantalla_id);
    }

    /**
     * Recarga la cola de una pantalla con todos los videos de la biblioteca
     * en orden aleatorio. Se llama cuando ya se reprodujeron todos los videos.
     *
     * @param int $nou_var_pantalla_id ID de la pantalla a recargar.
     */
    public function Nou_fun_recargar_cola(int $nou_var_pantalla_id): void
    {
        // Elimina los registros anteriores de esta pantalla
        DB::table('Nou_tbl_pant_cola_pantalla')
            ->where('id_pantalla', $nou_var_pantalla_id)
            ->delete();

        // Obtiene todos los videos disponibles en orden aleatorio
        $nou_arr_videos = NouPantallaVideo::where('estado', 'listo')
            ->inRandomOrder()
            ->get();

        // Inserta cada video como pendiente en la cola de esta pantalla
        foreach ($nou_arr_videos as $nou_var_video)
        {
            DB::table('Nou_tbl_pant_cola_pantalla')->insert([
                'id_pantalla'  => $nou_var_pantalla_id,
                'id_video'     => $nou_var_video->id_video,
                'reproducido'  => false,
                'created_at'   => now(),
                'updated_at'   => now(),
            ]);
        }

        Log::info('[NouRotacion] Cola recargada para pantalla ' . $nou_var_pantalla_id, [
            'total_videos' => $nou_arr_videos->count(),
        ]);
    }

    /**
     * Recalcula los turnos de la cola global cuando se agrega o elimina
     * un video de la biblioteca. Reinicia todas las colas para incluir
     * el cambio en la proxima recarga.
     */
    public function Nou_fun_recalcular_turnos(): void
    {
        // Elimina todas las entradas no reproducidas de todas las colas
        // para que en la proxima solicitud se recargue con los videos actuales
        DB::table('Nou_tbl_pant_cola_pantalla')
            ->where('reproducido', false)
            ->delete();

        // Reinicia el total en la cola global si existe
        DB::table('Nou_tbl_pant_cola_global')
            ->where('id_cola', 1)
            ->update([
                'total_videos' => NouPantallaVideo::where('estado', 'listo')->count(),
                'updated_at'   => now(),
            ]);

        Log::info('[NouRotacion] Colas reiniciadas por cambio en biblioteca');
    }
}