<?php
// modules/admin/importar_usuarios.php
// ─────────────────────────────────────────────────────────────────
//  Carga masiva de usuarios desde Excel (.xlsx)
//  Requiere: composer require phpoffice/phpspreadsheet
// ─────────────────────────────────────────────────────────────────
require_once __DIR__ . '/../../config/app.php';
require_once __DIR__ . '/../../includes/auth.php';
require_once __DIR__ . '/../../includes/functions.php';
require_once __DIR__ . '/../../includes/flash.php';
requireRol(ROL_ADMIN);

$user        = currentUser();
$db          = getDB();
$idInstituto = (int)($user['id_instituto'] ?? 0);

// ─── Autoload PhpSpreadsheet ─────────────────────────────────────
$autoload = __DIR__ . '/../../vendor/autoload.php';
if (!file_exists($autoload)) {
    if (isset($_GET['accion']) && $_GET['accion'] === 'plantilla') {
        http_response_code(500);
        die('PhpSpreadsheet no instalado. Ejecuta: composer require phpoffice/phpspreadsheet');
    }
    flashSet('err', 'Librería PhpSpreadsheet no instalada. Ejecuta: composer require phpoffice/phpspreadsheet');
    header('Location: usuarios.php'); exit;
}
require_once $autoload;

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as XlsxWriter;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Cell\DataValidation;

// ═══════════════════════════════════════════════════════════════
//  DESCARGA DE PLANTILLA DINÁMICA
// ═══════════════════════════════════════════════════════════════
if (isset($_GET['accion']) && $_GET['accion'] === 'plantilla') {

    $instSQL = $idInstituto ? " AND id_instituto={$idInstituto}" : '';

    // Datos desde BD (siempre actualizados)
    $rolesArr = $db->query(
        "SELECT nombre FROM roles WHERE activo=1 ORDER BY id_rol"
    )->fetchAll(PDO::FETCH_COLUMN);

    $carrerasArr = $db->query(
        "SELECT nombre FROM carreras WHERE activa=1{$instSQL} ORDER BY nombre"
    )->fetchAll(PDO::FETCH_COLUMN);

    $periodosArr = $db->query(
        "SELECT nombre FROM periodos_academicos WHERE 1=1{$instSQL} ORDER BY id_periodo DESC"
    )->fetchAll(PDO::FETCH_COLUMN);

    if (empty($carrerasArr)) $carrerasArr = ['Sin carreras - crea una primero'];
    if (empty($periodosArr)) $periodosArr = ['Sin periodos - crea uno primero'];

    // Helper: fórmula inline para dropdown (max 253 chars sin comillas externas)
    $inlineFormula = function (array $items): string {
        $limpio = array_map(fn($v) => str_replace(['"', ','], ['', ' '], trim($v)), $items);
        $str    = implode(',', $limpio);
        if (mb_strlen($str) > 253) {
            $str = mb_substr($str, 0, 253);
            $last = mb_strrpos($str, ',');
            if ($last !== false) $str = mb_substr($str, 0, $last);
        }
        return '"' . $str . '"';
    };

    $fRol    = $inlineFormula($rolesArr);
    $fActivo = '"1,0"';
    $fCar    = $inlineFormula($carrerasArr);
    $fPer    = $inlineFormula($periodosArr);

    $maxRow = 502;

    // Crear libro
    $spreadsheet = new Spreadsheet();
    $spreadsheet->getProperties()
        ->setTitle('Plantilla Usuarios SIGVP')
        ->setSubject('Carga masiva de usuarios')
        ->setCreator('SIGVP');

    // ── Hoja 1: INSTRUCCIONES (usa la hoja por defecto — evita hoja huerfana) ──
    $wsI = $spreadsheet->getActiveSheet();
    $wsI->setTitle('INSTRUCCIONES');
    $wsI->getColumnDimension('A')->setWidth(75);

    $lineas = [
        '📋  SIGVP — Plantilla de Carga Masiva de Usuarios',
        '',
        '  📌 INSTRUCCIONES GENERALES',
        '',
        '  1. No modifiques ni elimines los encabezados de la hoja DATOS.',
        '  2. Los datos comienzan en la fila 3. Fila 1 = encabezado, fila 2 = descripcion.',
        '  3. Usa los menus desplegables para ROL, ACTIVO, CARRERA_NOMBRE y PERIODO_INGRESO.',
        '  4. Borra la fila de EJEMPLO antes de subir el archivo.',
        '  5. Maximo 500 usuarios por archivo (filas 3 a 502).',
        '  6. Columnas con * son OBLIGATORIAS para todos los roles.',
        '  7. CARRERA, PERIODO, CODIGO y SEMESTRE solo aplican si ROL = estudiante.',
        '  8. La cedula debe tener 10 digitos.',
        '  9. Si dejas PASSWORD vacio la contrasena inicial sera la cedula del usuario.',
        ' 10. Si el usuario ya existe (misma cedula) NO se modificara.',
        '',
        '  📐 COLUMNAS DE LA PLANTILLA',
        '',
        '  A  * CEDULA            - Cedula (10 digitos)',
        '  B  * NOMBRES           - Nombres en MAYUSCULAS',
        '  C  * APELLIDOS         - Apellidos en MAYUSCULAS',
        '  D  * EMAIL             - Email institucional',
        '  E    EMAIL_PERSONAL    - Email personal (opcional)',
        '  F    TELEFONO          - Telefono/movil (opcional)',
        '  G  * ROL               - Rol del usuario (usar desplegable)',
        '  H    ACTIVO            - 1=Activo, 0=Inactivo (usar desplegable)',
        '  I    PASSWORD          - Contrasena inicial (vacio = usa la cedula)',
        '  J    CARRERA_NOMBRE    - Solo si ROL=estudiante (usar desplegable)',
        '  K    PERIODO_INGRESO   - Solo si ROL=estudiante (usar desplegable)',
        '  L    CODIGO_ESTUDIANTE - Codigo unico (ej: 2024-ISW-001)',
        '  M    SEMESTRE_ACTUAL   - Numero de semestre (1 al 10)',
    ];
    foreach ($lineas as $i => $linea) {
        $wsI->setCellValue('A' . ($i + 1), $linea);
    }
    $wsI->getStyle('A1')->getFont()->setBold(true)->setSize(13)->getColor()->setARGB('FF003366');

    // ── Hoja 2: DATOS ─────────────────────────────────────────
    $wsD = $spreadsheet->createSheet(); // indice 1
    $wsD->setTitle('DATOS');

    $cabeceras = [
        'A'=>'* CEDULA',         'B'=>'* NOMBRES',        'C'=>'* APELLIDOS',
        'D'=>'* EMAIL',           'E'=>'EMAIL_PERSONAL',   'F'=>'TELEFONO',
        'G'=>'* ROL',             'H'=>'ACTIVO',           'I'=>'PASSWORD',
        'J'=>'CARRERA_NOMBRE',    'K'=>'PERIODO_INGRESO',
        'L'=>'CODIGO_ESTUDIANTE', 'M'=>'SEMESTRE_ACTUAL',
    ];
    $subHdrs = [
        'A'=>'Cedula (10 digitos)',           'B'=>'Nombres (MAYUSCULAS)',
        'C'=>'Apellidos (MAYUSCULAS)',         'D'=>'Email institucional',
        'E'=>'Email personal (opcional)',      'F'=>'Telefono (opcional)',
        'G'=>'Ver lista desplegable',          'H'=>'1=Activo  0=Inactivo',
        'I'=>'Vacio = usa la cedula',          'J'=>'Carrera (desplegable)',
        'K'=>'Periodo ingreso (desplegable)',  'L'=>'Codigo (ej: 2024-ISW-001)',
        'M'=>'Numero semestre (1-10)',
    ];

    foreach ($cabeceras as $col => $val) $wsD->setCellValue("{$col}1", $val);
    foreach ($subHdrs  as $col => $val) $wsD->setCellValue("{$col}2", $val);

    // Fila ejemplo
    $wsD->setCellValue('A3', '0912345698');
    $wsD->setCellValue('B3', 'JUAN CARLOS');
    $wsD->setCellValue('C3', 'PEREZ MORA');
    $wsD->setCellValue('D3', 'jperez@instituto.edu.ec');
    $wsD->setCellValue('E3', 'jperez@gmail.com');
    $wsD->setCellValue('F3', '0991234567');
    $wsD->setCellValue('G3', 'estudiante');
    $wsD->setCellValue('H3', '1');
    $wsD->setCellValue('I3', '');
    $wsD->setCellValue('J3', $carrerasArr[0]);
    $wsD->setCellValue('K3', $periodosArr[0]);
    $wsD->setCellValue('L3', '2024-ISW-001');
    $wsD->setCellValue('M3', 1);

    // Estilos encabezado
    $wsD->getStyle('A1:M1')->applyFromArray([
        'font'      => ['bold'=>true, 'color'=>['argb'=>'FFFFFFFF'], 'size'=>11],
        'fill'      => ['fillType'=>Fill::FILL_SOLID, 'startColor'=>['argb'=>'FF003366']],
        'alignment' => ['horizontal'=>Alignment::HORIZONTAL_CENTER, 'vertical'=>Alignment::VERTICAL_CENTER],
        'borders'   => ['allBorders'=>['borderStyle'=>Border::BORDER_THIN, 'color'=>['argb'=>'FFFFFFFF']]],
    ]);
    // Azul mas claro para columnas J y K (campos nuevos)
    $wsD->getStyle('J1:K1')->getFill()->setFillType(Fill::FILL_SOLID)
        ->getStartColor()->setARGB('FF0070C0');

    // Estilos subheader
    $wsD->getStyle('A2:M2')->applyFromArray([
        'font'      => ['italic'=>true, 'color'=>['argb'=>'FF555555'], 'size'=>9],
        'fill'      => ['fillType'=>Fill::FILL_SOLID, 'startColor'=>['argb'=>'FFD9E1F2']],
        'alignment' => ['horizontal'=>Alignment::HORIZONTAL_CENTER],
    ]);

    // Estilos fila ejemplo
    $wsD->getStyle('A3:M3')->applyFromArray([
        'fill'    => ['fillType'=>Fill::FILL_SOLID, 'startColor'=>['argb'=>'FFFFF2CC']],
        'font'    => ['color'=>['argb'=>'FF7F6000']],
        'borders' => ['allBorders'=>['borderStyle'=>Border::BORDER_THIN, 'color'=>['argb'=>'FFBFBFBF']]],
    ]);

    // Anchos de columna
    foreach ([
        'A'=>16,'B'=>20,'C'=>22,'D'=>30,'E'=>28,'F'=>14,
        'G'=>16,'H'=>13,'I'=>18,'J'=>32,'K'=>24,'L'=>24,'M'=>16,
    ] as $col => $w) $wsD->getColumnDimension($col)->setWidth($w);

    $wsD->getRowDimension(1)->setRowHeight(22);
    $wsD->freezePane('A3');

    // ── Dropdowns con formulas INLINE ─────────────────────────
    // Sin referencias a otras hojas -> funciona en todas las versiones de Excel
    $makeDV = function (string $formula): DataValidation {
        $dv = new DataValidation();
        $dv->setType(DataValidation::TYPE_LIST);
        $dv->setErrorStyle(DataValidation::STYLE_INFORMATION);
        $dv->setAllowBlank(true);
        $dv->setShowDropDown(false); // false = MOSTRAR flecha en Excel
        $dv->setShowInputMessage(false);
        $dv->setShowErrorMessage(true);
        $dv->setErrorTitle('Valor invalido');
        $dv->setError('Selecciona un valor de la lista.');
        $dv->setFormula1($formula);
        return $dv;
    };

    $dvRol = $makeDV($fRol); $dvRol->setSqref("G3:G{$maxRow}");
    $wsD->getCell('G3')->setDataValidation($dvRol);

    $dvAct = $makeDV($fActivo); $dvAct->setSqref("H3:H{$maxRow}");
    $wsD->getCell('H3')->setDataValidation($dvAct);

    $dvCar = $makeDV($fCar); $dvCar->setSqref("J3:J{$maxRow}");
    $wsD->getCell('J3')->setDataValidation($dvCar);

    $dvPer = $makeDV($fPer); $dvPer->setSqref("K3:K{$maxRow}");
    $wsD->getCell('K3')->setDataValidation($dvPer);

    $dvSem = new DataValidation();
    $dvSem->setType(DataValidation::TYPE_WHOLE);
    $dvSem->setOperator(DataValidation::OPERATOR_BETWEEN);
    $dvSem->setAllowBlank(true)->setShowErrorMessage(true);
    $dvSem->setErrorTitle('Semestre invalido')->setError('Ingresa un numero entre 1 y 10.');
    $dvSem->setFormula1('1')->setFormula2('10');
    $dvSem->setSqref("M3:M{$maxRow}");
    $wsD->getCell('M3')->setDataValidation($dvSem);

    // Hoja DATOS activa al abrir
    $spreadsheet->setActiveSheetIndex(1);

    header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
    header('Content-Disposition: attachment; filename="plantilla_usuarios_sigvp.xlsx"');
    header('Cache-Control: max-age=0');
    (new XlsxWriter($spreadsheet))->save('php://output');
    exit;
}

// ═══════════════════════════════════════════════════════════════
//  IMPORTACION (POST)
// ═══════════════════════════════════════════════════════════════
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    header('Location: usuarios.php'); exit;
}

// Validar archivo
if (empty($_FILES['archivo_excel']['tmp_name']) || $_FILES['archivo_excel']['error'] !== UPLOAD_ERR_OK) {
    flashSet('err', 'No se recibio ningun archivo o hubo un error en la subida.');
    header('Location: usuarios.php'); exit;
}
$ext = strtolower(pathinfo($_FILES['archivo_excel']['name'], PATHINFO_EXTENSION));
if (!in_array($ext, ['xlsx','xls'], true)) {
    flashSet('err', 'Formato no valido. Sube un archivo .xlsx o .xls.');
    header('Location: usuarios.php'); exit;
}

// Leer Excel
try {
    $spreadsheet = IOFactory::load($_FILES['archivo_excel']['tmp_name']);
} catch (\Exception $e) {
    flashSet('err', 'No se pudo leer el archivo Excel: ' . $e->getMessage());
    header('Location: usuarios.php'); exit;
}

// Buscar hoja DATOS
$ws = null;
foreach ($spreadsheet->getSheetNames() as $shName) {
    if (strtoupper(trim($shName)) === 'DATOS') {
        $ws = $spreadsheet->getSheetByName($shName);
        break;
    }
}
if (!$ws) $ws = $spreadsheet->getActiveSheet();

// Validar rango
$highestRow = $ws->getHighestDataRow();
if ($highestRow < 3) {
    flashSet('err', 'El archivo no tiene datos. Los datos comienzan en la fila 3.');
    header('Location: usuarios.php'); exit;
}
if ($highestRow > 502) {
    flashSet('err', 'El archivo supera el limite de 500 filas. Divide el archivo.');
    header('Location: usuarios.php'); exit;
}

// Precargar catalogos
$instSQL = $idInstituto ? " AND id_instituto={$idInstituto}" : '';

$rolesDB  = $db->query("SELECT id_rol, nombre FROM roles WHERE activo=1")->fetchAll();
$rolesMap = [];
foreach ($rolesDB as $r) {
    $rolesMap[strtolower(trim($r['nombre']))] = (int)$r['id_rol'];
}

$carrerasDB  = $db->query("SELECT id_carrera, nombre FROM carreras WHERE activa=1{$instSQL}")->fetchAll();
$carrerasMap = [];
foreach ($carrerasDB as $c) {
    $carrerasMap[mb_strtolower(trim($c['nombre']))] = (int)$c['id_carrera'];
}

$periodosDB  = $db->query("SELECT id_periodo, nombre FROM periodos_academicos WHERE 1=1{$instSQL} ORDER BY id_periodo DESC")->fetchAll();
$periodosMap = [];
$ultimoPeriodo = null;
foreach ($periodosDB as $p) {
    $periodosMap[mb_strtolower(trim($p['nombre']))] = (int)$p['id_periodo'];
    if ($ultimoPeriodo === null) $ultimoPeriodo = (int)$p['id_periodo'];
}

// Columnas: A=cedula B=nombres C=apellidos D=email E=email_personal F=telefono
//           G=rol H=activo I=password J=carrera_nombre K=periodo_ingreso
//           L=codigo_estudiante M=semestre_actual
$creados = 0; $ya_registrados = []; $errores = [];

for ($row = 3; $row <= $highestRow; $row++) {
    $cedula     = trim((string)($ws->getCell("A{$row}")->getValue() ?? ''));
    $nombres    = trim((string)($ws->getCell("B{$row}")->getValue() ?? ''));
    $apellidos  = trim((string)($ws->getCell("C{$row}")->getValue() ?? ''));
    $email      = trim((string)($ws->getCell("D{$row}")->getValue() ?? ''));
    $emailPers  = trim((string)($ws->getCell("E{$row}")->getValue() ?? '')) ?: null;
    $telefono   = trim((string)($ws->getCell("F{$row}")->getValue() ?? '')) ?: null;
    $rolNombre  = strtolower(trim((string)($ws->getCell("G{$row}")->getValue() ?? '')));
    $activoVal  = trim((string)($ws->getCell("H{$row}")->getValue() ?? '1'));
    $password   = trim((string)($ws->getCell("I{$row}")->getValue() ?? ''));
    $carreraNom = trim((string)($ws->getCell("J{$row}")->getValue() ?? ''));
    $periodoNom = trim((string)($ws->getCell("K{$row}")->getValue() ?? ''));
    $codigoEst  = trim((string)($ws->getCell("L{$row}")->getValue() ?? ''));
    $semestre   = trim((string)($ws->getCell("M{$row}")->getValue() ?? ''));

    if (!$cedula && !$nombres && !$email) continue;

    $filaErr = [];
    if (!$cedula)    $filaErr[] = 'Cedula vacia';
    if (!$nombres)   $filaErr[] = 'Nombres vacio';
    if (!$apellidos) $filaErr[] = 'Apellidos vacio';
    if (!$email)     $filaErr[] = 'Email vacio';
    if ($email && !filter_var($email, FILTER_VALIDATE_EMAIL)) $filaErr[] = 'Email invalido';
    if (!isset($rolesMap[$rolNombre])) $filaErr[] = "Rol '{$rolNombre}' no existe";

    if ($filaErr) {
        $errores[] = "Fila {$row}: " . implode(', ', $filaErr);
        continue;
    }

    $idRol    = $rolesMap[$rolNombre];
    $activo   = ($activoVal === '0' || strtolower($activoVal) === 'no') ? 0 : 1;
    $esAdmin  = ($idRol === ROL_ADMIN);
    $passUsar = $esAdmin ? 'Sigvp2026!' : ($password !== '' ? $password : ($cedula ?: 'Sigvp2026!'));
    $passHash = password_hash($passUsar, PASSWORD_BCRYPT);

    try {
        $stEx = $db->prepare("SELECT id_usuario FROM usuarios WHERE cedula=:c LIMIT 1");
        $stEx->execute([':c' => $cedula]);
        if ($stEx->fetch()) {
            $ya_registrados[] = "{$cedula} (" . strtoupper($nombres) . ' ' . strtoupper($apellidos) . ')';
            continue;
        }

        // Insertar usuario (con id_instituto del admin)
        $db->prepare("
            INSERT INTO usuarios
                (cedula,nombres,apellidos,email,email_personal,telefono,
                 password_hash,id_rol,id_instituto,activo,cambiar_password)
            VALUES (:c,:n,:a,:e,:ep,:tel,:p,:r,:ins,:ac,1)
        ")->execute([
            ':c'=>$cedula, ':n'=>strtoupper($nombres), ':a'=>strtoupper($apellidos),
            ':e'=>$email,  ':ep'=>$emailPers,           ':tel'=>$telefono,
            ':p'=>$passHash, ':r'=>$idRol, ':ins'=>$idInstituto ?: null, ':ac'=>$activo,
        ]);
        $idUsuario = (int)$db->lastInsertId();
        $creados++;

        // Perfil estudiante
        if ($idRol === ROL_ESTUDIANTE && $idUsuario) {
            $idCarrera = $carrerasMap[mb_strtolower($carreraNom)] ?? null;
            $semNum    = is_numeric($semestre) ? (int)$semestre : null;
            $idPeriodo = ($periodoNom !== '') ? ($periodosMap[mb_strtolower($periodoNom)] ?? null) : null;
            if (!$idPeriodo) $idPeriodo = $ultimoPeriodo;

            if ($idCarrera && $codigoEst) {
                $stChk = $db->prepare("SELECT id_estudiante FROM estudiantes WHERE id_usuario=:u");
                $stChk->execute([':u' => $idUsuario]);
                if ($stChk->fetch()) {
                    $db->prepare("UPDATE estudiantes SET id_carrera=:c,id_periodo_ingreso=:p,codigo_estudiante=:cod,semestre_actual=:s WHERE id_usuario=:u")
                       ->execute([':c'=>$idCarrera,':p'=>$idPeriodo,':cod'=>$codigoEst,':s'=>$semNum,':u'=>$idUsuario]);
                } else {
                    $db->prepare("INSERT INTO estudiantes (id_usuario,id_carrera,id_periodo_ingreso,codigo_estudiante,semestre_actual,id_instituto) VALUES (:u,:c,:p,:cod,:s,:ins)")
                       ->execute([':u'=>$idUsuario,':c'=>$idCarrera,':p'=>$idPeriodo,':cod'=>$codigoEst,':s'=>$semNum,':ins'=>$idInstituto ?: null]);
                }
            }
        }

        // Perfil tutor
        if ($idRol === ROL_TUTOR && $idUsuario) {
            $stTut = $db->prepare("SELECT id_tutor FROM tutores WHERE id_usuario=:u");
            $stTut->execute([':u' => $idUsuario]);
            if (!$stTut->fetch()) {
                $db->prepare("INSERT INTO tutores (id_usuario,max_estudiantes) VALUES (:u,5)")
                   ->execute([':u' => $idUsuario]);
            }
        }

    } catch (\PDOException $e) {
        $errores[] = "Fila {$row} ({$cedula}): Error BD - " . $e->getMessage();
    }
}

registrarAudit($user['id'], 'importacion_masiva_usuarios', 'usuarios', null,
    null, ['creados'=>$creados,'ya_registrados'=>count($ya_registrados),'errores'=>count($errores)]);

if ($creados > 0)
    flashSet('ok', "<i class='fa fa-circle-check me-1'></i><strong>{$creados} usuario(s) creado(s)</strong> correctamente.");
if ($ya_registrados) {
    $lista = implode(', ', array_slice($ya_registrados, 0, 10));
    $extra = count($ya_registrados) > 10 ? ' y ' . (count($ya_registrados) - 10) . ' mas' : '';
    flashSet('info', "<i class='fa fa-circle-info me-1'></i><strong>" . count($ya_registrados) . " ya registrado(s)</strong> - no se modificaron: {$lista}{$extra}.");
}
if ($errores) {
    $lista = implode(' · ', array_slice($errores, 0, 5));
    $extra = count($errores) > 5 ? ' (y ' . (count($errores) - 5) . ' mas)' : '';
    flashSet('err', "<i class='fa fa-triangle-exclamation me-1'></i><strong>" . count($errores) . " error(es)</strong>: {$lista}{$extra}");
}
if (!$creados && !$ya_registrados && !$errores)
    flashSet('warn', "No se proceso ninguna fila. Verifica que el archivo tenga datos desde la fila 3.");

header('Location: usuarios.php'); exit;