<?php
session_start();
require_once __DIR__ . '/../config/db_auto.php';
require_once __DIR__ . '/db_utils.php';
require_once __DIR__ . '/enhanced_validation.php';
require_once __DIR__ . '/import_result_manager.php';
require_once __DIR__ . '/csv_pre_validator.php';
require_once __DIR__ . '/system_logger.php';

use function App\DB\upsert;
use App\Utils\ImportValidator;
use App\Utils\ImportResultManager;
use App\Utils\CSVPreValidator;

$logger = SystemLogger::getInstance();

// Verificar autenticación
if (!isset($_SESSION['user_id'])) {
    $logger->warning('Intento de importación de matrículas sin autenticación', 'IP: ' . ($_SERVER['REMOTE_ADDR'] ?? 'N/A'));
    header('Location: ../views/login.php');
    exit;
}

// Definir el encabezado aquí para que esté disponible tanto para la validación como para la plantilla de descarga.
$expected_header = [
    'run_alumno',
    'grado_id',
    'fecha_matricula',
    'edad',
    'repitente',
    'grado_repitencia',
    'colegio_procedencia',
    'alumno_pie',
    'hermanos_escuela',
    'grado_hermanos',
    'nacionalidad',
    'domicilio',
    'observacion_alejamiento',
    'integrantes_familia',
    'orden_alejamiento',
    'programa_social',
    'etnia',
    'internet_hogar',
    'smartphone',
    'computador_hogar',
    'opta_religion',
    'religion',
    'transporte',
    'sector',
    'junaeb',
    'uso_imagen',
    'vive_con',
    'sistema_salud',
    'alergias',
    'enfermedad_cuidado',
    'medicamento_contraindicado',
    'medicamento_uso_diario',
    'observaciones_salud',
    // Nuevos campos para el apoderado
    'run_apoderado',
    'nombre_apoderado',
    'ap_paterno_apoderado',
    'ap_materno_apoderado',
    'parentesco_apoderado',
    'telefono_apoderado',
    'rol_apoderado'
];

if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['csv_file'])) {
    $result_manager = new ImportResultManager();
    $filename = $_FILES['csv_file']['tmp_name'];

    // Pre-validación del archivo
    $pre_validator = new CSVPreValidator();
    $pre_validation = $pre_validator->validateFile($filename, $expected_header);

    if (!empty($pre_validation['errors'])) {
        $error_html = '<h4>Errores en el archivo CSV:</h4><ul>';
        foreach ($pre_validation['errors'] as $error) {
            $error_html .= '<li>' . htmlspecialchars($error) . '</li>';
        }
        $error_html .= '</ul>';

        $_SESSION['import_message'] = $error_html;
        $_SESSION['import_status'] = 'error';
        $logger->error('Error en pre-validación de matrículas', 'Archivo rechazado: ' . implode(', ', $pre_validation['errors']));
        header('Location: ../views/importacion.php?tab=matriculas');
        exit;
    }

    // Mostrar advertencias si las hay
    if (!empty($pre_validation['warnings'])) {
        foreach ($pre_validation['warnings'] as $warning) {
            $result_manager->addWarning($warning);
        }
    }

    if (($handle = fopen($filename, "r")) !== FALSE) {
        $header = array_map('trim', fgetcsv($handle, 2000, ","));
        $result_manager->setTotalRows($pre_validation['stats']['total_rows']);

        $pdo->beginTransaction();
        try {
            $row_number = 1; // Para tracking de errores
            while (($data = fgetcsv($handle, 2000, ",")) !== FALSE) {
                $row_number++;

                if (empty(array_filter($data))) {
                    $result_manager->incrementSkipped();
                    continue;
                }

                $row = array_combine($expected_header, $data);

                // --- Normalización de datos ---
                // Normalizar campos SI/NO para consistencia y flexibilidad.
                $boolean_fields = [
                    'alumno_pie',
                    'computador_hogar',
                    'hermanos_escuela',
                    'internet_hogar',
                    'junaeb',
                    'opta_religion',
                    'orden_alejamiento',
                    'repitente',
                    'smartphone',
                    'transporte',
                    'uso_imagen'
                ];

                foreach ($boolean_fields as $field) {
                    if (isset($row[$field])) {
                        $value = strtoupper(trim($row[$field]));
                        // Aceptar 'SI', 'S', '1' como afirmativo y 'NO', 'N', '0' como negativo.
                        if (in_array($value, ['SI', 'S', '1'])) {
                            $row[$field] = 1;
                        } elseif (in_array($value, ['NO', 'N', '0'])) {
                            $row[$field] = 0;
                        }
                    }
                }

                // 1. Validar RUN y encontrar alumno_id
                $run_alumno_raw = $row['run_alumno'] ?? '';
                $run_alumno_cleaned = preg_replace('/[^0-9kK]/', '', strtoupper($run_alumno_raw));

                $stmt = $pdo->prepare("SELECT id FROM alumnos WHERE REPLACE(run, '-', '') = ?");
                $stmt->execute([$run_alumno_cleaned]);
                $alumno = $stmt->fetch(PDO::FETCH_ASSOC);

                if (!$alumno) {
                    $result_manager->addError("Alumno con RUN " . htmlspecialchars($run_alumno_raw) . " no encontrado.", $row_number);
                    continue;
                }
                $alumno_id = $alumno['id'];

                // 2. Preparar y validar datos de matrícula
                $fecha_matricula_raw = $row['fecha_matricula'];
                $fecha_obj = DateTime::createFromFormat('d/m/Y', $fecha_matricula_raw);

                if (empty($fecha_matricula_raw) || $fecha_obj === false) {
                    $result_manager->addError("Fecha de matrícula inválida o en formato incorrecto (se esperaba DD/MM/YYYY) para el RUN " . htmlspecialchars($run_alumno_raw), $row_number);
                    continue;
                }
                $fecha_matricula_db = $fecha_obj->format('Y-m-d');
                $mes_matricula = (int)$fecha_obj->format('n'); // Mes sin ceros iniciales
                $anio_matricula = (int)$fecha_obj->format('Y');

                // Regla de negocio: Si la matrícula es en diciembre, es para el año siguiente.
                // De lo contrario, es para el año en curso.
                $anio_escolar = ($mes_matricula == 12) ? $anio_matricula + 1 : $anio_matricula;

                // 3. Separar datos sociales y de salud
                $social_fields = [
                    'edad',
                    'repitente',
                    'grado_repitencia',
                    'colegio_procedencia',
                    'alumno_pie',
                    'hermanos_escuela',
                    'grado_hermanos',
                    'nacionalidad',
                    'domicilio',
                    'observacion_alejamiento',
                    'integrantes_familia',
                    'orden_alejamiento',
                    'programa_social',
                    'etnia',
                    'internet_hogar',
                    'smartphone',
                    'computador_hogar',
                    'opta_religion',
                    'religion',
                    'transporte',
                    'sector',
                    'junaeb',
                    'uso_imagen',
                    'vive_con'
                ];

                $salud_fields = [
                    'sistema_salud',
                    'alergias',
                    'enfermedad_cuidado',
                    'medicamento_contraindicado',
                    'medicamento_uso_diario'
                ];
                if (isset($row['observaciones_salud'])) {
                    $salud_fields[] = 'observaciones_salud';
                }
                if (isset($row['observaciones'])) {
                    $salud_fields[] = 'observaciones';
                }

                $social_data = array_filter(
                    array_intersect_key($row, array_flip($social_fields)),
                    fn($v) => $v !== ''
                );
                $salud_data = array_filter(
                    array_intersect_key($row, array_flip($salud_fields)),
                    fn($v) => $v !== ''
                );

                // 4. Ejecutar las inserciones/actualizaciones
                $grado_id = intval($row['grado_id'] ?? 0);

                // Validación mejorada del grado_id
                if ($grado_id <= 0 || !ImportValidator::validateGradoId($pdo, $grado_id)) {
                    $error_msg = "El 'grado_id' ($grado_id) es inválido o no existe en el sistema para el RUN " .
                        htmlspecialchars($run_alumno_raw);
                    $result_manager->addError($error_msg, $row_number);
                    continue;
                }

                // Validación de seguridad para campos de texto
                foreach ($row as $field => $value) {
                    if (is_string($value) && !ImportValidator::validateSafeString($value)) {
                        $error_msg = "Contenido sospechoso detectado en campo '$field' para RUN " .
                            htmlspecialchars($run_alumno_raw);
                        $result_manager->addError($error_msg, $row_number);
                        continue 2; // Saltar a la siguiente fila
                    }
                }

                // Al insertar o actualizar, nos aseguramos de que el estado sea 'ACTIVA'.
                // Esto es útil si un alumno fue retirado y se vuelve a matricular.
                $sql_matricula = 'INSERT INTO matriculas (alumno_id, anio, grado_id, fecha_matricula, estado) 
                                  VALUES (?, ?, ?, ?, "ACTIVA") 
                                  ON DUPLICATE KEY UPDATE 
                                      fecha_matricula = VALUES(fecha_matricula), 
                                      grado_id = VALUES(grado_id), 
                                      estado = "ACTIVA"';
                $pdo->prepare($sql_matricula)->execute([
                    $alumno_id,
                    $anio_escolar,
                    $grado_id,
                    $fecha_matricula_db
                ]);

                if (!empty($social_data)) {
                    upsert($pdo, 'social_alumno', $social_data, 'alumno_id', $alumno_id);
                }
                if (!empty($salud_data)) {
                    upsert($pdo, 'salud_alumno', $salud_data, 'alumno_id', $alumno_id);
                }

                // 5. Procesar y asociar apoderado (si existe en el CSV)
                $run_apoderado_raw = $row['run_apoderado'] ?? '';
                if (!empty($run_apoderado_raw)) {
                    $run_apoderado_cleaned = preg_replace('/[^0-9kK]/', '', strtoupper($run_apoderado_raw));
                    if (strlen($run_apoderado_cleaned) > 1) {
                        $run_apoderado_formatted = substr($run_apoderado_cleaned, 0, -1) . '-' . substr($run_apoderado_cleaned, -1);
                    } else {
                        $run_apoderado_formatted = $run_apoderado_cleaned;
                    }

                    // Preparar datos del apoderado para el upsert
                    $apoderado_data = [
                        'nombre' => $row['nombre_apoderado'],
                        'ap_paterno' => $row['ap_paterno_apoderado'],
                        'ap_materno' => $row['ap_materno_apoderado'],
                        'parentesco' => $row['parentesco_apoderado'],
                        'telefono' => $row['telefono_apoderado'],
                    ];
                    $apoderado_data = array_filter($apoderado_data, fn($v) => $v !== '');

                    // Validaciones adicionales para apoderado
                    if (
                        !empty($apoderado_data['telefono']) &&
                        !ImportValidator::validatePhone($apoderado_data['telefono'])
                    ) {
                        $warning_msg = "Teléfono del apoderado inválido para RUN alumno " .
                            htmlspecialchars($run_alumno_raw) . ". Se omitirá el teléfono.";
                        $result_manager->addWarning($warning_msg, $row_number);
                        unset($apoderado_data['telefono']);
                    }

                    if (
                        !empty($apoderado_data['parentesco']) &&
                        !ImportValidator::validateParentesco($apoderado_data['parentesco'])
                    ) {
                        $warning_msg = "Parentesco del apoderado inválido para RUN alumno " .
                            htmlspecialchars($run_alumno_raw) . ". Se omitirá el parentesco.";
                        $result_manager->addWarning($warning_msg, $row_number);
                        unset($apoderado_data['parentesco']);
                    }

                    // Crear o actualizar el familiar
                    if (!empty($apoderado_data)) {
                        upsert($pdo, 'familiares', $apoderado_data, 'run', $run_apoderado_formatted);
                    }

                    // Obtener el ID del familiar para asociarlo
                    $stmt_fam = $pdo->prepare("SELECT id FROM familiares WHERE run = ?");
                    $stmt_fam->execute([$run_apoderado_formatted]);
                    $familiar = $stmt_fam->fetch(PDO::FETCH_ASSOC);

                    if ($familiar) {
                        $familiar_id = $familiar['id'];
                        // Rol por defecto si no se especifica. Acepta múltiples roles separados por coma.
                        $roles_string = !empty($row['rol_apoderado']) ?
                            $row['rol_apoderado'] : 'APODERADO TITULAR';
                        $roles = array_map('trim', explode(',', $roles_string));

                        // Limpiar roles existentes para este familiar y alumno
                        $deleteStmt = $pdo->prepare(
                            'DELETE FROM alumno_familiar WHERE alumno_id = ? AND familiar_id = ?'
                        );
                        $deleteStmt->execute([$alumno_id, $familiar_id]);

                        // Insertar cada rol en una fila separada
                        $sql_asoc = 'INSERT INTO alumno_familiar (alumno_id, familiar_id, tipo_relacion) 
                                    VALUES (?, ?, ?)';
                        $stmt_asoc = $pdo->prepare($sql_asoc);
                        foreach ($roles as $rol) {
                            if (!empty($rol)) {
                                $stmt_asoc->execute([$alumno_id, $familiar_id, $rol]);
                            }
                        }
                    }
                }

                $result_manager->incrementProcessed();
            }

            $pdo->commit();
            $stats = $result_manager->getStats();
            $logger->data(
                'Importación de matrículas completada',
                "Procesados: {$stats['processed']}, Errores: {$stats['errors']}, Advertencias: {$stats['warnings']}"
            );
        } catch (Throwable $e) {
            $pdo->rollBack();
            $result_manager->addError("Error crítico durante la importación: " . $e->getMessage());
            $logger->error(
                'Error crítico en importación de matrículas',
                $e->getMessage()
            );
        }

        fclose($handle);

        // Generar reporte de resultados
        $report_html = $result_manager->generateReport();
        $stats = $result_manager->getStats();

        if ($stats['errors'] > 0) {
            $_SESSION['import_status'] = 'error';
        } elseif ($stats['warnings'] > 0) {
            $_SESSION['import_status'] = 'warning';
        } else {
            $_SESSION['import_status'] = 'success';
        }
        $_SESSION['import_message'] = $report_html;
    }
}

header('Location: ../views/importacion.php?tab=matriculas');
exit;
