#!/usr/bin/env php
<?php

declare(strict_types=1);

/**
 * Cierra las inscripciones de quien ya terminó su curso pero quedó marcado como «activa».
 *
 * Hasta ahora nadie escribía ese estado: el alumno veía su curso al 100% y recibía su
 * certificado, pero la inscripción seguía abierta y la analítica informaba cero cursos
 * terminados. Este comando repara lo que quedó atrás; de aquí en adelante lo hace solo
 * ServicioProgreso al caer la última actividad obligatoria.
 *
 * Es idempotente: correrlo dos veces no cambia nada la segunda.
 *
 * bin/cerrar-inscripciones [--aplicar]
 */

use App\Core\Kernel;
use App\Modules\Inscripciones\Models\Inscripcion;
use Illuminate\Database\Capsule\Manager as DB;

require dirname(__DIR__) . '/vendor/autoload.php';

$base = dirname(__DIR__);
Dotenv\Dotenv::createImmutable($base)->safeLoad();
(new Kernel($base))->boot();

$aplicar = in_array('--aplicar', $argv, true);

$abiertas = Inscripcion::query()->where('estado', 'activa')->get();
$cerradas = 0;

foreach ($abiertas as $inscripcion) {
    $pendientes = DB::table('actividades as a')
        ->leftJoin('progreso as p', function ($join) use ($inscripcion): void {
            $join->on('p.actividad_id', '=', 'a.id')
                 ->where('p.usuario_id', '=', $inscripcion->usuario_id)
                 ->where('p.estado', '=', 'completada');
        })
        ->where('a.curso_id', $inscripcion->curso_id)
        ->where('a.obligatoria', true)
        ->whereNull('p.id')
        ->exists();

    // Un curso sin actividades obligatorias no está «terminado»: está vacío. Cerrarlo
    // inflaría la tasa de completitud con cursos que nadie cursó.
    $tieneObligatorias = DB::table('actividades')
        ->where('curso_id', $inscripcion->curso_id)
        ->where('obligatoria', true)
        ->exists();

    if ($pendientes || !$tieneObligatorias) {
        continue;
    }

    printf("  usuario %d · curso %d → terminado\n", $inscripcion->usuario_id, $inscripcion->curso_id);

    if ($aplicar) {
        $inscripcion->estado = 'completada';
        // La fecha real es la de la última actividad completada, no la de hoy: fechar el
        // término el día en que se corre un script de reparación falsea el histórico.
        $inscripcion->completado_en = DB::table('progreso as p')
            ->join('actividades as a', 'a.id', '=', 'p.actividad_id')
            ->where('p.usuario_id', $inscripcion->usuario_id)
            ->where('a.curso_id', $inscripcion->curso_id)
            ->where('p.estado', 'completada')
            ->max('p.completado_en') ?? date('Y-m-d H:i:s');
        $inscripcion->save();
    }

    $cerradas++;
}

printf(
    "\n%d inscripción(es) %s.\n",
    $cerradas,
    $aplicar ? 'cerradas' : 'por cerrar — vuelve a correrlo con --aplicar',
);
