<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Hash;

class HashStudentsCsvPins extends Command
{
    protected $signature = 'sisvot:hash-student-pins
                            {input : Ruta del CSV de entrada}
                            {output : Ruta del CSV de salida}
                            {--keep-pin : Conserva la columna pin en el archivo de salida}';

    protected $description = 'Convierte PIN en texto plano de un CSV de estudiantes a login_pin_hash para importación segura.';

    public function handle(): int
    {
        $inputPath = (string) $this->argument('input');
        $outputPath = (string) $this->argument('output');
        $keepPin = (bool) $this->option('keep-pin');

        if (! is_file($inputPath) || ! is_readable($inputPath)) {
            $this->error("No se puede leer el archivo de entrada: {$inputPath}");

            return self::FAILURE;
        }

        $inputHandle = fopen($inputPath, 'r');
        if (! $inputHandle) {
            $this->error('No fue posible abrir el CSV de entrada.');

            return self::FAILURE;
        }

        $header = fgetcsv($inputHandle);
        if (! $header) {
            fclose($inputHandle);
            $this->error('El CSV de entrada no contiene encabezados.');

            return self::FAILURE;
        }

        $normalizedHeader = array_map(fn ($item) => strtolower(trim((string) $item)), $header);
        $indexes = array_flip($normalizedHeader);

        $requiredColumns = ['full_name', 'grade_level', 'login_code', 'pin'];
        foreach ($requiredColumns as $column) {
            if (! array_key_exists($column, $indexes)) {
                fclose($inputHandle);
                $this->error("Falta la columna requerida '{$column}' en el CSV de entrada.");

                return self::FAILURE;
            }
        }

        $outputHeader = $normalizedHeader;
        if (! in_array('login_pin_hash', $outputHeader, true)) {
            $outputHeader[] = 'login_pin_hash';
        }

        if (! $keepPin) {
            $outputHeader = array_values(array_filter($outputHeader, fn ($column) => $column !== 'pin'));
        }

        $outputDirectory = dirname($outputPath);
        if (! is_dir($outputDirectory)) {
            mkdir($outputDirectory, 0777, true);
        }

        $outputHandle = fopen($outputPath, 'w');
        if (! $outputHandle) {
            fclose($inputHandle);
            $this->error("No fue posible crear el archivo de salida: {$outputPath}");

            return self::FAILURE;
        }

        fputcsv($outputHandle, $outputHeader);

        $processed = 0;
        $skipped = 0;
        $line = 1;

        while (($row = fgetcsv($inputHandle)) !== false) {
            $line++;

            if (count(array_filter($row, fn ($value) => trim((string) $value) !== '')) === 0) {
                continue;
            }

            $pin = trim((string) ($row[$indexes['pin']] ?? ''));
            if ($pin === '') {
                $this->warn("Línea {$line}: PIN vacío, fila omitida.");
                $skipped++;

                continue;
            }

            $hashedPin = Hash::make($pin);
            $rowAssoc = [];
            foreach ($normalizedHeader as $columnName) {
                $columnIndex = $indexes[$columnName];
                $rowAssoc[$columnName] = (string) ($row[$columnIndex] ?? '');
            }

            $rowAssoc['login_pin_hash'] = $hashedPin;

            if (! $keepPin) {
                unset($rowAssoc['pin']);
            }

            $outputRow = [];
            foreach ($outputHeader as $columnName) {
                $outputRow[] = $rowAssoc[$columnName] ?? '';
            }

            fputcsv($outputHandle, $outputRow);
            $processed++;
        }

        fclose($inputHandle);
        fclose($outputHandle);

        $this->info("Proceso finalizado. Registros convertidos: {$processed}. Omitidos: {$skipped}.");
        $this->line("Archivo generado: {$outputPath}");

        return self::SUCCESS;
    }
}
