<?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 App\Models\GrupoDeEvaluaciones;
use App\Models\Evaluaciones;
use App\Models\Cursos;
use Carbon\Carbon;

class SubidaMasivaController extends Controller
{
    /**
     * Procesar subida masiva de evaluaciones
     * 
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function procesarSubidaMasiva(Request $request)
    {
        try {
            Log::info('🚀 Iniciando subida masiva de evaluaciones', $request->all());

            // Validar estructura del request
            $validator = $this->validarRequest($request);
            if ($validator->fails()) {
                return response()->json([
                    'success' => false,
                    'message' => 'Error de validación',
                    'errors' => $validator->errors()
                ], 422);
            }

            $registros = $request->input('registros');
            $resultados = [];
            $errores = [];

            // Iniciar transacción principal
            DB::beginTransaction();

            foreach ($registros as $index => $registro) {
                try {
                    Log::info("📝 Procesando registro #{$index}", $registro);

                    $resultado = $this->procesarRegistroIndividual($registro, $index);
                    $resultados[] = $resultado;
                } catch (\Exception $e) {
                    Log::error("❌ Error en registro #{$index}: " . $e->getMessage());
                    $errores[] = [
                        'registro' => $index,
                        'error' => $e->getMessage(),
                        'data' => $registro
                    ];
                }
            }

            // Si hay errores, hacer rollback
            if (!empty($errores)) {
                DB::rollBack();
                return response()->json([
                    'success' => false,
                    'message' => 'Error al procesar algunos registros',
                    'errores' => $errores,
                    'procesados_exitosamente' => count($resultados),
                    'total_errores' => count($errores)
                ], 400);
            }

            // Si todo está bien, confirmar transacción
            DB::commit();

            Log::info("✅ Subida masiva completada exitosamente", [
                'total_procesados' => count($resultados),
                'total_errores' => count($errores)
            ]);

            return response()->json([
                'success' => true,
                'message' => 'Subida masiva procesada exitosamente',
                'resultados' => $resultados,
                'resumen' => [
                    'total_registros' => count($registros),
                    'procesados_exitosamente' => count($resultados),
                    'errores' => count($errores)
                ]
            ], 201);
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('❌ Error general en subida masiva: ' . $e->getMessage());

            return response()->json([
                'success' => false,
                'message' => 'Error interno del servidor',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Validar la estructura del request
     */
    private function validarRequest(Request $request)
    {
        return Validator::make($request->all(), [
            'domain_id' => 'required|integer|min:1',
            'registros' => 'required|array|min:1',
            'registros.*.dni' => 'required|string|max:20',
            'registros.*.nombre_alumno' => 'required|string|max:255',
            'registros.*.codigo_unidad_didactica' => 'required|string|max:50',
            'registros.*.nombre_unidad_didactica' => 'required|string|max:255',
            'registros.*.nombre_grupo_evaluacion' => 'required|string|max:255',
            'registros.*.nombre_evaluacion' => 'required|string|max:255',
            'registros.*.nota_evaluacion' => 'required|numeric|min:0|max:20',
            'registros.*.porcentaje' => 'required|numeric|min:0|max:100'
        ], [
            // Mensajes para domain_id
            'domain_id.required' => 'El domain_id es obligatorio',
            'domain_id.integer' => 'El domain_id debe ser un número entero',
            'domain_id.min' => 'El domain_id debe ser mayor a 0',

            // Mensajes para registros
            'registros.required' => 'Se requiere al menos un registro',
            'registros.array' => 'Los registros deben ser un arreglo',
            'registros.min' => 'Debe enviar al menos un registro',

            // Mensajes para DNI
            'registros.*.dni.required' => 'El DNI es obligatorio en todos los registros',
            'registros.*.dni.string' => 'El DNI debe ser un texto',
            'registros.*.dni.max' => 'El DNI no puede exceder 20 caracteres',

            // Mensajes para nombre_alumno
            'registros.*.nombre_alumno.required' => 'El nombre del alumno es obligatorio',
            'registros.*.nombre_alumno.string' => 'El nombre del alumno debe ser un texto',
            'registros.*.nombre_alumno.max' => 'El nombre del alumno no puede exceder 255 caracteres',

            // Mensajes para codigo_unidad_didactica
            'registros.*.codigo_unidad_didactica.required' => 'El código de unidad didáctica es obligatorio',
            'registros.*.codigo_unidad_didactica.string' => 'El código de unidad didáctica debe ser un texto',
            'registros.*.codigo_unidad_didactica.max' => 'El código de unidad didáctica no puede exceder 50 caracteres',

            // Mensajes para nombre_unidad_didactica
            'registros.*.nombre_unidad_didactica.required' => 'El nombre de unidad didáctica es obligatorio',
            'registros.*.nombre_unidad_didactica.string' => 'El nombre de unidad didáctica debe ser un texto',
            'registros.*.nombre_unidad_didactica.max' => 'El nombre de unidad didáctica no puede exceder 255 caracteres',

            // Mensajes para nombre_grupo_evaluacion
            'registros.*.nombre_grupo_evaluacion.required' => 'El nombre del grupo de evaluación es obligatorio',
            'registros.*.nombre_grupo_evaluacion.string' => 'El nombre del grupo de evaluación debe ser un texto',
            'registros.*.nombre_grupo_evaluacion.max' => 'El nombre del grupo de evaluación no puede exceder 255 caracteres',

            // Mensajes para nombre_evaluacion
            'registros.*.nombre_evaluacion.required' => 'El nombre de la evaluación es obligatorio',
            'registros.*.nombre_evaluacion.string' => 'El nombre de la evaluación debe ser un texto',
            'registros.*.nombre_evaluacion.max' => 'El nombre de la evaluación no puede exceder 255 caracteres',

            // Mensajes para nota_evaluacion
            'registros.*.nota_evaluacion.required' => 'La nota de evaluación es obligatoria',
            'registros.*.nota_evaluacion.numeric' => 'La nota debe ser un número',
            'registros.*.nota_evaluacion.min' => 'La nota mínima es 0',
            'registros.*.nota_evaluacion.max' => 'La nota máxima es 20',

            // Mensajes para porcentaje
            'registros.*.porcentaje.required' => 'El porcentaje es obligatorio',
            'registros.*.porcentaje.numeric' => 'El porcentaje debe ser un número',
            'registros.*.porcentaje.min' => 'El porcentaje mínimo es 0',
            'registros.*.porcentaje.max' => 'El porcentaje máximo es 100'
        ]);
    }

    /**
     * ✅ ACTUALIZADO: Procesar registro con domain_id
     */
    private function procesarRegistroIndividual($registro, $index)
    {
        // ✅ OBTENER domain_id del request
        $domainId = request()->input('domain_id');

        if (!$domainId) {
            throw new \Exception("Se requiere domain_id en el request");
        }

        // 1. Buscar el alumno por DNI
        $alumno = $this->buscarAlumno($registro['dni']);
        if (!$alumno) {
            throw new \Exception("El alumno con DNI {$registro['dni']} no existe en el sistema");
        }

        // 2. Buscar el curso por código Y domain_id
        $curso = $this->buscarCurso($registro['codigo_unidad_didactica'], $domainId);
        if (!$curso) {
            throw new \Exception(
                "La unidad didáctica con código {$registro['codigo_unidad_didactica']} " .
                    "no existe en el dominio {$domainId}"
            );
        }

        // 3. Verificar vinculación con domain_id
        $this->verificarVinculacionAlumnoCurso($alumno->id, $curso->id, $registro, $domainId);

        // 4. Buscar o crear el Indicador
        $grupoEvaluaciones = $this->buscarOCrearGrupoEvaluaciones($registro, $curso->id);

        // 5. Buscar o crear la evaluación
        $evaluacion = $this->buscarOCrearEvaluacion($registro, $grupoEvaluaciones->id);

        // 6. Crear o actualizar la nota
        $evaluacionAlumno = $this->crearOActualizarNota($alumno->id, $evaluacion->id, $registro);

        return [
            'registro' => $index,
            'alumno_id' => $alumno->id,
            'alumno_nombre' => $alumno->nombres . ' ' . $alumno->apellidos,
            'alumno_dni' => $alumno->dni,
            'curso_id' => $curso->id,
            'curso_codigo' => $curso->codigo,
            'curso_nombre' => $curso->nombre,
            'domain_id' => $curso->domain_id,
            'grupo_evaluaciones_id' => $grupoEvaluaciones->id,
            'grupo_nombre' => $grupoEvaluaciones->nombre_del_grupo,
            'evaluacion_id' => $evaluacion->id,
            'evaluacion_nombre' => $evaluacion->nombre,
            'evaluacion_porcentaje' => $evaluacion->porcentaje_asignado,
            'nota' => $evaluacionAlumno->nota,
            'procesado' => 'exitoso'
        ];
    }

    /**
     * Buscar alumno por DNI (debe existir previamente)
     */
    private function buscarAlumno($dni)
    {
        $alumno = DB::table('alumnos')
            ->where('dni', $dni)
            ->whereNull('deleted_at')
            ->first();

        if ($alumno) {
            Log::info("👤 Alumno encontrado: {$alumno->nombres} {$alumno->apellidos} (DNI: {$dni})");
        } else {
            Log::error("❌ Alumno no encontrado con DNI: {$dni}");
        }

        return $alumno;
    }

    /**
     * ✅ ACTUALIZADO: Buscar curso por código Y domain_id
     */
    private function buscarCurso($codigo, $domainId)
    {
        // Normalizar código para búsqueda
        $codigoNormalizado = strtoupper(trim($codigo));

        $curso = DB::table('cursos')
            ->whereRaw('UPPER(TRIM(codigo)) = ?', [$codigoNormalizado])
            ->where('domain_id', $domainId) // ✅ FILTRO POR DOMAIN
            ->whereNull('deleted_at')
            ->first();

        if ($curso) {
            Log::info("📚 Curso encontrado: {$curso->nombre} ({$codigo}) en domain {$domainId}");
        } else {
            Log::error("❌ Curso no encontrado con código: {$codigo} en domain {$domainId}");
        }

        return $curso;
    }

    /**
     * ✅ ACTUALIZADO: Verificar vinculación considerando domain_id
     */
    private function verificarVinculacionAlumnoCurso($alumnoId, $cursoId, $registro, $domainId)
    {
        // Buscar vinculación sin deleted_at (la tabla pivot no lo tiene)
        $vinculacion = DB::table('curso_alumno')
            ->where('alumno_id', $alumnoId)
            ->where('curso_id', $cursoId)
            ->first();

        if (!$vinculacion) {
            // Buscar inscripciones del alumno en el MISMO domain
            $inscripcionesActivas = DB::table('curso_alumno as ca')
                ->join('cursos as c', 'ca.curso_id', '=', 'c.id')
                ->where('ca.alumno_id', $alumnoId)
                ->where('c.domain_id', $domainId) // ✅ MISMO DOMAIN
                ->whereNull('c.deleted_at')
                ->select('c.codigo', 'c.nombre', 'c.id as curso_id', 'ca.estado_id')
                ->get();

            $mensajeAyuda = $inscripcionesActivas->count() > 0
                ? " En este dominio, el alumno está inscrito en: " .
                $inscripcionesActivas->pluck('codigo')->implode(', ') .
                " (IDs: " . $inscripcionesActivas->pluck('curso_id')->implode(', ') . ")"
                : " El alumno NO tiene inscripciones en cursos de este dominio (domain_id: {$domainId})";

            throw new \Exception(
                "El alumno {$registro['nombre_alumno']} (DNI: {$registro['dni']}) " .
                    "no está inscrito en la unidad didáctica {$registro['codigo_unidad_didactica']} " .
                    "del dominio {$domainId}." .
                    $mensajeAyuda
            );
        }

        Log::info("✅ Vinculación verificada", [
            'alumno_id' => $alumnoId,
            'curso_id' => $cursoId,
            'vinculacion_id' => $vinculacion->id,
            'estado_id' => $vinculacion->estado_id ?? null,
            'domain_id' => $domainId
        ]);

        return $vinculacion;
    }

    /**
     * Buscar o crear Indicador
     */
    private function buscarOCrearGrupoEvaluaciones($registro, $cursoId)
    {
        $grupo = DB::table('grupo_de_evaluaciones')
            ->where('curso_id', $cursoId)
            ->where('nombre_del_grupo', $registro['nombre_grupo_evaluacion'])
            ->whereNull('deleted_at')
            ->first();

        if (!$grupo) {
            $grupoId = DB::table('grupo_de_evaluaciones')->insertGetId([
                'curso_id' => $cursoId,
                'nombre_del_grupo' => $registro['nombre_grupo_evaluacion'],
                'created_at' => Carbon::now(),
                'updated_at' => Carbon::now()
            ]);

            $grupo = DB::table('grupo_de_evaluaciones')->where('id', $grupoId)->first();
            Log::info("📋 Indicador creado: {$registro['nombre_grupo_evaluacion']}");
        } else {
            Log::info("📋 Indicador encontrado: {$grupo->nombre_del_grupo}");
        }

        return $grupo;
    }

    /**
     * Buscar o crear evaluación con porcentaje específico
     */
    private function buscarOCrearEvaluacion($registro, $grupoEvaluacionesId)
    {
        $evaluacion = DB::table('evaluaciones')
            ->where('grupo_de_evaluaciones_id', $grupoEvaluacionesId)
            ->where('nombre', $registro['nombre_evaluacion'])
            ->whereNull('deleted_at')
            ->first();

        if (!$evaluacion) {
            $evaluacionId = DB::table('evaluaciones')->insertGetId([
                'nombre' => $registro['nombre_evaluacion'],
                'tipo_evaluacion_id' => 1,
                'fecha_y_hora_programo' => Carbon::now(),
                'observaciones' => 'Evaluación creada automáticamente por subida masiva',
                'estado_id' => 2,
                'domain_id' => 1,
                'porcentaje_asignado' => $registro['porcentaje'],
                'grupo_de_evaluaciones_id' => $grupoEvaluacionesId,
                'modalidad' => 1,
                'created_at' => Carbon::now(),
                'updated_at' => Carbon::now()
            ]);

            $evaluacion = DB::table('evaluaciones')->where('id', $evaluacionId)->first();
            Log::info("📝 Evaluación creada: {$registro['nombre_evaluacion']} con {$registro['porcentaje']}%");
        } else {
            if ($evaluacion->porcentaje_asignado != $registro['porcentaje']) {
                DB::table('evaluaciones')
                    ->where('id', $evaluacion->id)
                    ->update([
                        'porcentaje_asignado' => $registro['porcentaje'],
                        'updated_at' => Carbon::now()
                    ]);

                Log::info("📝 Evaluación actualizada: {$evaluacion->nombre} - porcentaje: {$registro['porcentaje']}%");
                $evaluacion = DB::table('evaluaciones')->where('id', $evaluacion->id)->first();
            } else {
                Log::info("📝 Evaluación encontrada: {$evaluacion->nombre} ({$evaluacion->porcentaje_asignado}%)");
            }
        }

        return $evaluacion;
    }

    /**
     * Crear o actualizar nota del alumno
     */
    private function crearOActualizarNota($alumnoId, $evaluacionId, $registro)
    {
        $evaluacionAlumno = DB::table('evaluaciones_alumno')
            ->where('alumno_id', $alumnoId)
            ->where('evaluacion_id', $evaluacionId)
            ->first();

        $datosNota = [
            'nota' => $registro['nota_evaluacion'],
            'asistencia' => 1,
            'updated_at' => Carbon::now()
        ];

        if (!$evaluacionAlumno) {
            $datosNota['alumno_id'] = $alumnoId;
            $datosNota['evaluacion_id'] = $evaluacionId;
            $datosNota['created_at'] = Carbon::now();

            $evaluacionAlumnoId = DB::table('evaluaciones_alumno')->insertGetId($datosNota);
            $evaluacionAlumno = DB::table('evaluaciones_alumno')->where('id', $evaluacionAlumnoId)->first();

            Log::info("📊 Nota creada: Alumno {$alumnoId}, Nota: {$registro['nota_evaluacion']}");
        } else {
            DB::table('evaluaciones_alumno')
                ->where('id', $evaluacionAlumno->id)
                ->update($datosNota);

            $evaluacionAlumno = DB::table('evaluaciones_alumno')->where('id', $evaluacionAlumno->id)->first();
            Log::info("📊 Nota actualizada: Alumno {$alumnoId}, Nota: {$registro['nota_evaluacion']}");
        }

        return $evaluacionAlumno;
    }

    /**
     * Endpoint para obtener un ejemplo de estructura de datos
     */
    public function ejemploEstructura()
    {
        return response()->json([
            'message' => 'Estructura de datos requerida para subida masiva',
            'estructura' => [
                'registros' => [
                    [
                        'dni' => '12345678',
                        'nombre_alumno' => 'Juan Carlos Pérez López',
                        'codigo_unidad_didactica' => 'UD001',
                        'nombre_unidad_didactica' => 'Matemáticas Básicas',
                        'nombre_grupo_evaluacion' => 'Exámenes Parciales',
                        'nombre_evaluacion' => 'Primer Parcial',
                        'nota_evaluacion' => 15.5,
                        'porcentaje' => 30
                    ]
                ]
            ],
            'notas' => [
                '⚠️ El alumno debe existir previamente en el sistema',
                '⚠️ La unidad didáctica debe existir previamente',
                '⚠️ El alumno debe estar inscrito activamente en esa unidad',
                'Las notas van de 0 a 20',
                'El porcentaje va de 0 a 100'
            ],
            'flujo_de_proceso' => [
                '1. Buscar alumno por DNI',
                '2. Buscar unidad didáctica por código',
                '3. Verificar inscripción activa',
                '4. Crear/buscar grupo de evaluación',
                '5. Crear/buscar evaluación',
                '6. Asignar nota'
            ]
        ]);
    }
}
