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

declare(strict_types=1);

/**
 * Cursos desde un archivo JSON.
 *
 *   bin/curso importar estructura.json [--publicar]
 *   bin/curso importar estructura.json --ensayo     ← valida y dice qué haría, sin tocar nada
 *   bin/curso exportar excel-basico > estructura.json
 *   bin/curso plantilla > nuevo.json
 *
 * Armar un curso de veinte actividades a mano son veinte formularios. Con un archivo se
 * escribe la estructura de una vez y después se van colgando los recursos: la dirección
 * del video, el PDF, el objeto interactivo. Al terminar, el script dice exactamente qué
 * quedó pendiente.
 *
 * Importar es idempotente por slug: volver a pasar el mismo archivo actualiza el curso en
 * vez de duplicarlo. Lo que ya no aparece en el archivo NO se borra —una actividad
 * retirada del JSON puede tener avance de gente— y se avisa para que se decida a mano.
 */

use App\Core\Kernel;
use App\Modules\Catalogo\Models\Curso;
use App\Modules\Catalogo\Services\EsqueletoDeCurso;
use App\Modules\Catalogo\Services\EstructuraDeCurso;
use App\Modules\Objetos\Models\Objeto;

require dirname(__DIR__) . '/vendor/autoload.php';
$base = dirname(__DIR__);
Dotenv\Dotenv::createImmutable($base)->safeLoad();
(new Kernel($base))->boot();

$orden     = $argv[1] ?? '';
$argumento = $argv[2] ?? '';
$banderas  = array_slice($argv, 2);

$ensayo   = in_array('--ensayo', $banderas, true);
$publicar = in_array('--publicar', $banderas, true);

exit(match ($orden) {
    'importar' => importar($argumento, $ensayo, $publicar),
    'exportar' => exportar($argumento),
    'plantilla' => plantilla(),
    'objetos'  => listarObjetos(),
    default    => uso(),
});

function uso(): int
{
    fwrite(STDERR, <<<TXT
    Uso:
      bin/curso importar <archivo.json> [--ensayo] [--publicar]
      bin/curso exportar <slug>
      bin/curso plantilla
      bin/curso objetos            ← los slugs para el campo «objeto»

    TXT);

    return 1;
}

function importar(string $ruta, bool $ensayo, bool $publicar): int
{
    if ($ruta === '' || !is_file($ruta)) {
        fwrite(STDERR, "No encuentro el archivo: $ruta\n");
        return 1;
    }

    $lectura = (new EsqueletoDeCurso())->leer((string) file_get_contents($ruta));

    if (!$lectura['ok']) {
        fwrite(STDERR, "El archivo tiene problemas:\n");
        foreach ($lectura['errores'] as $error) {
            fwrite(STDERR, "  · $error\n");
        }
        return 1;
    }

    $datos    = $lectura['curso'];
    $unidades = $lectura['unidades'];

    if ($ensayo) {
        printf("Ensayo: no se escribe nada.\n\n");
        resumir($datos, $unidades);
        return 0;
    }

    // La escritura vive en el servicio: la pantalla de gestión hace exactamente lo mismo,
    // y dos copias de esta lógica se separarían en el primer cambio.
    $r = (new EstructuraDeCurso())->aplicar($datos, $unidades, $publicar);

    printf("Curso «%s» (%s) · %s\n", $r['curso']->titulo, $r['curso']->slug, $r['curso']->estado);
    printf("  %d unidades · %d actividades\n", $r['unidades'], $r['actividades']);

    if ($r['avisos'] !== []) {
        printf("\nAvisos:\n");
        foreach ($r['avisos'] as $aviso) {
            printf("  · %s\n", $aviso);
        }
    }

    if ($r['huerfanas'] !== []) {
        printf("\nEn el curso pero no en el archivo (no se tocaron):\n");
        foreach ($r['huerfanas'] as $titulo) {
            printf("  · %s\n", $titulo);
        }
    }

    $curso  = $r['curso'];
    $faltan = EsqueletoDeCurso::loQueFalta($unidades);

    if ($faltan !== []) {
        printf("\nRecursos por colgar:\n");
        foreach ($faltan as $pendiente) {
            printf("  · %s\n", $pendiente);
        }
        printf("\n  Se cuelgan en /admin/cursos/%s\n", $curso->slug);
    } else {
        printf("\nNo falta ningún recurso.\n");
    }

    return 0;
}

/** @param array<int,array<string,mixed>> $unidades */
function resumir(array $datos, array $unidades): void
{
    printf("Curso «%s» (%s) · %s · %s\n", $datos['titulo'], $datos['slug'], $datos['nivel'], $datos['estado']);

    foreach ($unidades as $u) {
        printf("\n  %d. %s\n", $u['numero'], $u['titulo']);

        foreach ($u['actividades'] as $a) {
            printf("     %d. [%-10s] %-42s %s\n", $a['orden'], $a['tipo'], $a['titulo'], $a['regla_completitud']);
        }
    }

    $faltan = EsqueletoDeCurso::loQueFalta($unidades);

    if ($faltan !== []) {
        printf("\n  Recursos por colgar:\n");
        foreach ($faltan as $pendiente) {
            printf("    · %s\n", $pendiente);
        }
    }
}

/**
 * Un curso existente en formato de esqueleto.
 *
 * Sirve para copiar la estructura de algo que ya funciona en vez de escribirla desde cero,
 * y para llevarse un curso de una instalación a otra.
 */
function exportar(string $slug): int
{
    $curso = Curso::query()->where('slug', $slug)->first();

    if ($curso === null) {
        fwrite(STDERR, "No existe el curso: $slug\n");
        return 1;
    }

    echo json_encode(
        EstructuraDeCurso::exportar($curso),
        JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES,
    ) . "\n";

    return 0;
}

/**
 * Los objetos interactivos disponibles, con el slug que hay que escribir en el archivo.
 *
 * Sin esto hay que ir a buscarlo a la base o adivinarlo: el rosco se llama «rosco_excel»
 * y no «rosco-de-excel», y el error solo aparece al importar.
 */
function listarObjetos(): int
{
    $objetos = Objeto::query()->where('archivado', false)->orderBy('titulo')->get();

    if ($objetos->isEmpty()) {
        printf("No hay objetos disponibles. Se registran con bin/importar-objetos.\n");
        return 0;
    }

    printf("Para el campo «objeto» de una actividad de tipo «objeto»:\n\n");

    foreach ($objetos as $objeto) {
        printf("  %-34s %s%s\n", $objeto->slug, $objeto->titulo, $objeto->emite_progreso ? '' : '  (no reporta avance)');
    }

    printf("\nHay %d más archivados. Vuelven con: bin/importar-objetos --desarchivar\n",
        Objeto::query()->where('archivado', true)->count());

    return 0;
}

/** Un archivo de partida con un ejemplo de cada tipo y sus campos comentados en el resumen. */
function plantilla(): int
{
    echo json_encode(
        EstructuraDeCurso::plantilla(),
        JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES,
    ) . "\n";

    return 0;
}
