<?php

namespace App\Http\Controllers\Api\dev;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\ValidationException;
use App\Models\dev\RegistroAsistencia;
use App\Models\dev\PersonalResidencia;
use App\Models\dev\Personal;
use App\Models\AsignacionRecurrente;
use App\Models\Vacacion;
use App\Models\Licencia;
use Carbon\Carbon;

class MobileAsistenciaController extends Controller
{
    /**
     * Obtener personal_residencia basado en dni_ce o usuario autenticado
     * 
     * @param Request $request
     * @return array ['personal_residencia' => PersonalResidencia|null, 'personal' => Personal|null, 'error' => string|null]
     */
    private function obtenerPersonalResidencia(Request $request)
    {
        Log::info('Obteniendo personal_residencia', ['dni_ce' => $request->input('dni_ce'), 'user_id' => $request->user()->id]);
        $user = $request->user();
        $dniCeObjetivo = $request->input('dni_ce');

        // Si se proporciona dni_ce, buscar personal por DNI
        if ($dniCeObjetivo) {
            // Buscar personal por DNI
            $personalObjetivo = Personal::where('dni_ce', $dniCeObjetivo)->first();

            if (!$personalObjetivo) {
                return [
                    'personal_residencia' => null,
                    'personal' => null,
                    'error' => 'No se encontró personal con el DNI proporcionado'
                ];
            }

            // Validar que el personal esté activo
            if ($personalObjetivo->estado !== 'Activo') {
                return [
                    'personal_residencia' => null,
                    'personal' => $personalObjetivo,
                    'error' => 'El personal no está activo'
                ];
            }

            // Obtener personal_residencia activa del personal objetivo
            $personalResidencia = PersonalResidencia::where('id_personal', $personalObjetivo->id_personal)
                ->where('activo', true)
                ->first();

            if (!$personalResidencia) {
                return [
                    'personal_residencia' => null,
                    'personal' => $personalObjetivo,
                    'error' => 'El empleado no tiene residencias asignadas activas'
                ];
            }

            return [
                'personal_residencia' => $personalResidencia,
                'personal' => $personalObjetivo,
                'error' => null
            ];
        }

        // Modo: Marcar/Ver propia asistencia (comportamiento original)
        if (!$user->personal_id) {
            return [
                'personal_residencia' => null,
                'personal' => null,
                'error' => 'El usuario no está asociado a un empleado'
            ];
        }

        // Obtener personal_residencia activa del usuario autenticado
        $personalResidencia = PersonalResidencia::where('id_personal', $user->personal_id)
            ->where('activo', true)
            ->first();

        if (!$personalResidencia) {
            return [
                'personal_residencia' => null,
                'personal' => null,
                'error' => 'El empleado no tiene residencias asignadas activas'
            ];
        }

        $personal = Personal::find($user->personal_id);

        return [
            'personal_residencia' => $personalResidencia,
            'personal' => $personal,
            'error' => null
        ];
    }

    /**
     * Guardar foto de asistencia con nombre cifrado
     * 
     * @param \Illuminate\Http\UploadedFile $foto
     * @param string $tipo 'entrada' o 'salida'
     * @param int $idRegistro
     * @param int $personalId
     * @param string $fecha Fecha en formato Y-m-d
     * @return array ['ruta_relativa' => string, 'url_publica' => string]
     */
    private function guardarFotoAsistencia($foto, $tipo, $idRegistro, $personalId, $fecha)
    {
        // Obtener ruta base desde .env (default: asistencia/fotos)
        $rutaBase = env('ASISTENCIA_FOTOS_PATH', 'asistencia/fotos');

        // Extraer año y mes de la fecha
        $year = date('Y', strtotime($fecha));
        $month = date('m', strtotime($fecha));

        // Obtener extensión del archivo
        $extension = $foto->getClientOriginalExtension();

        // Generar hash único para el nombre del archivo
        // Combinar: id_registro + timestamp + random_bytes + personal_id
        $hash = substr(
            hash('sha256', $idRegistro . time() . random_bytes(16) . $personalId),
            0,
            16
        );

        // Nombre del archivo: {tipo}_{hash}.{extension}
        $nombreArchivo = $tipo . '_' . $hash . '.' . $extension;

        // Ruta completa: {ruta_base}/{año}/{mes}/{nombre_archivo}
        $rutaCompleta = $rutaBase . '/' . $year . '/' . $month . '/' . $nombreArchivo;

        // Guardar en el storage del ERP
        $rutaGuardada = $foto->storeAs(
            $rutaBase . '/' . $year . '/' . $month,
            $nombreArchivo,
            'erp_storage'
        );

        // Obtener URL pública
        $urlPublica = Storage::disk('erp_storage')->url($rutaGuardada);

        return [
            'ruta_relativa' => $rutaGuardada,
            'url_publica' => $urlPublica
        ];
    }

    /**
     * Obtener estado de asistencia del día actual
     * 
     * Query params opcionales:
     * - dni_ce: DNI del empleado
     * - id_personal_residencia: ID de la residencia específica (si trabaja en varias)
     * 
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function estado(Request $request)
    {
        try {
            // Obtener personal_residencia (propia o de otro si se pasa dni_ce)
            $resultado = $this->obtenerPersonalResidencia($request);

            if ($resultado['error']) {
                $codigoError = str_contains($resultado['error'], 'No se encontró') ? 404 : 403;
                return response()->json([
                    'success' => false,
                    'message' => $resultado['error']
                ], $codigoError);
            }

            $personalResidencia = $resultado['personal_residencia'];
            $personalObjetivo = $resultado['personal'];
            $personalIdParaConsulta = $personalObjetivo ? $personalObjetivo->id_personal : $request->user()->personal_id;

            // Fecha de ayer (zona horaria Perú)
            $hoy = Carbon::now()->setTimezone('America/Lima');
            $fechaHoy = $hoy->format('Y-m-d');
            $diaSemana = $hoy->format('l');
            $fechaAyer = $hoy->copy()->subDay()->format('Y-m-d');

            // Obtener todas las personal_residencia activas del empleado
            $todasPersonalResidencias = PersonalResidencia::where('id_personal', $personalIdParaConsulta)
                ->where('activo', true)
                ->pluck('id')
                ->toArray();

            // Si se especifica una residencia en particular, filtrar solo esa
            $idPersonalResidenciaEspecifica = $request->input('id_personal_residencia');
            if ($idPersonalResidenciaEspecifica) {
                if (in_array($idPersonalResidenciaEspecifica, $todasPersonalResidencias)) {
                    $todasPersonalResidencias = [$idPersonalResidenciaEspecifica];
                } else {
                    return response()->json([
                        'success' => false,
                        'message' => 'La residencia especificada no está asignada al empleado o no está activa'
                    ], 403);
                }
            }

            // Buscar registro de asistencia de hoy en las personal_residencia seleccionadas
            $registroHoy = RegistroAsistencia::whereIn('id_personal_residencia', $todasPersonalResidencias)
                ->where('fecha_entrada', $fechaHoy)
                ->whereNotNull('id_asignacion_recurrente')
                ->orderBy('fecha_entrada', 'desc')
                ->orderBy('hora_entrada', 'desc')
                ->first();

            // Buscar registro sin salida (para soportar turnos nocturnos: entrada ayer, salida hoy)
            $registroSinSalida = RegistroAsistencia::whereIn('id_personal_residencia', $todasPersonalResidencias)
                ->whereNotNull('hora_entrada')
                ->whereNotNull('id_asignacion_recurrente')
                ->whereNull('hora_salida')
                ->where('fecha_entrada', '>=', $fechaAyer)
                ->orderBy('fecha_entrada', 'desc')
                ->orderBy('hora_entrada', 'desc')
                ->first();

            $registro = $registroHoy ?: $registroSinSalida;

            $horarioRegistro = null;
            if ($registroSinSalida) {
                $horariosHoy = AsignacionRecurrente::where('id_asignacion_recurrente', $registroSinSalida->id_asignacion_recurrente)
                    ->where('activa', true)
                    ->orderBy('hora_entrada', 'asc')  // Ordenar por hora de entrada
                    ->get();  // Devolver TODOS

                if ($horariosHoy->isNotEmpty()) {
                    $horariosAdicionales = AsignacionRecurrente::whereIn('id_personal_residencia', $todasPersonalResidencias)
                        ->whereNot('id_asignacion_recurrente', $registroSinSalida->id_asignacion_recurrente)
                        ->where('activa', true)
                        ->where('dias_semana', 'like', "%{$diaSemana}%")
                        ->where('fecha_inicio', '<=', $fechaHoy)
                        ->where(function ($query) use ($fechaHoy) {
                            $query->whereNull('fecha_fin')
                                ->orWhere('fecha_fin', '>=', $fechaHoy);
                        })
                        ->orderBy('hora_entrada', 'asc')  // Ordenar por hora de entrada
                        ->get();  // Devolver TODOS
                    $horariosHoy = $horariosHoy->concat($horariosAdicionales);
                }
            } else {
                $horariosHoy = AsignacionRecurrente::whereIn('id_personal_residencia', $todasPersonalResidencias)
                    ->where('activa', true)
                    ->where('dias_semana', 'like', "%{$diaSemana}%")
                    ->where('fecha_inicio', '<=', $fechaHoy)
                    ->where(function ($query) use ($fechaHoy) {
                        $query->whereNull('fecha_fin')
                            ->orWhere('fecha_fin', '>=', $fechaHoy);
                    })
                    ->orderBy('hora_entrada', 'asc')  // Ordenar por hora de entrada
                    ->get();  // Devolver TODOS
            }

            // Si se encontró un horario para hoy y no hay registro, usar la personal_residencia del primer horario
            if ($horariosHoy->isNotEmpty() && !$registro) {
                $personalResidencia = PersonalResidencia::find($horariosHoy->first()->id_personal_residencia);
            }

            // Tiene horario si tiene horario para hoy O para el registro
            $tieneHorario = ($horariosHoy->isNotEmpty()) || ($horarioRegistro !== null);

            // Verificar vacaciones/licencias
            $enVacaciones = false;
            $enLicencia = false;

            try {
                $enVacaciones = Vacacion::where('id_personal', $personalIdParaConsulta)
                    ->where('estado', 'Aprobada')
                    ->where('fecha_inicio', '<=', $fechaHoy)
                    ->where('fecha_fin', '>=', $fechaHoy)
                    ->exists();
            } catch (\Exception $e) {
                // Si no existe el modelo de vacaciones, continuar
            }

            try {
                $enLicencia = Licencia::where('id_personal', $personalIdParaConsulta)
                    ->where('estado', 'Aprobada')
                    ->where('fecha_inicio', '<=', $fechaHoy)
                    ->where('fecha_fin', '>=', $fechaHoy)
                    ->exists();
            } catch (\Exception $e) {
                // Si no existe el modelo de licencias, continuar
            }
            $tieneEntrada = $registro && $registro->hora_entrada !== null;
            $tieneSalida = $registro && $registro->hora_salida !== null;
            $tieneAlgunTurnoSinEntrada = false;
            $tieneAlgunTurnoConEntradaSinSalida = false;

            if ($horariosHoy->isNotEmpty()) {
                foreach ($horariosHoy as $h) {
                    $registroEste = RegistroAsistencia::where('id_personal_residencia', $h->id_personal_residencia)
                        ->where('fecha_entrada', $fechaHoy)
                        ->first();

                    // ¿Hay algún turno sin entrada?
                    if (!$registroEste || !$registroEste->hora_entrada) {
                        $tieneAlgunTurnoSinEntrada = true;
                    }

                    // ¿Hay algún turno con entrada pero sin salida?
                    if ($registroEste && $registroEste->hora_entrada && !$registroEste->hora_salida) {
                        $tieneAlgunTurnoConEntradaSinSalida = true;
                    }
                }
            }

            $puedeMarcarEntrada = $tieneAlgunTurnoSinEntrada && !$enVacaciones && !$enLicencia;
            $puedeMarcarSalida = $tieneAlgunTurnoConEntradaSinSalida;

            $registroData = null;
            if ($registro) {
                $registroData = [
                    'id_registro' => $registro->id_registro,
                    'fecha_entrada' => $registro->fecha_entrada ? Carbon::parse($registro->fecha_entrada)->format('Y-m-d') : null,
                    'hora_entrada' => $registro->hora_entrada ? Carbon::parse($registro->hora_entrada)->format('H:i') : null,
                    'latitud_entrada' => $registro->latitud_entrada,
                    'longitud_entrada' => $registro->longitud_entrada,
                    'foto_entrada' => $registro->foto_entrada,
                    'foto_entrada_url' => $registro->foto_entrada ? Storage::disk('erp_storage')->url($registro->foto_entrada) : null,
                    'fecha_salida' => $registro->fecha_salida ? Carbon::parse($registro->fecha_salida)->format('Y-m-d') : null,
                    'hora_salida' => $registro->hora_salida ? Carbon::parse($registro->hora_salida)->format('H:i') : null,
                    'latitud_salida' => $registro->latitud_salida,
                    'longitud_salida' => $registro->longitud_salida,
                    'foto_salida' => $registro->foto_salida,
                    'foto_salida_url' => $registro->foto_salida ? Storage::disk('erp_storage')->url($registro->foto_salida) : null,
                    'estado' => $registro->estado
                ];
            }
            $horarioRegistroData = null;
            if ($horarioRegistro && $registro && isset($registro) && $registro->fecha_entrada) {
                $horarioRegistro->load('personalResidencia.residencia', 'personalResidencia.personal');
                $personalResidenciaRegistro = $horarioRegistro->personalResidencia;

                $fechaRegistro = Carbon::parse($registro->fecha_entrada)->format('Y-m-d');
                $horaEntradaHorario = Carbon::parse($horarioRegistro->hora_entrada)->format('H:i');
                $horaSalidaHorario = Carbon::parse($horarioRegistro->hora_salida)->format('H:i');

                $fechaEntradaHorario = $fechaRegistro;
                $fechaSalidaHorario = $fechaRegistro;

                if ($horaSalidaHorario <= $horaEntradaHorario) {
                    // Turno nocturno o de 24h: la salida es al día siguiente
                    $fechaSalidaHorario = Carbon::parse($fechaRegistro)->addDay()->format('Y-m-d');
                }

                $horarioRegistroData = [
                    'fecha_entrada' => $fechaEntradaHorario,
                    'hora_entrada' => $horaEntradaHorario,
                    'fecha_salida' => $fechaSalidaHorario,
                    'hora_salida' => $horaSalidaHorario,
                    'dias_semana' => explode(',', $horarioRegistro->dias_semana),
                    'fecha_inicio' => $horarioRegistro->fecha_inicio ? Carbon::parse($horarioRegistro->fecha_inicio)->format('Y-m-d') : null,
                    'fecha_fin' => $horarioRegistro->fecha_fin ? Carbon::parse($horarioRegistro->fecha_fin)->format('Y-m-d') : null,
                    'personal_residencia' => $personalResidenciaRegistro ? [
                        'id' => $personalResidenciaRegistro->id,
                        'cargo' => $personalResidenciaRegistro->cargo . ' - ' . ($personalResidenciaRegistro->personal ? trim($personalResidenciaRegistro->personal->nombres . ' ' . $personalResidenciaRegistro->personal->apellidos) : 'Sin nombre')
                    ] : null,
                    'residencia' => $personalResidenciaRegistro && $personalResidenciaRegistro->residencia ? [
                        'id_residencia' => $personalResidenciaRegistro->residencia->id_residencia,
                        'nombre' => $personalResidenciaRegistro->residencia->nombre
                    ] : null
                ];
            }
            // Formatear TODOS los horarios de hoy con su estado individual
            $horariosHoyData = [];
            $yaMarcadoTrue = false;
            $countTieneEntrada = 0;
            $countTieneSalida = 0;
            if ($horariosHoy->isNotEmpty()) {
                $horariosHoyData = $horariosHoy->map(function ($horarioHoy) use ($fechaHoy, $todasPersonalResidencias, $enVacaciones, $enLicencia, &$yaMarcadoTrue, &$countTieneEntrada, &$countTieneSalida, $registro, $tieneHorario) {

                    // Cargar relación personal_residencia con residencia y personal
                    $horarioHoy->load('personalResidencia.residencia', 'personalResidencia.personal');
                    $personalResidenciaHoy = $horarioHoy->personalResidencia;

                    $horaEntradaHorario = Carbon::parse($horarioHoy->hora_entrada)->format('H:i');
                    $horaSalidaHorario = Carbon::parse($horarioHoy->hora_salida)->format('H:i');

                    if ($registro && $registro->fecha_entrada) {
                        $fechaEntradaHorario = $registro->fecha_entrada;
                        $fechaSalidaHorario = $registro->fecha_entrada;
                    } else {
                        $fechaEntradaHorario = $fechaHoy;
                        $fechaSalidaHorario = $fechaHoy;
                    }

                    if ($horaSalidaHorario <= $horaEntradaHorario) {
                        // Turno nocturno o de 24h: la salida es al día siguiente
                        $fechaSalidaHorario = Carbon::parse($fechaSalidaHorario)->addDay()->format('Y-m-d');
                    }

                    // Verificar si THIS residencia tiene registro de entrada hoy
                    $registroEsteHorario = RegistroAsistencia::where('id_personal_residencia', $horarioHoy->id_personal_residencia)
                        ->where('id_asignacion_recurrente', $horarioHoy->id_asignacion_recurrente)
                        ->where('fecha_entrada', $fechaEntradaHorario)
                        ->first();
                    $tieneEntradaEste = $registroEsteHorario && $registroEsteHorario->hora_entrada !== null;
                    $tieneSalidaEste = $registroEsteHorario && $registroEsteHorario->hora_salida !== null;

                    if ($tieneEntradaEste) {
                        $countTieneEntrada++;
                    }
                    if ($tieneSalidaEste) {
                        $countTieneSalida++;
                    }
                    $puedeMarcarEntradaEste = !$enVacaciones && !$enLicencia;

                    if ($tieneEntradaEste && $tieneSalidaEste) {
                        $puedeMarcarSalidaEste = false;
                        $puedeMarcarEntradaEste = false;
                    } elseif ($tieneEntradaEste && !$tieneSalidaEste) {
                        $puedeMarcarSalidaEste = true;
                        $puedeMarcarEntradaEste = false;
                    } else {
                        $puedeMarcarSalidaEste = false;
                        $puedeMarcarEntradaEste = true;
                    }

                    // Si ya se encontró previamente un turno con alguno de los permisos en true,
                    // bloquear ambos para los turnos restantes.
                    if ($yaMarcadoTrue) {
                        $puedeMarcarEntradaEste = false;
                        $puedeMarcarSalidaEste = false;
                    } else {
                        // Si en este turno cualquiera es true, marcar la bandera para bloquear los siguientes
                        if ($puedeMarcarEntradaEste || $puedeMarcarSalidaEste) {
                            $yaMarcadoTrue = true;
                        }
                    }




                    $registroEste = RegistroAsistencia::where('id_personal_residencia', $horarioHoy->id_personal_residencia)
                        ->where('id_asignacion_recurrente', $horarioHoy->id_asignacion_recurrente)
                        ->where('fecha_entrada', $fechaEntradaHorario)
                        ->first();


                    $registroHorarioHoyData = null;
                    if ($registroEste) {
                        $registroHorarioHoyData = [
                            'id_registro' => $registroEste->id_registro,
                            'fecha_entrada' => $registroEste->fecha_entrada ? Carbon::parse($registroEste->fecha_entrada)->format('Y-m-d') : null,
                            'hora_entrada' => $registroEste->hora_entrada ? Carbon::parse($registroEste->hora_entrada)->format('H:i') : null,
                            'latitud_entrada' => $registroEste->latitud_entrada,
                            'longitud_entrada' => $registroEste->longitud_entrada,
                            'foto_entrada' => $registroEste->foto_entrada,
                            'foto_entrada_url' => $registroEste->foto_entrada ? Storage::disk('erp_storage')->url($registroEste->foto_entrada) : null,
                            'fecha_salida' => $registroEste->fecha_salida ? Carbon::parse($registroEste->fecha_salida)->format('Y-m-d') : null,
                            'hora_salida' => $registroEste->hora_salida ? Carbon::parse($registroEste->hora_salida)->format('H:i') : null,
                            'latitud_salida' => $registroEste->latitud_salida,
                            'longitud_salida' => $registroEste->longitud_salida,
                            'foto_salida' => $registroEste->foto_salida,
                            'foto_salida_url' => $registroEste->foto_salida ? Storage::disk('erp_storage')->url($registroEste->foto_salida) : null,
                            'estado' => $registroEste->estado
                        ];
                    }
                    return [
                        'id_asignacion_recurrente' => $horarioHoy->id_asignacion_recurrente,
                        'id_personal_residencia' => $horarioHoy->id_personal_residencia,
                        'fecha_entrada' => $fechaEntradaHorario,
                        'hora_entrada' => $horaEntradaHorario,
                        'fecha_salida' => $fechaSalidaHorario,
                        'hora_salida' => $horaSalidaHorario,
                        'dias_semana' => explode(',', $horarioHoy->dias_semana),
                        'fecha_inicio' => $horarioHoy->fecha_inicio ? Carbon::parse($horarioHoy->fecha_inicio)->format('Y-m-d') : null,
                        'fecha_fin' => $horarioHoy->fecha_fin ? Carbon::parse($horarioHoy->fecha_fin)->format('Y-m-d') : null,
                        'personal_residencia' => $personalResidenciaHoy ? [
                            'id' => $personalResidenciaHoy->id,
                            'cargo' => $personalResidenciaHoy->cargo . ' - ' . ($personalResidenciaHoy->personal ? trim($personalResidenciaHoy->personal->nombres . ' ' . $personalResidenciaHoy->personal->apellidos) : 'Sin nombre')
                        ] : null,
                        'residencia' => $personalResidenciaHoy && $personalResidenciaHoy->residencia ? [
                            'id_residencia' => $personalResidenciaHoy->residencia->id_residencia,
                            'nombre' => $personalResidenciaHoy->residencia->nombre
                        ] : null,
                        // NUEVO: Estado individual de cada turno
                        'tiene_entrada' => $tieneEntradaEste,
                        'tiene_salida' => $tieneSalidaEste,
                        'puede_marcar_entrada' => $puedeMarcarEntradaEste,
                        'puede_marcar_salida' => $puedeMarcarSalidaEste,
                        'registro' => $registroHorarioHoyData,
                    ];
                })->toArray();
            }

            if ($enVacaciones) {
                $mensaje = 'El empleado está en vacaciones aprobadas';
            } elseif ($enLicencia) {
                $mensaje = 'El empleado está en licencia aprobada';
            } elseif (!$tieneHorario) {
                $mensaje = 'No tiene horario asignado para hoy';
            } elseif ($tieneEntrada && $tieneSalida) {
                $mensaje = 'Asistencia completa del día';
            } elseif ($puedeMarcarSalida) {
                if ($registro && $registro->fecha_entrada != $fechaHoy) {
                    $fechaEntradaFormato = Carbon::parse($registro->fecha_entrada)->format('d/m/Y');
                    $mensaje = "Pendiente marcar salida - Entrada: {$fechaEntradaFormato}";
                } else {
                    $mensaje = 'Puede marcar su salida';
                }
            } elseif ($puedeMarcarEntrada) {
                $mensaje = 'Puede marcar su entrada';
            } else {
                $mensaje = 'Sin acciones pendientes';
            }

            Log::info('Horarios hoy: ' . count($horariosHoyData) . ', Tiene entrada: ' . ($tieneEntrada ? 'Sí' : 'No') . ', Tiene salida: ' . ($tieneSalida ? 'Sí' : 'No') . ', Puede marcar entrada: ' . ($puedeMarcarEntrada ? 'Sí' : 'No') . ', Puede marcar salida: ' . ($puedeMarcarSalida ? 'Sí' : 'No') . ', En vacaciones: ' . ($enVacaciones ? 'Sí' : 'No') . ', En licencia: ' . ($enLicencia ? 'Sí' : 'No'));

            return response()->json([
                'success' => true,
                'fecha' => $fechaHoy,
                'tiene_entrada' => $tieneEntrada,
                'tiene_salida' => $tieneSalida,
                'puede_marcar_entrada' => $puedeMarcarEntrada,
                'puede_marcar_salida' => $puedeMarcarSalida,
                'tiene_horario' => $tieneHorario,
                'total_horarios_hoy' => count($horariosHoyData),
                'en_vacaciones' => $enVacaciones,
                'en_licencia' => $enLicencia,
                'horario_registro' => $horarioRegistroData,
                'horario_hoy' => $horariosHoyData[0] ?? null,  // Retrocompatibilidad: devuelve el PRIMER horario (objeto)
                'horarios_hoy' => $horariosHoyData,  // NUEVO: devuelve TODOS los horarios (array)
                'registro' => $registroData,
                'mensaje' => $mensaje
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error al obtener estado: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * Marcar entrada automática
     * 
     * Body opcional:
     * - dni_ce: DNI del empleado
     * - id_personal_residencia: ID de la residencia donde marca (requerido si trabaja en varias)
     * - latitud: Latitud de la ubicación (requerido)
     * - longitud: Longitud de la ubicación (requerido)
     * - foto: Imagen de la entrada (requerido, multipart/form-data)
     * 
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function marcarEntrada(Request $request)
    {
        try {
            // Validar coordenadas y foto
            try {
                $request->validate([
                    'latitud' => ['required', 'numeric', 'between:-90,90'],
                    'longitud' => ['required', 'numeric', 'between:-180,180'],
                    'foto' => ['required', 'image', 'mimes:jpeg,jpg,png,webp', 'max:5120'],
                    'id_asignacion_recurrente' => ['required', 'integer', 'exists:asignacion_recurrente,id_asignacion_recurrente'],
                    'dni_ce' => ['sometimes', 'string', 'max:20'],
                    'id_personal_residencia' => ['sometimes', 'integer', 'exists:personal_residencia,id'],
                ]);
            } catch (\Illuminate\Validation\ValidationException $e) {
                return response()->json([
                    'success' => false,
                    'message' => 'Error de validación',
                    'errors' => $e->errors()
                ], 422);
            }

            // Obtener personal_residencia (propia o de otro si se pasa dni_ce)
            $resultado = $this->obtenerPersonalResidencia($request);

            if ($resultado['error']) {
                $codigoError = str_contains($resultado['error'], 'No se encontró') ? 404 : 403;
                return response()->json([
                    'success' => false,
                    'message' => $resultado['error']
                ], $codigoError);
            }

            
            $personalResidencia = $resultado['personal_residencia'];
            $personalObjetivo = $resultado['personal'];
            $personalIdParaConsulta = $personalObjetivo ? $personalObjetivo->id_personal : $request->user()->personal_id;
            $user = $request->user();
            $idAsignacionRecurrente = $request->input('id_asignacion_recurrente');

            // Fecha y hora actual (zona horaria Perú)
            $ahora = Carbon::now()->setTimezone('America/Lima');
            $fechaHoy = $ahora->format('Y-m-d');
            $horaActual = $ahora->format('H:i:s');
            $diaSemana = $ahora->format('l');

            // Obtener todas las personal_residencia activas del empleado
            $todasPersonalResidencias = PersonalResidencia::where('id_personal', $personalIdParaConsulta)
                ->where('activo', true)
                ->pluck('id')
                ->toArray();

            // Si se especifica una residencia en particular, usar solo esa
            $idPersonalResidenciaEspecifica = $request->input('id_personal_residencia');
            if ($idPersonalResidenciaEspecifica) {
                if (in_array($idPersonalResidenciaEspecifica, $todasPersonalResidencias)) {
                    $todasPersonalResidencias = [$idPersonalResidenciaEspecifica];
                    $personalResidencia = PersonalResidencia::find($idPersonalResidenciaEspecifica);
                } else {
                    return response()->json([
                        'success' => false,
                        'message' => 'La residencia especificada no está asignada al empleado o no está activa'
                    ], 403);
                }
            }

            // Buscar horarios en las personal_residencia seleccionadas (ordenados por hora)
            $horariosDisponibles = AsignacionRecurrente::whereIn('id_personal_residencia', $todasPersonalResidencias)
                ->where('activa', true)
                ->where('dias_semana', 'like', "%{$diaSemana}%")
                ->where('fecha_inicio', '<=', $fechaHoy)
                ->where('id_asignacion_recurrente', $idAsignacionRecurrente)
                ->where(function ($query) use ($fechaHoy) {
                    $query->whereNull('fecha_fin')
                        ->orWhere('fecha_fin', '>=', $fechaHoy);
                })
                ->orderBy('hora_entrada', 'asc')  // Ordenar por hora de entrada
                ->get();

            if ($horariosDisponibles->isEmpty()) {
                return response()->json([
                    'success' => false,
                    'message' => 'No tiene horario asignado para hoy'
                ], 400);
            }

            // Si NO se especificó residencia, buscar el PRIMER turno que NO tenga entrada
            $horario = null;
            if (!$idPersonalResidenciaEspecifica) {
                foreach ($horariosDisponibles as $h) {
                    $tieneEntradaEste = RegistroAsistencia::where('id_personal_residencia', $h->id_personal_residencia)
                        ->where('id_asignacion_recurrente', $idAsignacionRecurrente)
                        ->where('fecha_entrada', $fechaHoy)
                        ->whereNotNull('hora_entrada')
                        ->exists();

                    if (!$tieneEntradaEste) {
                        $horario = $h;
                        break;
                    }
                }
            } else {
                // Si SÍ se especificó residencia, usar ese horario
                $horario = $horariosDisponibles->first();
            }

            if (!$horario) {
                return response()->json([
                    'success' => false,
                    'message' => 'Ya tiene entrada marcada en todos los turnos de hoy'
                ], 400);
            }

            // Usar la personal_residencia del horario encontrado
            $personalResidencia = PersonalResidencia::find($horario->id_personal_residencia);

            // Verificar que no tenga entrada marcada hoy en ESTE horario específico
            $existente = RegistroAsistencia::where('id_personal_residencia', $personalResidencia->id)
                ->where('id_asignacion_recurrente', $idAsignacionRecurrente)
                ->where('fecha_entrada', $fechaHoy)
                ->first();

            if ($existente && $existente->hora_entrada) {
                return response()->json([
                    'success' => false,
                    'message' => 'Ya tiene entrada marcada para este turno'
                ], 400);
            }

            // Verificar vacaciones/licencias
            try {
                $enVacaciones = Vacacion::where('id_personal', $personalIdParaConsulta)
                    ->where('estado', 'Aprobada')
                    ->where('fecha_inicio', '<=', $fechaHoy)
                    ->where('fecha_fin', '>=', $fechaHoy)
                    ->exists();

                if ($enVacaciones) {
                    return response()->json([
                        'success' => false,
                        'message' => 'No puede marcar asistencia: está en vacaciones aprobadas'
                    ], 400);
                }
            } catch (\Exception $e) {
                // Continuar si no existe el modelo
            }

            try {
                $enLicencia = Licencia::where('id_personal', $personalIdParaConsulta)
                    ->where('estado', 'Aprobada')
                    ->where('fecha_inicio', '<=', $fechaHoy)
                    ->where('fecha_fin', '>=', $fechaHoy)
                    ->exists();

                if ($enLicencia) {
                    return response()->json([
                        'success' => false,
                        'message' => 'No puede marcar asistencia: está en licencia aprobada'
                    ], 400);
                }
            } catch (\Exception $e) {
                // Continuar si no existe el modelo
            }

            // Obtener coordenadas de entrada (ya validadas arriba)
            $latitudEntrada = $request->input('latitud');
            $longitudEntrada = $request->input('longitud');

            // Determinar estado (Presente o Tardanza)
            $horaEntradaHorario = Carbon::parse($horario->hora_entrada)->format('H:i');
            $horaActualFormato = $ahora->format('H:i');
            $estado = ($horaActualFormato > $horaEntradaHorario) ? 'Tardanza' : 'Presente';

            // Combinar fecha y hora
            $horaEntradaReal = Carbon::createFromFormat(
                'Y-m-d H:i:s',
                $fechaHoy . ' ' . $horaActual
            );

            // Obtener ID temporal para generar el hash (usaremos 0 si no existe registro aún)
            $idRegistroTemporal = $existente ? $existente->id_registro : 0;
            $personalId = $personalObjetivo ? $personalObjetivo->id_personal : $user->personal_id;

            // Guardar foto de entrada
            $foto = $request->file('foto');
            $fotoData = $this->guardarFotoAsistencia($foto, 'entrada', $idRegistroTemporal, $personalId, $fechaHoy);

            DB::beginTransaction();

            try {
                // Usar el procedimiento almacenado si existe, sino crear directamente
                try {
                    DB::statement(
                        'CALL sp_registrar_asistencia(?, ?, ?, ?, ?, ?)',
                        [
                            $personalResidencia->id,
                            $idAsignacionRecurrente,
                            $fechaHoy,
                            $horaEntradaReal,
                            'Marcado desde app móvil',
                            $user->id
                        ]
                    );

                    // Si el procedimiento se ejecutó, actualizar coordenadas y estado
                    $registroActualizado = RegistroAsistencia::where('id_personal_residencia', $personalResidencia->id)
                        ->where('id_asignacion_recurrente', $idAsignacionRecurrente)
                        ->first();

                    if ($registroActualizado) {
                        $registroActualizado->latitud_entrada = $latitudEntrada;
                        $registroActualizado->longitud_entrada = $longitudEntrada;
                        $registroActualizado->foto_entrada = $fotoData['ruta_relativa'];
                        $registroActualizado->estado = $estado;
                        $registroActualizado->save();
                    }
                } catch (\Exception $e) {
                    // Si el procedimiento no existe, crear directamente
                    /*if ($existente) {
                        $existente->hora_entrada = $horaEntradaReal;
                        $existente->latitud_entrada = $latitudEntrada;
                        $existente->longitud_entrada = $longitudEntrada;
                        //$existente->foto_entrada = $fotoData['ruta_relativa'];
                        $existente->estado = $estado;
                        $existente->observaciones = 'Marcado desde app móvil';
                        $existente->save();
                    } else {*/
                    $nuevoRegistro = RegistroAsistencia::create([
                        'id_personal_residencia' => $personalResidencia->id,
                        'id_asignacion_recurrente' => $idAsignacionRecurrente,
                        'fecha_entrada' => $fechaHoy,
                        'hora_entrada' => $horaEntradaReal,
                        'latitud_entrada' => $latitudEntrada,
                        'longitud_entrada' => $longitudEntrada,
                        'foto_entrada' => $fotoData['ruta_relativa'],
                        'estado' => $estado,
                        'observaciones' => 'Marcado desde app móvil',
                        'fecha_creacion' => Carbon::now()->setTimezone('America/Lima'),
                        'usuario_creacion' => $user->id
                    ]);

                    // Si el hash se generó con id_registro = 0, actualizar con el nombre correcto
                    if ($idRegistroTemporal == 0 && $nuevoRegistro->id_registro) {
                        // Regenerar nombre con el ID real
                        $extension = $foto->getClientOriginalExtension();
                        $hash = substr(
                            hash('sha256', $nuevoRegistro->id_registro . time() . random_bytes(16) . $personalId),
                            0,
                            16
                        );
                        $year = date('Y', strtotime($fechaHoy));
                        $month = date('m', strtotime($fechaHoy));
                        $rutaBase = env('ASISTENCIA_FOTOS_PATH', 'asistencia/fotos');
                        $nuevoNombre = 'entrada_' . $hash . '.' . $extension;
                        $nuevaRuta = $rutaBase . '/' . $year . '/' . $month . '/' . $nuevoNombre;

                        // Renombrar archivo
                        $rutaVieja = $fotoData['ruta_relativa'];
                        if (Storage::disk('erp_storage')->exists($rutaVieja)) {
                            Storage::disk('erp_storage')->move($rutaVieja, $nuevaRuta);
                            $nuevoRegistro->foto_entrada = $nuevaRuta;
                            $nuevoRegistro->save();
                            $fotoData['ruta_relativa'] = $nuevaRuta;
                            $fotoData['url_publica'] = Storage::disk('erp_storage')->url($nuevaRuta);
                        }
                    }
                    // }
                }

                DB::commit();

                // Obtener el registro creado/actualizado
                $registro = RegistroAsistencia::where('id_personal_residencia', $personalResidencia->id)
                    ->where('id_asignacion_recurrente', $idAsignacionRecurrente)
                    ->first();

                return response()->json([
                    'success' => true,
                    'message' => 'Entrada marcada correctamente',
                    'registro' => [
                        'id_registro' => $registro->id_registro,
                        'id_asignacion_recurrente' => $registro->id_asignacion_recurrente,
                        'fecha_entrada' => $registro->fecha_entrada ? Carbon::parse($registro->fecha_entrada)->format('Y-m-d') : null,
                        'hora_entrada' => $registro->hora_entrada ? Carbon::parse($registro->hora_entrada)->format('H:i') : null,
                        'latitud_entrada' => $registro->latitud_entrada,
                        'longitud_entrada' => $registro->longitud_entrada,
                        'foto_entrada' => $registro->foto_entrada,
                        'foto_entrada_url' => $registro->foto_entrada ? Storage::disk('erp_storage')->url($registro->foto_entrada) : null,
                        'estado' => $registro->estado
                    ]
                ], 201);
            } catch (\Exception $e) {
                DB::rollBack();
                throw $e;
            }
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error al marcar entrada: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * Marcar salida automática
     * 
     * Body opcional:
     * - dni_ce: DNI del empleado
     * - id_personal_residencia: ID de la residencia donde marca (opcional, se detecta automáticamente)
     * - latitud: Latitud de la ubicación (requerido)
     * - longitud: Longitud de la ubicación (requerido)
     * - foto: Imagen de la salida (requerido, multipart/form-data)
     * 
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function marcarSalida(Request $request)
    {
        try {
            // Validar coordenadas y foto
            $request->validate([
                'latitud' => ['required', 'numeric', 'between:-90,90'],
                'longitud' => ['required', 'numeric', 'between:-180,180'],
                'foto' => ['required', 'image', 'mimes:jpeg,jpg,png,webp', 'max:5120'],
                'dni_ce' => ['sometimes', 'string', 'max:20'],
                'id_personal_residencia' => ['sometimes', 'integer', 'exists:personal_residencia,id'],
            ]);

            // Obtener personal_residencia (propia o de otro si se pasa dni_ce)
            $resultado = $this->obtenerPersonalResidencia($request);

            if ($resultado['error']) {
                $codigoError = str_contains($resultado['error'], 'No se encontró') ? 404 : 403;
                return response()->json([
                    'success' => false,
                    'message' => $resultado['error']
                ], $codigoError);
            }

            $personalResidencia = $resultado['personal_residencia'];
            $personalObjetivo = $resultado['personal'];
            $personalIdParaConsulta = $personalObjetivo ? $personalObjetivo->id_personal : $request->user()->personal_id;
            $user = $request->user();

            // Fecha y hora actual (zona horaria Perú)
            $ahora = Carbon::now()->setTimezone('America/Lima');
            $fechaHoy = $ahora->format('Y-m-d');
            $horaActual = $ahora->format('H:i:s');

            // Obtener todas las personal_residencia activas del empleado
            $todasPersonalResidencias = PersonalResidencia::where('id_personal', $personalIdParaConsulta)
                ->where('activo', true)
                ->pluck('id')
                ->toArray();

            // Si se especifica una residencia en particular, filtrar solo esa
            $idPersonalResidenciaEspecifica = $request->input('id_personal_residencia');
            if ($idPersonalResidenciaEspecifica) {
                if (in_array($idPersonalResidenciaEspecifica, $todasPersonalResidencias)) {
                    $todasPersonalResidencias = [$idPersonalResidenciaEspecifica];
                } else {
                    return response()->json([
                        'success' => false,
                        'message' => 'La residencia especificada no está asignada al empleado o no está activa'
                    ], 403);
                }
            }

            // Buscar el registro más reciente sin salida (para soportar turnos nocturnos)
            // Esto permite que la entrada sea de ayer y la salida de hoy
            $registro = RegistroAsistencia::whereIn('id_personal_residencia', $todasPersonalResidencias)
                ->whereNotNull('hora_entrada')  // Debe tener entrada marcada
                ->whereNull('hora_salida')      // No debe tener salida marcada
                ->orderBy('fecha_entrada', 'desc')
                ->orderBy('hora_entrada', 'desc')
                ->first();

            // Si se encontró un registro, usar la personal_residencia donde está el registro
            if ($registro) {
                $personalResidencia = PersonalResidencia::find($registro->id_personal_residencia);
            }

            if (!$registro) {
                return response()->json([
                    'success' => false,
                    'message' => 'No tiene entrada marcada sin salida'
                ], 400);
            }

            // Obtener coordenadas de salida (ya validadas arriba)
            $latitudSalida = $request->input('latitud');
            $longitudSalida = $request->input('longitud');

            // Verificar que la hora de salida sea posterior a la entrada
            // Para turnos nocturnos: entrada puede ser ayer, salida hoy
            $fechaEntrada = Carbon::parse($registro->fecha_entrada)->format('Y-m-d');
            $horaEntrada = Carbon::createFromFormat('Y-m-d H:i:s', $fechaEntrada . ' ' . Carbon::parse($registro->hora_entrada)->format('H:i:s'));
            $horaSalida = Carbon::createFromFormat('Y-m-d H:i:s', $fechaHoy . ' ' . $horaActual);

            if ($horaSalida->lte($horaEntrada)) {
                return response()->json([
                    'success' => false,
                    'message' => 'La hora de salida debe ser posterior a la hora de entrada'
                ], 400);
            }

            // Validación adicional: la salida no debe ser más de 48 horas después de la entrada
            // (para evitar marcar salidas de registros muy antiguos)
            $diferenciaHoras = $horaEntrada->diffInHours($horaSalida);
            if ($diferenciaHoras > 48) {
                return response()->json([
                    'success' => false,
                    'message' => 'La salida no puede ser más de 48 horas después de la entrada'
                ], 400);
            }

            // Guardar foto de salida
            $foto = $request->file('foto');
            $personalId = $resultado['personal'] ? $resultado['personal']->id_personal : $user->personal_id;
            $fotoData = $this->guardarFotoAsistencia($foto, 'salida', $registro->id_registro, $personalId, $fechaHoy);

            // Actualizar registro
            $registro->fecha_salida = $fechaHoy;
            $registro->hora_salida = $horaSalida;
            $registro->latitud_salida = $latitudSalida;
            $registro->longitud_salida = $longitudSalida;
            $registro->foto_salida = $fotoData['ruta_relativa'];
            $registro->save();

            return response()->json([
                'success' => true,
                'message' => 'Salida marcada correctamente',
                'registro' => [
                    'id_registro' => $registro->id_registro,
                    'fecha_entrada' => $registro->fecha_entrada ? Carbon::parse($registro->fecha_entrada)->format('Y-m-d') : null,
                    'hora_entrada' => $registro->hora_entrada ? Carbon::parse($registro->hora_entrada)->format('H:i') : null,
                    'latitud_entrada' => $registro->latitud_entrada,
                    'longitud_entrada' => $registro->longitud_entrada,
                    'foto_entrada' => $registro->foto_entrada,
                    'foto_entrada_url' => $registro->foto_entrada ? Storage::disk('erp_storage')->url($registro->foto_entrada) : null,
                    'fecha_salida' => $registro->fecha_salida ? Carbon::parse($registro->fecha_salida)->format('Y-m-d') : null,
                    'hora_salida' => $registro->hora_salida ? Carbon::parse($registro->hora_salida)->format('H:i') : null,
                    'latitud_salida' => $registro->latitud_salida,
                    'longitud_salida' => $registro->longitud_salida,
                    'foto_salida' => $registro->foto_salida,
                    'foto_salida_url' => $registro->foto_salida ? Storage::disk('erp_storage')->url($registro->foto_salida) : null,
                    'estado' => $registro->estado
                ]
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error al marcar salida: ' . $e->getMessage()
            ], 500);
        }
    }

    /**
     * Obtener historial de asistencia
     * 
     * Query params opcionales:
     * - dni_ce: DNI del empleado
     * - id_personal_residencia: ID de residencia específica (si no se pasa, muestra de todas)
     * - limite: Número de días a mostrar (default: 30)
     * - desde: Fecha inicio (formato: Y-m-d)
     * - hasta: Fecha fin (formato: Y-m-d)
     * 
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function historial(Request $request)
    {
        try {
            // Obtener personal_residencia (propia o de otro si se pasa dni_ce)
            $resultado = $this->obtenerPersonalResidencia($request);

            if ($resultado['error']) {
                $codigoError = str_contains($resultado['error'], 'No se encontró') ? 404 : 403;
                return response()->json([
                    'success' => false,
                    'message' => $resultado['error']
                ], $codigoError);
            }

            $personalResidencia = $resultado['personal_residencia'];
            $personalObjetivo = $resultado['personal'];
            $personalIdParaConsulta = $personalObjetivo ? $personalObjetivo->id_personal : $request->user()->personal_id;

            // Parámetros opcionales
            $limite = $request->input('limite', 30); // Por defecto últimos 30 días
            $desde = $request->input('desde');
            $hasta = $request->input('hasta');
            $idPersonalResidenciaEspecifica = $request->input('id_personal_residencia');

            // Obtener todas las personal_residencia activas
            $todasPersonalResidencias = PersonalResidencia::where('id_personal', $personalIdParaConsulta)
                ->where('activo', true)
                ->pluck('id')
                ->toArray();

            // Si se especifica una residencia, filtrar solo esa
            if ($idPersonalResidenciaEspecifica) {
                if (in_array($idPersonalResidenciaEspecifica, $todasPersonalResidencias)) {
                    $todasPersonalResidencias = [$idPersonalResidenciaEspecifica];
                } else {
                    return response()->json([
                        'success' => false,
                        'message' => 'La residencia especificada no está asignada al empleado o no está activa'
                    ], 403);
                }
            }

            // Construir consulta para TODAS las residencias activas (o una específica)
            $query = RegistroAsistencia::with(['personalResidencia.residencia'])
                ->whereIn('id_personal_residencia', $todasPersonalResidencias)
                ->whereNotNull('id_asignacion_recurrente')
                ->orderBy('fecha_entrada', 'desc');

            if ($desde) {
                $query->where('fecha_entrada', '>=', $desde);
            }

            if ($hasta) {
                $query->where('fecha_entrada', '<=', $hasta);
            }

            if (!$desde && !$hasta) {
                // Si no se especifican fechas, mostrar últimos N días
                $fechaInicio = Carbon::now()->subDays($limite)->format('Y-m-d');
                $query->where('fecha_entrada', '>=', $fechaInicio);
            }

            $registros = $query->limit(100)->get(); // Máximo 100 registros

            // Agrupar registros por fecha_entrada
            $historialAgrupado = $registros->groupBy(function ($registro) {
                return $registro->fecha_entrada ? Carbon::parse($registro->fecha_entrada)->format('Y-m-d') : 'sin_fecha';
            })->map(function ($registrosPorFecha) {
                return $registrosPorFecha->map(function ($registro) {
                    return [
                        'id_registro' => $registro->id_registro,
                        'id_personal_residencia' => $registro->id_personal_residencia,
                        'residencia' => [
                            'id_residencia' => $registro->personalResidencia->residencia->id_residencia ?? null,
                            'nombre' => $registro->personalResidencia->residencia->nombre ?? 'Sin residencia'
                        ],
                        'fecha_entrada' => $registro->fecha_entrada ? Carbon::parse($registro->fecha_entrada)->format('Y-m-d') : null,
                        'hora_entrada' => $registro->hora_entrada ? Carbon::parse($registro->hora_entrada)->format('H:i') : null,
                        'latitud_entrada' => $registro->latitud_entrada,
                        'longitud_entrada' => $registro->longitud_entrada,
                        'foto_entrada' => $registro->foto_entrada,
                        'foto_entrada_url' => $registro->foto_entrada ? Storage::disk('erp_storage')->url($registro->foto_entrada) : null,
                        'fecha_salida' => $registro->fecha_salida ? Carbon::parse($registro->fecha_salida)->format('Y-m-d') : null,
                        'hora_salida' => $registro->hora_salida ? Carbon::parse($registro->hora_salida)->format('H:i') : null,
                        'latitud_salida' => $registro->latitud_salida,
                        'longitud_salida' => $registro->longitud_salida,
                        'foto_salida' => $registro->foto_salida,
                        'foto_salida_url' => $registro->foto_salida ? Storage::disk('erp_storage')->url($registro->foto_salida) : null,
                        'estado' => $registro->estado,
                        'observaciones' => $registro->observaciones
                    ];
                })->values();
            })->values();

            return response()->json([
                'success' => true,
                'total' => $registros->count(),
                'historial' => $historialAgrupado
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error al obtener historial: ' . $e->getMessage()
            ], 500);
        }
    }
}
