<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use Carbon\Carbon;

class AsistenciasController extends Controller
{
    const PORCENTAJE_MAX_INASISTENCIA = 30; // 30%
    const ESTADO_INHABILITADO = 7;
    /**
     * ✅ Obtener clases del día para un docente
     * GET /api/asistencias/clases-hoy/{docente_id}/{domain_id}
     */
    public function getClasesDelDia($docente_id, $domain_id)
    {
        try {
            $hoy = Carbon::now()->format('Y-m-d');

            $clases = DB::table('clases_programadas as cp')
                ->select(
                    'cp.*',
                    'h.curso_id',
                    'h.aula',
                    'c.nombre as curso_nombre',
                    DB::raw('(SELECT COUNT(*) FROM asistencias WHERE clase_programada_id = cp.id AND estado = "presente") as total_presentes'),
                    DB::raw('(SELECT COUNT(*) FROM asistencias WHERE clase_programada_id = cp.id) as total_registrados'),
                    DB::raw('(SELECT COUNT(*) FROM curso_alumno WHERE curso_id = h.curso_id AND estado_id != 0) as total_alumnos')
                )
                ->join('horarios_unidad_didactica as h', 'h.id', '=', 'cp.horario_id')
                ->join('cursos as c', 'c.id', '=', 'h.curso_id')
                ->where('h.docente_id', $docente_id)
                ->where('h.domain_id', $domain_id)
                ->where('cp.fecha', $hoy)
                ->where('cp.estado', '!=', 'inhabilitada')
                ->orderBy('cp.hora_inicio')
                ->get();

            return response()->json([
                'success' => true,
                'data' => $clases,
                'fecha' => $hoy
            ]);
        } catch (\Exception $e) {
            Log::error('Error obteniendo clases del día:', [
                'error' => $e->getMessage()
            ]);

            return response()->json([
                'success' => false,
                'message' => 'Error al obtener clases del día'
            ], 500);
        }
    }

    /**
     * ✅ Obtener lista de alumnos con sus asistencias para una clase
     * GET /api/asistencias/alumnos/{clase_id}
     */
    public function getAlumnosPorClase($clase_id)
    {
        try {
            // Obtener info de la clase
            $clase = DB::table('clases_programadas as cp')
                ->select('cp.*', 'h.curso_id', 'h.domain_id')
                ->join('horarios_unidad_didactica as h', 'h.id', '=', 'cp.horario_id')
                ->where('cp.id', $clase_id)
                ->first();

            if (!$clase) {
                return response()->json([
                    'success' => false,
                    'message' => 'Clase no encontrada'
                ], 404);
            }

            // Obtener total de clases realizadas del curso
            $totalClasesRealizadas = DB::table('clases_programadas as cp')
                ->join('horarios_unidad_didactica as h', 'h.id', '=', 'cp.horario_id')
                ->where('h.curso_id', $clase->curso_id)
                ->where('cp.fecha', '<=', $clase->fecha)
                ->where('cp.estado', '!=', 'inhabilitada')
                ->count();

            // Obtener alumnos del curso con sus asistencias
            $alumnos = DB::table('alumnos as a')
                ->select(
                    'a.id',
                    'a.codigo',
                    DB::raw("CONCAT(a.apellidos, ', ', a.nombres) as nombre_completo"),
                    'a.email',
                    'ca.estado_curso_id',
                    'ec.nombre as estado_alumno',
                    'asist.estado as asistencia_actual',
                    'asist.id as asistencia_id',
                    // Calcular total de ausencias
                    DB::raw('(
                        SELECT COUNT(*) 
                        FROM asistencias asi
                        JOIN clases_programadas cp2 ON cp2.id = asi.clase_programada_id
                        JOIN horarios_unidad_didactica h2 ON h2.id = cp2.horario_id
                        WHERE asi.alumno_id = a.id 
                        AND h2.curso_id = ' . $clase->curso_id . '
                        AND asi.estado = "ausente"
                    ) as total_ausencias'),
                    // Calcular porcentaje de inasistencia
                    DB::raw('ROUND(
                        (SELECT COUNT(*) 
                        FROM asistencias asi
                        JOIN clases_programadas cp2 ON cp2.id = asi.clase_programada_id
                        JOIN horarios_unidad_didactica h2 ON h2.id = cp2.horario_id
                        WHERE asi.alumno_id = a.id 
                        AND h2.curso_id = ' . $clase->curso_id . '
                        AND asi.estado = "ausente"
                        ) * 100.0 / NULLIF(' . $totalClasesRealizadas . ', 0), 2
                    ) as porcentaje_inasistencia')
                )
                ->join('curso_alumno as ca', function ($join) use ($clase) {
                    $join->on('ca.alumno_id', '=', 'a.id')
                        ->where('ca.curso_id', $clase->curso_id)
                        ->where('ca.domain_id', $clase->domain_id)
                        ->where('ca.estado_id', '!=', 0);
                })
                ->join('estado_curso_alumno as ec', 'ec.id', '=', 'ca.estado_curso_id')
                ->leftJoin('asistencias as asist', function ($join) use ($clase_id) {
                    $join->on('asist.alumno_id', '=', 'a.id')
                        ->where('asist.clase_programada_id', $clase_id);
                })
                ->where('a.domain_id', $clase->domain_id)
                ->orderBy('a.apellidos')
                ->orderBy('a.nombres')
                ->get();

            return response()->json([
                'success' => true,
                'data' => $alumnos,
                'meta' => [
                    'total_clases_realizadas' => $totalClasesRealizadas,
                    'porcentaje_max_inasistencia' => self::PORCENTAJE_MAX_INASISTENCIA
                ]
            ]);
        } catch (\Exception $e) {
            Log::error('Error obteniendo alumnos:', [
                'clase_id' => $clase_id,
                'error' => $e->getMessage(),
                'line' => $e->getLine()
            ]);

            return response()->json([
                'success' => false,
                'message' => 'Error al obtener lista de alumnos',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * ✅ Validar antes de guardar (detectar alumnos que pasarán el 30%)
     * POST /api/asistencias/validar
     */
    public function validarAntesDeGuardar(Request $request)
    {
        try {
            $validator = Validator::make($request->all(), [
                'clase_programada_id' => 'required|integer',
                'asistencias' => 'required|array',
                'asistencias.*.alumno_id' => 'required|integer',
                'asistencias.*.estado' => 'required|in:presente,ausente'
            ]);

            if ($validator->fails()) {
                return response()->json([
                    'success' => false,
                    'errors' => $validator->errors()
                ], 422);
            }

            $claseId = $request->input('clase_programada_id');
            $asistencias = $request->input('asistencias');

            // Obtener info de la clase
            $clase = DB::table('clases_programadas as cp')
                ->select('h.curso_id', 'h.domain_id')
                ->join('horarios_unidad_didactica as h', 'h.id', '=', 'cp.horario_id')
                ->where('cp.id', $claseId)
                ->first();

            if (!$clase) {
                return response()->json([
                    'success' => false,
                    'message' => 'Clase no encontrada'
                ], 404);
            }

            // Total de clases realizadas (incluyendo la actual)
            $totalClases = DB::table('clases_programadas as cp')
                ->join('horarios_unidad_didactica as h', 'h.id', '=', 'cp.horario_id')
                ->where('h.curso_id', $clase->curso_id)
                ->where('cp.estado', '!=', 'inhabilitada')
                ->count();

            $alumnosEnRiesgo = [];

            foreach ($asistencias as $asistencia) {
                if ($asistencia['estado'] === 'ausente') {
                    $alumnoId = $asistencia['alumno_id'];

                    // Calcular ausencias actuales + esta nueva
                    $ausenciasActuales = DB::table('asistencias as asi')
                        ->join('clases_programadas as cp', 'cp.id', '=', 'asi.clase_programada_id')
                        ->join('horarios_unidad_didactica as h', 'h.id', '=', 'cp.horario_id')
                        ->where('asi.alumno_id', $alumnoId)
                        ->where('h.curso_id', $clase->curso_id)
                        ->where('asi.estado', 'ausente')
                        ->count();

                    // +1 por la nueva ausencia
                    $nuevasAusencias = $ausenciasActuales + 1;
                    $porcentaje = round(($nuevasAusencias / $totalClases) * 100, 2);

                    // ✅ Solo validar si NO está ya inhabilitado
                    $estadoCurso = DB::table('curso_alumno')
                        ->where('alumno_id', $alumnoId)
                        ->where('curso_id', $clase->curso_id)
                        ->where('domain_id', $clase->domain_id)
                        ->value('estado_curso_id');

                    if ($porcentaje > self::PORCENTAJE_MAX_INASISTENCIA && $estadoCurso != self::ESTADO_INHABILITADO) {
                        // Obtener nombre del alumno
                        $alumno = DB::table('alumnos')
                            ->select(DB::raw("CONCAT(apellidos, ', ', nombres) as nombre_completo"))
                            ->where('id', $alumnoId)
                            ->first();

                        $alumnosEnRiesgo[] = [
                            'alumno_id' => $alumnoId,
                            'nombre' => $alumno->nombre_completo ?? 'Desconocido',
                            'ausencias_actuales' => $ausenciasActuales,
                            'nuevas_ausencias' => $nuevasAusencias,
                            'porcentaje_actual' => round(($ausenciasActuales / $totalClases) * 100, 2),
                            'porcentaje_nuevo' => $porcentaje,
                            'total_clases' => $totalClases
                        ];
                    }
                }
            }

            return response()->json([
                'success' => true,
                'hay_alumnos_en_riesgo' => count($alumnosEnRiesgo) > 0,
                'alumnos_en_riesgo' => $alumnosEnRiesgo,
                'porcentaje_max' => self::PORCENTAJE_MAX_INASISTENCIA
            ]);
        } catch (\Exception $e) {
            Log::error('Error validando asistencias:', [
                'error' => $e->getMessage()
            ]);

            return response()->json([
                'success' => false,
                'message' => 'Error al validar asistencias'
            ], 500);
        }
    }

    /**
     * ✅ Guardar asistencias (con opción de inhabilitar)
     * POST /api/asistencias/guardar
     */
    public function guardarAsistencias(Request $request)
    {
        try {
            $validator = Validator::make($request->all(), [
                'clase_programada_id' => 'required|integer',
                'asistencias' => 'required|array',
                'asistencias.*.alumno_id' => 'required|integer',
                'asistencias.*.estado' => 'required|in:presente,ausente',
                'registrado_por' => 'required|integer',
                'inhabilitar_alumnos' => 'nullable|boolean',
                'alumnos_a_inhabilitar' => 'nullable|array'
            ]);

            if ($validator->fails()) {
                return response()->json([
                    'success' => false,
                    'errors' => $validator->errors()
                ], 422);
            }

            DB::beginTransaction();

            $claseId = $request->input('clase_programada_id');
            $asistencias = $request->input('asistencias');
            $registradoPor = $request->input('registrado_por');
            $inhabilitarAlumnos = $request->input('inhabilitar_alumnos', false);
            $alumnosAInhabilitar = $request->input('alumnos_a_inhabilitar', []);

            $registrados = 0;
            $actualizados = 0;

            foreach ($asistencias as $asistencia) {
                $existe = DB::table('asistencias')
                    ->where('clase_programada_id', $claseId)
                    ->where('alumno_id', $asistencia['alumno_id'])
                    ->first();

                if ($existe) {
                    // Actualizar
                    DB::table('asistencias')
                        ->where('id', $existe->id)
                        ->update([
                            'estado' => $asistencia['estado'],
                            'hora_registro' => Carbon::now(),
                            'updated_at' => Carbon::now()
                        ]);
                    $actualizados++;
                } else {
                    // Insertar
                    DB::table('asistencias')->insert([
                        'clase_programada_id' => $claseId,
                        'alumno_id' => $asistencia['alumno_id'],
                        'estado' => $asistencia['estado'],
                        'hora_registro' => Carbon::now(),
                        'registrado_por' => $registradoPor,
                        'created_at' => Carbon::now(),
                        'updated_at' => Carbon::now()
                    ]);
                    $registrados++;
                }
            }

            // Obtener curso_id y domain_id una sola vez
            $clase = DB::table('clases_programadas as cp')
                ->select('h.curso_id', 'h.domain_id')
                ->join('horarios_unidad_didactica as h', 'h.id', '=', 'cp.horario_id')
                ->where('cp.id', $claseId)
                ->first();

            $cursoId = $clase->curso_id ?? null;
            $domainId = $clase->domain_id ?? null;

            // Inhabilitar alumnos si es necesario
            $inhabilitados = 0;
            if ($inhabilitarAlumnos && !empty($alumnosAInhabilitar) && $cursoId && $domainId) {
                $inhabilitados = DB::table('curso_alumno')
                    ->whereIn('alumno_id', $alumnosAInhabilitar)
                    ->where('curso_id', $cursoId)
                    ->where('domain_id', $domainId)
                    ->update([
                        'estado_curso_id' => self::ESTADO_INHABILITADO, // ✅ Cambiar a ID 7
                        'updated_at' => Carbon::now()
                    ]);

                Log::info('Alumnos inhabilitados por exceder inasistencias:', [
                    'curso_id' => $cursoId,
                    'total_inhabilitados' => $inhabilitados,
                    'alumnos_ids' => $alumnosAInhabilitar,
                    'porcentaje_max' => self::PORCENTAJE_MAX_INASISTENCIA
                ]);
            }

            DB::commit();

            Log::info('Asistencias guardadas:', [
                'clase_id' => $claseId,
                'registrados' => $registrados,
                'actualizados' => $actualizados,
                'inhabilitados' => $inhabilitados
            ]);

            return response()->json([
                'success' => true,
                'message' => 'Asistencias guardadas exitosamente',
                'data' => [
                    'registrados' => $registrados,
                    'actualizados' => $actualizados,
                    'inhabilitados' => $inhabilitados
                ]
            ]);
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Error guardando asistencias:', [
                'error' => $e->getMessage(),
                'line' => $e->getLine()
            ]);

            return response()->json([
                'success' => false,
                'message' => 'Error al guardar asistencias',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * ✅ Abrir asistencia desde clase programada
     * GET /api/asistencias/clase/{clase_programada_id}
     */
    public function abrirAsistenciaDesdeClase($clase_programada_id)
    {
        try {
            // Verificar que la clase existe primero (sin JOIN)
            $claseSimple = DB::table('clases_programadas')
                ->where('id', $clase_programada_id)
                ->first();

            if (!$claseSimple) {
                return response()->json([
                    'success' => false,
                    'message' => 'Clase programada no encontrada',
                    'debug' => [
                        'clase_id' => $clase_programada_id,
                        'total_clases' => DB::table('clases_programadas')->count()
                    ]
                ], 404);
            }

            // Ahora hacer el JOIN completo
            $clase = DB::table('clases_programadas as cp')
                ->select(
                    'cp.id',
                    'cp.horario_id',
                    'cp.fecha',
                    'cp.hora_inicio',
                    'cp.hora_fin',
                    'cp.es_feriado',
                    'cp.feriado_id',
                    'cp.estado',
                    'cp.observaciones',
                    'h.curso_id',
                    'h.docente_id',
                    'h.domain_id',
                    'h.aula',
                    'c.nombre as curso_nombre',
                    'c.codigo as curso_codigo'
                )
                ->join('horarios_unidad_didactica as h', 'h.id', '=', 'cp.horario_id')
                ->join('cursos as c', 'c.id', '=', 'h.curso_id')
                ->where('cp.id', $clase_programada_id)
                ->whereNull('h.deleted_at') // ✅ Solo horarios tiene deleted_at
                ->whereNull('c.deleted_at')  // ✅ Solo cursos tiene deleted_at
                ->first();

            if (!$clase) {
                return response()->json([
                    'success' => false,
                    'message' => 'Error en las relaciones de la clase',
                    'debug' => [
                        'clase_existe' => 'Sí',
                        'horario_id' => $claseSimple->horario_id,
                        'problema' => 'El horario o curso asociado fue eliminado'
                    ]
                ], 404);
            }

            // Verificar estado
            if ($clase->estado === 'inhabilitada') {
                return response()->json([
                    'success' => false,
                    'message' => 'No se puede tomar asistencia en clases inhabilitadas por feriado'
                ], 422);
            }

            // Total de clases realizadas (solo programadas, no inhabilitadas)
            $totalClasesRealizadas = DB::table('clases_programadas as cp')
                ->join('horarios_unidad_didactica as h', 'h.id', '=', 'cp.horario_id')
                ->where('h.curso_id', $clase->curso_id)
                ->where('cp.fecha', '<=', $clase->fecha)
                ->where('cp.estado', 'programada')
                ->whereNull('h.deleted_at')
                ->count();

            // Asegurar al menos 1 para evitar división por cero
            $totalClasesRealizadas = max($totalClasesRealizadas, 1);

            // Obtener alumnos del curso
            $alumnos = DB::table('alumnos as a')
                ->select(
                    'a.id',
                    'a.codigo',
                    DB::raw("CONCAT(a.apellidos, ', ', a.nombres) as nombre_completo"),
                    'a.email',
                    'ca.estado_curso_id',
                    'ec.nombre as estado_alumno',
                    'asist.estado as asistencia_actual',
                    'asist.id as asistencia_id',
                    DB::raw('COALESCE((
                        SELECT COUNT(*) 
                        FROM asistencias asi
                        JOIN clases_programadas cp2 ON cp2.id = asi.clase_programada_id
                        JOIN horarios_unidad_didactica h2 ON h2.id = cp2.horario_id
                        WHERE asi.alumno_id = a.id 
                        AND h2.curso_id = ' . (int)$clase->curso_id . '
                        AND asi.estado = "ausente"
                    ), 0) as total_ausencias'),
                    DB::raw('ROUND(
                        COALESCE((
                            SELECT COUNT(*) 
                            FROM asistencias asi
                            JOIN clases_programadas cp2 ON cp2.id = asi.clase_programada_id
                            JOIN horarios_unidad_didactica h2 ON h2.id = cp2.horario_id
                            WHERE asi.alumno_id = a.id 
                            AND h2.curso_id = ' . (int)$clase->curso_id . '
                            AND asi.estado = "ausente"
                        ), 0) * 100.0 / ' . $totalClasesRealizadas . ', 2
                    ) as porcentaje_inasistencia')
                )
                ->join('curso_alumno as ca', function ($join) use ($clase) {
                    $join->on('ca.alumno_id', '=', 'a.id')
                        ->where('ca.curso_id', (int)$clase->curso_id)
                        ->where('ca.domain_id', (int)$clase->domain_id);
                })
                ->join('estado_curso_alumno as ec', 'ec.id', '=', 'ca.estado_curso_id')
                ->leftJoin('asistencias as asist', function ($join) use ($clase_programada_id) {
                    $join->on('asist.alumno_id', '=', 'a.id')
                        ->where('asist.clase_programada_id', (int)$clase_programada_id);
                })
                ->where('a.domain_id', (int)$clase->domain_id)
                ->whereNull('a.deleted_at')
                ->orderBy('a.apellidos')
                ->orderBy('a.nombres')
                ->get();

            return response()->json([
                'success' => true,
                'clase' => $clase,
                'alumnos' => $alumnos,
                'meta' => [
                    'total_clases_realizadas' => $totalClasesRealizadas,
                    'porcentaje_max_inasistencia' => self::PORCENTAJE_MAX_INASISTENCIA
                ]
            ]);
        } catch (\Exception $e) {
            Log::error('Error abriendo asistencia desde clase:', [
                'clase_id' => $clase_programada_id,
                'error' => $e->getMessage(),
                'line' => $e->getLine(),
                'file' => $e->getFile()
            ]);

            return response()->json([
                'success' => false,
                'message' => 'Error al cargar asistencia',
                'error' => config('app.debug') ? $e->getMessage() : 'Error interno del servidor'
            ], 500);
        }
    }
}
