<?php

namespace App\Http\Controllers;

use App\Models\Matricula;
use App\Models\Postulante;
use App\Models\PlanEstudio;
use App\Models\CursoPlanEstudio;
use App\Models\MatriculaCurso;
use App\Models\Periodo;
use App\Models\Semestre;
use App\Models\Curso;
use App\Models\ResultadoAdmision;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Models\Horario;
use App\Models\Docente;
use App\Models\Instituto;
use Barryvdh\DomPDF\Facade\Pdf; 
use Illuminate\Support\Facades\Crypt;
use App\Models\NotaFinal;
use Illuminate\Contracts\Encryption\DecryptException;

use App\Models\Usuario;
use App\Models\Role;
use App\Models\UsuarioRol;
class MatriculaController extends Controller
{
    // Mostrar la lista de matrículas
    public function index(Request $request)
    {
        // Consulta base con relaciones
        $matriculas = Matricula::with(['postulante', 'planEstudio', 'periodo', 'semestre']);

        // Filtros dinámicos
        if ($request->filled('plan_estudio_id')) {
            $matriculas->where('plan_estudio_id', $request->plan_estudio_id);
        }

        if ($request->filled('semestre_id')) {
            $matriculas->where('semestre_id', $request->semestre_id);
        }

        if ($request->filled('estado')) {
            $matriculas->where('estado', $request->estado);
        }

        if ($request->filled('fecha_matricula')) {
            $matriculas->whereDate('fecha_matricula', $request->fecha_matricula);
        }

        // Ejecutar consulta
        $matriculas = $matriculas->get();

        // Datos para los selects
        $planesEstudio = PlanEstudio::all();
        $semestres = Semestre::all();
        $postulantes = Postulante::all();
        $periodos = Periodo::all();

        // Si es AJAX, retornar solo la tabla
        if ($request->ajax()) {
            return view('matriculas.partials.tabla', compact('matriculas'))->render();
        }

        // Vista completa
        return view('matriculas.index', compact('matriculas', 'planesEstudio', 'semestres', 'postulantes', 'periodos'));
    }


    public function create()
    {
        // Obtener postulantes con vacante desde resultados_admision
        $postulantesConVacante = ResultadoAdmision::where('estado', 'vacante')
            ->with('postulante', 'planEstudio', 'admision') // Asegúrate de traer el plan de estudio
            ->get();

        // Obtener planes de estudio, periodos y semestres activos
        $planesEstudio = PlanEstudio::where('activo', 1)->get();
        $periodos = Periodo::where('activo', 1)->get();
        $semestres = Semestre::where('activo', 1)->get();
        $periodos = Periodo::where('activo', 1)->get(); // o con orden, filtro, etc.
        return view('matriculas.create', compact(
            'postulantesConVacante',
            'planesEstudio',
            'periodos',
            'semestres','periodos'
        ));
    }


    public function store(Request $request)
    {
        //
    }


    // Editar la matrícula
    public function edit($id)
    {
        $matricula = Matricula::findOrFail($id);
        $postulantes = Postulante::all();
        $planesEstudio = PlanEstudio::all();
        $periodos = Periodo::all();
        $semestres = Semestre::all();

        return view('matriculas.edit', compact('matricula', 'postulantes', 'planesEstudio', 'periodos', 'semestres'));
    }

    public function update(Request $request, $id)
{
    $request->validate([
        'codigo_matricula' => 'required|unique:matriculas,codigo_matricula,' . $id,
        'postulante_id' => 'required|exists:postulantes,id_postulante',
        'plan_estudio_id' => 'required|exists:planes_estudio,id',
        'periodo_id' => 'required|exists:periodos,id',
        'semestre_id' => 'required|exists:semestres,id',
        'estado' => 'required|in:Pendiente,Matriculado,Retirado,Convalidado,Repitencia',
        'fecha_matricula' => 'required|date',
    ]);

    $matricula = Matricula::findOrFail($id);
    $matricula->update([
        'codigo_matricula' => $request->codigo_matricula,
        'postulante_id' => $request->postulante_id,
        'plan_estudio_id' => $request->plan_estudio_id,
        'periodo_id' => $request->periodo_id,
        'semestre_id' => $request->semestre_id,
        'estado' => $request->estado,
        'fecha_matricula' => $request->fecha_matricula,
    ]);

    // ✅ RESPUESTA PARA AJAX
    return response()->json(['message' => 'Matrícula actualizada exitosamente.']);
}


    // Eliminar matrícula
    public function destroy($id)
    {
        $matricula = Matricula::findOrFail($id);
        $matricula->delete();

        return redirect()->route('matriculas.index')->with('success', 'Matrícula eliminada exitosamente.');
    }

    public function show($id)
    {
        // Puedes cargar la matrícula con su ID si deseas mostrarla
        // $matricula = Matricula::findOrFail($id);
        // return view('matriculas.show', compact('matricula'));

        // Por ahora simplemente redirecciona o lanza un 404
        abort(404);
    }



    public function nuevaMatricula1(Request $request, \App\Services\MoodleService $moodle)
{
    $tipoMatrícula = $request->input('tipo_matricula');
    $postulantes = json_decode($request->input('postulantes'), true);
    $periodoId = $request->input('periodo_id');

    if ($tipoMatrícula === 'nueva') {
        foreach ($postulantes as $postulanteData) {

            $planEstudio = PlanEstudio::where('nombre', $postulanteData['planEstudioNombre'])->first();

            if ($planEstudio) {

                // 1) Crear matrícula
                $matricula = Matricula::create([
                    'postulante_id' => $postulanteData['postulante_id'],
                    'plan_estudio_id' => $planEstudio->id,
                    'semestre_id' => 1,
                    'periodo_id' => $periodoId,
                    'estado' => 'Matriculado',
                    'fecha_matricula' => now(),
                    'codigo_matricula' => $postulanteData['dni'] . '-' . Periodo::find($periodoId)->nombre,
                ]);

                // 2) Obtener cursos del semestre 1
                $cursos = Curso::whereHas('planesEstudio', function ($q) use ($planEstudio) {
                    $q->where('plan_estudio_id', $planEstudio->id);
                })->where('semestre_id', 1)->get();

                // 3) Obtener usuario y moodle_user_id
                $postulante = Postulante::find($postulanteData['postulante_id']);
                $usuario = $postulante->usuario; // relación postulante -> usuario
                $moodleUserId = $usuario->moodle_user_id;

                // 4) Registrar cursos y matricular en Moodle
                foreach ($cursos as $curso) {
                    MatriculaCurso::create([
                        'matricula_id' => $matricula->id,
                        'curso_id' => $curso->id,
                        'estado' => 'Inscrito',
                        'fecha_matricula' => now()
                    ]);

                    if ($moodleUserId && $curso->moodle_course_id) {
                        $moodle->matricularUsuario(
                            $moodleUserId,
                            $curso->moodle_course_id,
                            5 // estudiante
                        );
                    }
                }
            }
        }

        return response()->json(['success' => true]);
    }

    return response()->json(['success' => false]);
}

public function nuevaMatricula(Request $request, \App\Services\MoodleService $moodle)
{
    $tipoMatricula = $request->input('tipo_matricula');
    $periodoId     = $request->input('periodo_id');
    $postulantes   = json_decode($request->input('postulantes'), true);

    if ($tipoMatricula !== 'nueva') {
        return response()->json([
            'success' => false,
            'message' => 'Tipo de matrícula no soportado.'
        ], 422);
    }

    if (empty($postulantes)) {
        return response()->json([
            'success' => false,
            'message' => 'No se recibió ningún postulante para matricular.'
        ], 422);
    }

    $periodo = Periodo::find($periodoId);
    if (!$periodo) {
        return response()->json([
            'success' => false,
            'message' => 'Periodo no encontrado.'
        ], 422);
    }

    // Rol estudiante
    $rolEstudiante = Role::where('nombre', 'Estudiante')->first();
    if (!$rolEstudiante) {
        return response()->json([
            'success' => false,
            'message' => 'Rol "Estudiante" no encontrado.'
        ], 500);
    }

    $resumen = [
        'procesados'  => 0,
        'matriculados'=> 0,
        'errores'     => []
    ];

    foreach ($postulantes as $item) {

        DB::beginTransaction();

        try {
            $resumen['procesados']++;

            $postulanteId      = $item['postulante_id'] ?? null;
            $planEstudioNombre = $item['planEstudioNombre'] ?? null;
            $dni               = $item['dni'] ?? null;

            if (!$postulanteId || !$planEstudioNombre || !$dni) {
                throw new \Exception('Datos incompletos para el postulante seleccionado.');
            }

            $postulante = Postulante::find($postulanteId);
            if (!$postulante) {
                throw new \Exception("Postulante con ID {$postulanteId} no encontrado.");
            }

            // 1) Validar vacante
            $resultado = ResultadoAdmision::where('postulante_id', $postulante->id_postulante)
                ->where('estado', 'Vacante')
                ->first();

            if (!$resultado) {
                throw new \Exception("El postulante {$postulante->dni} no tiene resultado 'Vacante'.");
            }

            // 2) Validar que no esté ya matriculado
            $yaMatriculado = Matricula::where('postulante_id', $postulante->id_postulante)
                ->where('periodo_id', $periodoId)
                ->exists();

            if ($yaMatriculado) {
                throw new \Exception("El postulante {$postulante->dni} ya está matriculado en el periodo {$periodo->nombre}.");
            }

            // 3) Obtener plan
            $planEstudio = PlanEstudio::where('nombre', $planEstudioNombre)->first();
            if (!$planEstudio) {
                throw new \Exception("El plan de estudio '{$planEstudioNombre}' no existe.");
            }

            // 4) Usuario local
            $usuario = $postulante->usuario;
            if (!$usuario) {

                $usuario = Usuario::create([
                    'username'      => $postulante->dni,
                    'password_hash' => bcrypt($postulante->dni),
                    'status'        => 1,
                ]);

                $postulante->usuario_id = $usuario->id;
                $postulante->save();
            }

            // 5) Rol Estudiante
            $yaTieneRol = UsuarioRol::where('usuario_id', $usuario->id)
                ->where('rol_id', $rolEstudiante->id)
                ->exists();

            if (!$yaTieneRol) {
                UsuarioRol::create([
                    'usuario_id' => $usuario->id,
                    'rol_id'     => $rolEstudiante->id
                ]);
            }

            // 6) Crear usuario en Moodle si no existe
            if (!$usuario->moodle_user_id) {

                $passwordMoodle = "Alumno@" . $postulante->dni;

                $moodleResponse = $moodle->crearUsuario(
                    $usuario->username,
                    $passwordMoodle,
                    $postulante->nombres,
                    $postulante->apellidos,
                    $postulante->email
                );

                if (isset($moodleResponse[0]['id'])) {
                    $usuario->moodle_user_id = $moodleResponse[0]['id'];
                    $usuario->save();
                }
            }

            // 7) Mover documentos
            $origen = public_path('documentospostulantes/' . $postulante->dni);
            $destinoRel = 'estudiantesdocumentos/' . $postulante->id_postulante;
            $destino = public_path($destinoRel);

            if (file_exists($origen)) {

                if (!file_exists($destino)) {
                    mkdir($destino, 0755, true);
                }

                foreach (scandir($origen) as $file) {
                    if ($file != '.' && $file != '..') {
                        @rename($origen . '/' . $file, $destino . '/' . $file);
                    }
                }

                // actualizar rutas en BD
                $campos = [
                    'foto_postulante',
                    'certificado_estudios',
                    'partida_nacimiento',
                    'copia_dni',
                    'comprobante_pago',
                    'curriculum_archivo',
                ];

                foreach ($campos as $campo) {
                    if (!empty($postulante->$campo)) {
                        $postulante->$campo = str_replace(
                            'documentospostulantes/' . $postulante->dni,
                            $destinoRel,
                            $postulante->$campo
                        );
                    }
                }

                $postulante->save();

                // eliminar carpeta origen
                \Illuminate\Support\Facades\File::deleteDirectory($origen);
            }

            // 8) Grado → Estudiante
            $postulante->grado = 'Estudiante';
            $postulante->save();

            // 9) Crear matrícula
            $matricula = Matricula::create([
                'postulante_id'   => $postulante->id_postulante,
                'plan_estudio_id' => $planEstudio->id,
                'semestre_id'     => 1,
                'periodo_id'      => $periodoId,
                'estado'          => 'Matriculado',
                'fecha_matricula' => now(),
                'codigo_matricula'=> $dni . '-' . $periodo->nombre,
            ]);

            // 10) Cursos del semestre 1
            $cursos = Curso::whereHas('planesEstudio', function ($q) use ($planEstudio) {
                $q->where('plan_estudio_id', $planEstudio->id);
            })->where('semestre_id', 1)->get();

            $moodleUserId = $usuario->moodle_user_id;

            foreach ($cursos as $curso) {
                MatriculaCurso::create([
                    'matricula_id'    => $matricula->id,
                    'curso_id'        => $curso->id,
                    'estado'          => 'Inscrito',
                    'fecha_matricula' => now()
                ]);

                if ($moodleUserId && $curso->moodle_course_id) {
                    $moodle->matricularUsuario(
                        $moodleUserId,
                        $curso->moodle_course_id,
                        5
                    );
                }
            }

            // 11) Cambiar ResultadoAdmision → Matriculado
            $resultado->estado = 'Matriculado';
            $resultado->save();

            $resumen['matriculados']++;

            DB::commit();

        } catch (\Exception $e) {
            DB::rollBack();

            $resumen['errores'][] = [
                'dni'    => $item['dni'] ?? null,
                'motivo' => $e->getMessage()
            ];
        }
    }

    return response()->json([
        'success'       => true,
        'message'       => 'Proceso de matrícula finalizado.',
        'procesados'    => $resumen['procesados'],
        'matriculados'  => $resumen['matriculados'],
        'errores'       => $resumen['errores'],
    ]);
}


    public function buscarPorDni(Request $request)
    {
        $dni = $request->query('dni');

        $postulante = Postulante::where('dni', $dni)->first();

        if ($postulante) {
            return response()->json([
                'success' => true,
                'postulante' => [
                    'id' => $postulante->id_postulante,
                    'nombre' => $postulante->nombres . ' ' . $postulante->apellidos,
                    'dni' => $postulante->dni,
                ]
            ]);
        }

        return response()->json([
            'success' => false,
            'message' => 'Postulante no encontrado.'
        ]);
    }

    public function obtenerCursos(Request $request)
    {
        $planEstudioId = $request->input('plan_estudio_id');
        $semestreId = $request->input('semestre_id');
        
        // Obtener los cursos asociados al plan de estudio y semestre, incluyendo los docentes y horarios
        $cursos = Curso::with(['docentes', 'horarios'])
            ->where('semestre_id', $semestreId)
            ->whereHas('planesEstudio', function ($query) use ($planEstudioId) {
                $query->where('plan_estudio_id', $planEstudioId);
            })
            ->get(['id', 'nombre', 'creditos', 'tipo', 'horas_semestrales']);

        // Mapeo para agregar información de los docentes y horarios
        $cursosConDocentesYHorarios = $cursos->map(function($curso) {
            $curso->docentes_info = $curso->docentes->map(function($docente) {
                return $docente->nombre . ' ' . $docente->apellido;
            });

            $curso->horarios_info = $curso->horarios->map(function($horario) {
                return $horario->dia . ' - ' . $horario->hora_inicio . ' a ' . $horario->hora_fin . ' (' . $horario->numero_aula . ')';
            });

            return $curso;
        });

        return response()->json($cursosConDocentesYHorarios);
    }

   
    public function registrarOrdinaria(Request $request, \App\Services\MoodleService $moodle)
{
    $request->validate([
        'tipo_matricula' => 'required|in:ordinaria',
        'postulante_id' => 'required|exists:postulantes,id_postulante',
        'codigo_matricula' => 'required|string',
        'periodo_id' => 'required|exists:periodos,id',
        'plan_estudio_id' => 'required|exists:planes_estudio,id',
        'semestre_id' => 'required|exists:semestres,id',
        'cursos' => 'required|array|min:1',
        'cursos.*' => 'exists:cursos,id',
    ]);

    $postulante = Postulante::findOrFail($request->postulante_id);
    $usuario = $postulante->usuario;
    $moodleUserId = $usuario->moodle_user_id;

    // 1) Crear matrícula
    $matricula = Matricula::create([
        'codigo_matricula' => $request->codigo_matricula,
        'postulante_id' => $postulante->id_postulante,
        'periodo_id' => $request->periodo_id,
        'plan_estudio_id' => $request->plan_estudio_id,
        'semestre_id' => $request->semestre_id,
        'estado' => 'Matriculado',
        'fecha_matricula' => now(),
    ]);

    // 2) Registrar cursos + matricular en Moodle
    foreach ($request->cursos as $cursoId) {

        $curso = Curso::find($cursoId);

        MatriculaCurso::create([
            'matricula_id' => $matricula->id,
            'curso_id' => $cursoId,
            'estado' => 'Inscrito',
        ]);

        if ($moodleUserId && $curso->moodle_course_id) {
            $moodle->matricularUsuario(
                $moodleUserId,
                $curso->moodle_course_id,
                5
            );
        }
    }

    return response()->json(['success' => true]);
}


    public function reporteMatriculados(Request $request)
    {
        // Cargar listas para filtros
        $periodos = Periodo::all();
        $planesEstudio = PlanEstudio::all();
        $semestres = Semestre::all();

        // Consulta base con relaciones
        $matriculas = Matricula::with('postulante', 'planEstudio', 'periodo', 'semestre');

        // Aplicar filtros
        if ($request->filled('periodo_id')) {
            $matriculas->where('periodo_id', $request->periodo_id);
        }

        if ($request->filled('plan_estudio_id')) {
            $matriculas->where('plan_estudio_id', $request->plan_estudio_id);
        }

        if ($request->filled('semestre_id')) {
            $matriculas->where('semestre_id', $request->semestre_id);
        }

        $matriculas = $matriculas->get();

        return view('reportes.reporte_matriculados', compact('matriculas', 'periodos', 'planesEstudio', 'semestres'));
    }

    public function buscarMatriculados(Request $request)
{
    $matriculas = Matricula::with(['postulante', 'planEstudio', 'periodo', 'semestre']);

    if ($request->filled('periodo_id')) {
        $matriculas->where('periodo_id', $request->periodo_id);
    }

    if ($request->filled('plan_estudio_id')) {
        $matriculas->where('plan_estudio_id', $request->plan_estudio_id);
    }

    if ($request->filled('semestre_id')) {
        $matriculas->where('semestre_id', $request->semestre_id);
    }

    $matriculas = $matriculas->get();

    // Añadir campos cifrados manualmente
    $matriculas = $matriculas->map(function ($m) {
        $m->id_cifrado = Crypt::encrypt($m->id);
        $m->postulante_id_cifrado = Crypt::encrypt($m->postulante_id);
        $m->semestre_id_cifrado = Crypt::encrypt($m->semestre_id);
        return $m;
    });

    return response()->json($matriculas);
}

    public function generarReportePDF(Request $request)
    {
        $matriculas = Matricula::with('postulante', 'planEstudio', 'periodo', 'semestre');

        if ($request->filled('periodo_id')) {
            $matriculas->where('periodo_id', $request->periodo_id);
        }

        if ($request->filled('plan_estudio_id')) {
            $matriculas->where('plan_estudio_id', $request->plan_estudio_id);
        }

        if ($request->filled('semestre_id')) {
            $matriculas->where('semestre_id', $request->semestre_id);
        }

        $matriculas = $matriculas->get();
        $instituto = Instituto::first(); // o ->find(1) si sabes el ID
        $curso_info = [
            'carrera' => optional($matriculas->first()->planEstudio)->nombre ?? '---',
            'periodo' => optional($matriculas->first()->periodo)->nombre ?? '---',
            'semestre' => optional($matriculas->first()->semestre)->nombre ?? '---',
            
        ];

        $pdf = Pdf::loadView('reportes.pdf_matriculados', compact('matriculas', 'instituto', 'curso_info'))
          ->setPaper('a3', 'portrait');


       
        return $pdf->stream('reporte_matriculados.pdf'); // O usar ->download() para forzar descarga
    }

    public function generarActaNotas(Request $request)
    {
        $idPeriodo = $request->periodo_id;
        $idPlanEstudio = $request->plan_estudio_id;
        $idSemestre = $request->semestre_id;

        $matriculas = Matricula::with(['postulante', 'planEstudio', 'periodo', 'semestre', 'matriculaCursos.curso'])
            ->when($idPeriodo, fn($q) => $q->where('periodo_id', $idPeriodo))
            ->when($idPlanEstudio, fn($q) => $q->where('plan_estudio_id', $idPlanEstudio))
            ->when($idSemestre, fn($q) => $q->where('semestre_id', $idSemestre))
            ->get();

        if ($matriculas->isEmpty()) {
            return back()->with('error', 'No se encontraron estudiantes con los criterios seleccionados.');
        }

        $datos_estudiantes = [];
        $cursos_unicos = [];

        foreach ($matriculas as $matricula) {
            $postulante = $matricula->postulante;
            $dni = $postulante->dni;

            if (!isset($datos_estudiantes[$dni])) {
                $datos_estudiantes[$dni] = [
                    'nombres' => $postulante->nombres,
                    'apellidos' => $postulante->apellidos,
                    'semestre' => $matricula->semestre->nombre ?? '',
                    'carrera' => $matricula->planEstudio->nombre ?? '',
                    'periodo' => $matricula->periodo->nombre ?? '',
                    'cursos' => [],
                    'aprobados' => 0,
                    'desaprobados' => 0,
                ];
            }

            foreach ($matricula->matriculaCursos as $mc) {
                $curso = $mc->curso;
                $nombreCurso = $curso->nombre;
                $cursos_unicos[] = $nombreCurso;

                $nota = NotaFinal::where('curso_id', $curso->id)
                    ->where('estudiante_id', $postulante->id_postulante)
                    ->value('promedio') ?? '-';

                $datos_estudiantes[$dni]['cursos'][$nombreCurso] = $nota;

                if ($nota !== '-') {
                    if ($nota >= 11) {
                        $datos_estudiantes[$dni]['aprobados']++;
                    } else {
                        $datos_estudiantes[$dni]['desaprobados']++;
                    }
                }
            }
        }

        $cursos_unicos = array_unique($cursos_unicos);
        $instituto = Instituto::first();
        $curso_info = [
                    'carrera' => optional($matriculas->first()->planEstudio)->nombre ?? '---',
                    'periodo' => optional($matriculas->first()->periodo)->nombre ?? '---',
                    'semestre' => optional($matriculas->first()->semestre)->nombre ?? '---',
                    
                ];
        $pdf = Pdf::loadView('reportes.pdf_acta_notas', compact('datos_estudiantes', 'cursos_unicos', 'instituto', 'curso_info'))
            ->setPaper('a3', 'landscape');

        return $pdf->stream('acta_notas.pdf');
    }


   public function fichaMatricula($id)
{
    // Desencriptar el ID recibido desde la URL
    $id = Crypt::decrypt($id);

    $matricula = Matricula::with([
        'postulante', 
        'periodo', 
        'planEstudio', 
        'semestre', 
        'matriculaCursos.curso'
    ])->findOrFail($id);

    $instituto = Instituto::first();

    $pdf = Pdf::loadView('reportes.ficha_matricula', compact('matricula', 'instituto'));
    return $pdf->stream("ficha_matricula_{$id}.pdf");
}

public function boletaNotas($idPostulante, $idSemestre)
{
    try {
        $idPostulante = Crypt::decrypt($idPostulante);
        $idSemestre = Crypt::decrypt($idSemestre);
    } catch (DecryptException $e) {
        abort(403, 'Parámetros inválidos o manipulados');
    }

    $matricula = Matricula::with([
        'postulante',
        'periodo',
        'planEstudio',
        'semestre',
        'matriculaCursos.curso'
    ])
    ->where('postulante_id', $idPostulante)
    ->where('semestre_id', $idSemestre)
    ->firstOrFail();

    // Obtener notas finales del estudiante
    $notas = NotaFinal::where('estudiante_id', $idPostulante)->get()->keyBy('curso_id');

    // Adjuntar nota final a cada curso de la matrícula
    foreach ($matricula->matriculaCursos as $mc) {
        $mc->nota_final = $notas[$mc->curso_id]->promedio ?? null;
    }

    $instituto = Instituto::first();

    $pdf = Pdf::loadView('reportes.boleta_notas', compact('matricula', 'instituto'));
    return $pdf->stream("boleta_notas_{$idPostulante}_{$idSemestre}.pdf");
}

}
