<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use PhpOffice\PhpSpreadsheet\Style\Color;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\Border;
use App\Models\Curso;
use App\Models\Alumno;

class ReporteOrdenMeritoController extends Controller
{
    /**
     * Obtener orden de mérito por carrera y ciclo
     * GET /api/reportes/orden-merito
     * Query params: carrera_id, ciclo_id, domain_id
     */
    public function getOrdenMerito(Request $request)
    {
        try {
            $carreraId = $request->query('carrera_id');
            $cicloId = $request->query('ciclo_id');
            $domainId = $request->query('domain_id');

            if (!$carreraId || !$cicloId || !$domainId) {
                return response()->json([
                    'success' => false,
                    'message' => 'Se requieren carrera_id, ciclo_id y domain_id'
                ], 400);
            }

            // Obtener información de la carrera y ciclo
            $carrera = DB::table('carreras')->where('id', $carreraId)->first();
            $ciclo = DB::table('ciclos')->where('id', $cicloId)->first();

            if (!$carrera || !$ciclo) {
                return response()->json([
                    'success' => false,
                    'message' => 'Carrera o ciclo no encontrados'
                ], 404);
            }

            // ✅ Query principal: Calcula promedios usando misma lógica que ParticipanteController
            $alumnos = DB::select("
                SELECT 
                    sub.alumno_id,
                    sub.codigo,
                    sub.nombre_completo,
                    sub.email,
                    sub.total_cursos,
                    sub.promedio_general,
                    DENSE_RANK() OVER (ORDER BY sub.promedio_general DESC) as posicion
                FROM (
                    SELECT 
                        a.id as alumno_id,
                        a.codigo,
                        CONCAT(a.apellidos, ', ', a.nombres) as nombre_completo,
                        a.email,
                        COUNT(DISTINCT c.id) as total_cursos,
                        ROUND(AVG(promedios_grupo.promedio_grupo), 2) as promedio_general
                    FROM alumnos a
                    INNER JOIN curso_alumno ca ON ca.alumno_id = a.id
                    INNER JOIN cursos c ON c.id = ca.curso_id
                    INNER JOIN (
                        -- Calcula promedio ponderado por grupo de evaluaciones
                        SELECT 
                            ge.curso_id,
                            ea.alumno_id,
                            ge.id as grupo_id,
                            SUM(
                                CASE 
                                    WHEN IFNULL(e.aplicar_en_calculo, 1) = 1 
                                    THEN IFNULL(ea.nota, 0) * e.porcentaje_asignado 
                                    ELSE 0 
                                END
                            ) / NULLIF(
                                SUM(
                                    CASE 
                                        WHEN IFNULL(e.aplicar_en_calculo, 1) = 1 
                                        THEN e.porcentaje_asignado 
                                        ELSE 0 
                                    END
                                ), 0
                            ) as promedio_grupo
                        FROM grupo_de_evaluaciones ge
                        LEFT JOIN evaluaciones e ON e.grupo_de_evaluaciones_id = ge.id 
                            AND e.deleted_at IS NULL
                        LEFT JOIN evaluaciones_alumno ea ON ea.evaluacion_id = e.id
                        WHERE ge.deleted_at IS NULL
                        GROUP BY ge.curso_id, ea.alumno_id, ge.id
                        HAVING SUM(
                            CASE 
                                WHEN IFNULL(e.aplicar_en_calculo, 1) = 1 
                                THEN e.porcentaje_asignado 
                                ELSE 0 
                            END
                        ) > 0
                    ) promedios_grupo ON promedios_grupo.curso_id = c.id 
                        AND promedios_grupo.alumno_id = a.id
                    WHERE a.domain_id = ?
                    AND c.carrera_id = ?
                    AND c.ciclo_id = ?
                    AND c.deleted_at IS NULL
                    AND a.deleted_at IS NULL
                    AND ca.estado_curso_id IN (2, 3, 4, 7)
                    GROUP BY a.id
                    HAVING promedio_general IS NOT NULL AND promedio_general > 0
                ) sub
                ORDER BY sub.promedio_general DESC
            ", [$domainId, $carreraId, $cicloId]);

            // ✅ Obtener detalle de cursos para top 20 alumnos
            $alumnosConDetalle = collect($alumnos)->take(20)->map(function ($alumno) use ($carreraId, $cicloId, $domainId) {
                $cursos = DB::select("
                    SELECT 
                        c.codigo,
                        c.nombre,
                        c.cantidad_de_creditos as creditos,
                        ROUND(AVG(promedios_grupo.promedio_grupo), 2) as promedio_curso,
                        ca.nota_recuperacion,
                        ca.sistema_recuperacion,
                        ca.criterio_nota_final
                    FROM cursos c
                    INNER JOIN curso_alumno ca ON ca.curso_id = c.id
                    LEFT JOIN (
                        SELECT 
                            ge.curso_id,
                            ea.alumno_id,
                            SUM(
                                CASE 
                                    WHEN IFNULL(e.aplicar_en_calculo, 1) = 1 
                                    THEN IFNULL(ea.nota, 0) * e.porcentaje_asignado 
                                    ELSE 0 
                                END
                            ) / NULLIF(
                                SUM(
                                    CASE 
                                        WHEN IFNULL(e.aplicar_en_calculo, 1) = 1 
                                        THEN e.porcentaje_asignado 
                                        ELSE 0 
                                    END
                                ), 0
                            ) as promedio_grupo
                        FROM grupo_de_evaluaciones ge
                        LEFT JOIN evaluaciones e ON e.grupo_de_evaluaciones_id = ge.id 
                            AND e.deleted_at IS NULL
                        LEFT JOIN evaluaciones_alumno ea ON ea.evaluacion_id = e.id
                        WHERE ge.deleted_at IS NULL
                        GROUP BY ge.curso_id, ea.alumno_id, ge.id
                    ) promedios_grupo ON promedios_grupo.curso_id = c.id 
                        AND promedios_grupo.alumno_id = ca.alumno_id
                    WHERE ca.alumno_id = ?
                    AND c.carrera_id = ?
                    AND c.ciclo_id = ?
                    AND c.domain_id = ?
                    AND c.deleted_at IS NULL
                    GROUP BY c.id, ca.nota_recuperacion, ca.sistema_recuperacion, ca.criterio_nota_final
                    ORDER BY c.codigo
                ", [$alumno->alumno_id, $carreraId, $cicloId, $domainId]);

                $alumno->cursos = $cursos;
                return $alumno;
            });

            // Estadísticas generales
            $estadisticas = [
                'total_alumnos' => count($alumnos),
                'promedio_general_carrera' => round(collect($alumnos)->avg('promedio_general'), 2),
                'promedio_mas_alto' => count($alumnos) > 0 ? $alumnos[0]->promedio_general : 0,
                'promedio_mas_bajo' => count($alumnos) > 0 ? end($alumnos)->promedio_general : 0,
                'alumnos_destacados' => collect($alumnos)->where('promedio_general', '>=', 16)->count(),
            ];

            return response()->json([
                'success' => true,
                'carrera' => $carrera,
                'ciclo' => $ciclo,
                'alumnos' => $alumnos,
                'alumnos_top_detalle' => $alumnosConDetalle,
                'estadisticas' => $estadisticas
            ]);
        } catch (\Exception $e) {
            Log::error('Error generando orden de mérito:', [
                'carrera_id' => $request->query('carrera_id'),
                'ciclo_id' => $request->query('ciclo_id'),
                'domain_id' => $request->query('domain_id'),
                'error' => $e->getMessage(),
                'line' => $e->getLine(),
                'file' => $e->getFile(),
                'trace' => $e->getTraceAsString()
            ]);

            return response()->json([
                'success' => false,
                'message' => 'Error al generar el reporte',
                'error' => config('app.debug') ? $e->getMessage() : null
            ], 500);
        }
    }

    /**
     * Exportar orden de mérito a CSV
     * GET /api/reportes/orden-merito/export
     */
    public function exportarOrdenMerito(Request $request)
    {
        try {
            $carreraId = $request->query('carrera_id');
            $cicloId = $request->query('ciclo_id');
            $domainId = $request->query('domain_id');

            if (!$carreraId || !$cicloId || !$domainId) {
                return response()->json([
                    'success' => false,
                    'message' => 'Se requieren carrera_id, ciclo_id y domain_id'
                ], 400);
            }

            $cursos = Curso::where('carrera_id', $carreraId)
                ->where('ciclo_id', $cicloId)
                ->where('domain_id', $domainId)
                ->whereNull('deleted_at')
                ->orderBy('codigo')
                ->get();

            $alumnos = DB::select("
                SELECT DISTINCT
                    a.id,
                    a.codigo,
                    a.apellidos,
                    a.nombres
                FROM alumnos a
                INNER JOIN curso_alumno ca ON ca.alumno_id = a.id
                INNER JOIN cursos c ON c.id = ca.curso_id
                WHERE a.domain_id = ?
                AND c.carrera_id = ?
                AND c.ciclo_id = ?
                AND c.deleted_at IS NULL
                AND a.deleted_at IS NULL
                AND ca.estado_curso_id IN (2, 3, 4, 7)
                ORDER BY a.apellidos, a.nombres
            ", [$domainId, $carreraId, $cicloId]);

            $spreadsheet = new Spreadsheet();
            $sheet = $spreadsheet->getActiveSheet();

            $getColumnLetter = function ($colNumber) {
                return \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($colNumber);
            };

            // ===== CALCULAR COLUMNAS =====
            $primerCursoCol = 4; // Columna D
            $ultimoCursoCol = $primerCursoCol + count($cursos) - 1;
            $colExperiencias = $ultimoCursoCol + 1;
            $colAprobadas = $colExperiencias + 1;
            $colDesaprobadas = $colAprobadas + 1;
            $colObservaciones = $colDesaprobadas + 1;

            $primerCursoLetter = $getColumnLetter($primerCursoCol);
            $ultimoCursoLetter = $getColumnLetter($ultimoCursoCol);
            $colExperienciasLetter = $getColumnLetter($colExperiencias);
            $colAprobadasLetter = $getColumnLetter($colAprobadas);
            $colDesaprobadasLetter = $getColumnLetter($colDesaprobadas);
            $colObservacionesLetter = $getColumnLetter($colObservaciones);

            // ===== ESTRUCTURA DE 4 FILAS DE ENCABEZADOS =====

            // ✅ FILA 1: Columnas A, B, C (merge vertical A1:A4)
            $sheet->mergeCells('A1:A4');
            $sheet->setCellValue('A1', 'N°');

            $sheet->mergeCells('B1:B4');
            $sheet->setCellValue('B1', "Número de\ndocumento de\nidentidad");

            $sheet->mergeCells('C1:C4');
            $sheet->setCellValue('C1', "APELLIDOS Y NOMBRES\n(En orden alfabético)");

            // ✅ "UNIDADES DIDÁCTICAS" en fila 1 (INCLUYE cursos + experiencias + aprobadas + desaprobadas)
            $sheet->mergeCells("{$primerCursoLetter}1:{$colDesaprobadasLetter}1");
            $sheet->setCellValue("{$primerCursoLetter}1", 'UNIDADES DIDÁCTICAS');

            // ✅ OBSERVACIONES (merge vertical 1:4) - FUERA de UNIDADES DIDÁCTICAS
            $sheet->mergeCells("{$colObservacionesLetter}1:{$colObservacionesLetter}4");
            $sheet->setCellValue("{$colObservacionesLetter}1", "OBSERVACIONES");

            // ✅ FILA 2: NOMBRES DE CURSOS (rotados 90°)
            $colIndex = $primerCursoCol;
            foreach ($cursos as $curso) {
                $colLetter = $getColumnLetter($colIndex);
                $sheet->setCellValue("{$colLetter}2", $curso->nombre);
                $colIndex++;
            }

            // ✅ FILA 2: EXPERIENCIAS FORMATIVAS (rotado 90°)
            $sheet->setCellValue("{$colExperienciasLetter}2", "EXPERIENCIAS FORMATIVAS EN SITUACIONES REALES DE TRABAJO");

            // ✅ FILA 2: APROBADAS Y DESAPROBADAS (rotado 90°)
            $sheet->setCellValue("{$colAprobadasLetter}2", "NUMERO DE UNIDADES DIDACTICAS APROBADAS");
            $sheet->setCellValue("{$colDesaprobadasLetter}2", "NUMERO DE UNIDADES DIDACTICAS DESAPROBADAS");

            // ✅ FILA 3: "CREDITOS" combina SOLO cursos + experiencias (NO aprobadas/desaprobadas)
            $sheet->mergeCells("{$primerCursoLetter}3:{$colExperienciasLetter}3");
            $sheet->setCellValue("{$primerCursoLetter}3", 'CREDITOS');

            // Celdas vacías en aprobadas/desaprobadas fila 3
            $sheet->setCellValue("{$colAprobadasLetter}3", '');
            $sheet->setCellValue("{$colDesaprobadasLetter}3", '');

            // ✅ FILA 4: VALORES DE CRÉDITOS individuales
            $colIndex = $primerCursoCol;
            foreach ($cursos as $curso) {
                $colLetter = $getColumnLetter($colIndex);
                $sheet->setCellValue("{$colLetter}4", $curso->cantidad_de_creditos);
                $colIndex++;
            }

            // Valor de crédito para experiencias formativas
            $sheet->setCellValue("{$colExperienciasLetter}4", ''); // O el valor que corresponda

            // Celdas vacías en aprobadas/desaprobadas fila 4
            $sheet->setCellValue("{$colAprobadasLetter}4", '');
            $sheet->setCellValue("{$colDesaprobadasLetter}4", '');

            // ===== DATOS DE ALUMNOS (empiezan en fila 5) =====
            $filaActual = 5;
            $contador = 1;

            foreach ($alumnos as $alumno) {
                $sheet->setCellValue("A{$filaActual}", $contador++);
                $sheet->setCellValue("B{$filaActual}", $alumno->codigo);
                $sheet->setCellValue(
                    "C{$filaActual}",
                    strtoupper($alumno->apellidos . ', ' . $alumno->nombres)
                );

                $aprobadas = 0;
                $desaprobadas = 0;
                $colIndex = $primerCursoCol;

                foreach ($cursos as $curso) {
                    $colLetter = $getColumnLetter($colIndex);

                    $promedio = DB::selectOne("
                        SELECT 
                            ROUND(AVG(promedios_grupo.promedio_grupo), 0) as promedio_final
                        FROM curso_alumno ca
                        LEFT JOIN (
                            SELECT 
                                ge.curso_id,
                                ea.alumno_id,
                                SUM(
                                    CASE 
                                        WHEN IFNULL(e.aplicar_en_calculo, 1) = 1 
                                        THEN IFNULL(ea.nota, 0) * e.porcentaje_asignado 
                                        ELSE 0 
                                    END
                                ) / NULLIF(
                                    SUM(
                                        CASE 
                                            WHEN IFNULL(e.aplicar_en_calculo, 1) = 1 
                                            THEN e.porcentaje_asignado 
                                            ELSE 0 
                                        END
                                    ), 0
                                ) as promedio_grupo
                            FROM grupo_de_evaluaciones ge
                            LEFT JOIN evaluaciones e ON e.grupo_de_evaluaciones_id = ge.id 
                                AND e.deleted_at IS NULL
                            LEFT JOIN evaluaciones_alumno ea ON ea.evaluacion_id = e.id
                            WHERE ge.deleted_at IS NULL
                            GROUP BY ge.curso_id, ea.alumno_id, ge.id
                        ) promedios_grupo ON promedios_grupo.curso_id = ca.curso_id 
                            AND promedios_grupo.alumno_id = ca.alumno_id
                        WHERE ca.alumno_id = ?
                        AND ca.curso_id = ?
                        AND ca.estado_curso_id IN (2, 3, 4, 7)
                        GROUP BY ca.curso_id
                    ", [$alumno->id, $curso->id]);

                    if ($promedio && $promedio->promedio_final !== null) {
                        $notaFinal = (int) $promedio->promedio_final;
                        $sheet->setCellValue("{$colLetter}{$filaActual}", $notaFinal);

                        if ($notaFinal < 11) {
                            $sheet->getStyle("{$colLetter}{$filaActual}")
                                ->getFont()->getColor()->setARGB(Color::COLOR_RED);
                            $desaprobadas++;
                        } else {
                            $aprobadas++;
                        }
                    } else {
                        $sheet->setCellValue("{$colLetter}{$filaActual}", '--');
                    }

                    $colIndex++;
                }

                // ✅ Columna de experiencias formativas (ajusta según tu lógica)
                $sheet->setCellValue("{$colExperienciasLetter}{$filaActual}", '--');

                $sheet->setCellValue("{$colAprobadasLetter}{$filaActual}", $aprobadas);
                $sheet->setCellValue("{$colDesaprobadasLetter}{$filaActual}", $desaprobadas);
                $sheet->setCellValue("{$colObservacionesLetter}{$filaActual}", '');

                $filaActual++;
            }

            // ===== ESTILOS =====
            // ===== ESTILOS =====
            $lastRow = $filaActual - 1;

            // ✅ Fondo gris SOLO para nombres de cursos en fila 2 (desde D hasta última columna de curso)
            $sheet->getStyle("{$primerCursoLetter}2:{$ultimoCursoLetter}2")
                ->getFill()
                ->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
                ->getStartColor()->setARGB('FFD9D9D9');

            // ✅ Negrita SOLO en encabezados principales (A, B, C) y título "UNIDADES DIDÁCTICAS"
            $sheet->getStyle("A1:C4")->getFont()->setBold(true); // N°, Doc, Apellidos
            $sheet->getStyle("{$primerCursoLetter}1:{$colDesaprobadasLetter}1")->getFont()->setBold(true); // UNIDADES DIDÁCTICAS
            $sheet->getStyle("{$colObservacionesLetter}1")->getFont()->setBold(true); // OBSERVACIONES

            // ✅ Negrita en nombres de cursos individuales (fila 2, solo cursos)
            $sheet->getStyle("{$primerCursoLetter}2:{$ultimoCursoLetter}2")->getFont()->setBold(true);

            // ✅ Negrita en "CREDITOS" (fila 3)
            $sheet->getStyle("{$primerCursoLetter}3:{$colExperienciasLetter}3")->getFont()->setBold(true);

            // ✅ Negrita en valores de créditos (fila 4, solo cursos)
            $sheet->getStyle("{$primerCursoLetter}4:{$ultimoCursoLetter}4")->getFont()->setBold(true);

            // Centrado horizontal y vertical en TODO
            $sheet->getStyle("A1:{$colObservacionesLetter}{$lastRow}")
                ->getAlignment()
                ->setHorizontal(Alignment::HORIZONTAL_CENTER)
                ->setVertical(Alignment::VERTICAL_CENTER);

            // Ajustar texto (wrap) en columnas A, B, C
            $sheet->getStyle("A1:C4")->getAlignment()->setWrapText(true);

            $sheet->getStyle("{$primerCursoLetter}2:{$colDesaprobadasLetter}2")
                ->getAlignment()
                ->setWrapText(true);

            // ✅ ROTACIÓN 90° para nombres de cursos (fila 2, solo cursos)
            for ($i = $primerCursoCol; $i <= $ultimoCursoCol; $i++) {
                $colLetter = $getColumnLetter($i);
                $sheet->getStyle("{$colLetter}2")
                    ->getAlignment()
                    ->setTextRotation(90);
            }

            // ✅ ROTACIÓN 90° para experiencias formativas (fila 2)
            $sheet->getStyle("{$colExperienciasLetter}2")
                ->getAlignment()
                ->setTextRotation(90);

            // ✅ ROTACIÓN 90° para aprobadas/desaprobadas (fila 2)
            $sheet->getStyle("{$colAprobadasLetter}2")
                ->getAlignment()
                ->setTextRotation(90);

            $sheet->getStyle("{$colDesaprobadasLetter}2")
                ->getAlignment()
                ->setTextRotation(90);

            // ✅ OBSERVACIONES SIN ROTACIÓN (texto normal)
            // No aplicar setTextRotation

            // Bordes en todas las celdas
            $sheet->getStyle("A1:{$colObservacionesLetter}{$lastRow}")
                ->getBorders()->getAllBorders()
                ->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN);

            // ✅ Ajustar anchos de columna
            $sheet->getColumnDimension('A')->setWidth(5);
            $sheet->getColumnDimension('B')->setWidth(20);
            $sheet->getColumnDimension('C')->setWidth(70);

            // Columnas de cursos (texto rotado)
            for ($i = $primerCursoCol; $i <= $ultimoCursoCol; $i++) {
                $sheet->getColumnDimension($getColumnLetter($i))->setWidth(8);
            }

            // Columna experiencias formativas
            $sheet->getColumnDimension($colExperienciasLetter)->setWidth(8);

            // Columnas de aprobadas/desaprobadas
            $sheet->getColumnDimension($colAprobadasLetter)->setWidth(8);
            $sheet->getColumnDimension($colDesaprobadasLetter)->setWidth(8);

            // Columna observaciones (más ancha, sin rotación)
            $sheet->getColumnDimension($colObservacionesLetter)->setWidth(50);

            // ✅ Altura de filas
            $sheet->getRowDimension(1)->setRowHeight(30);
            $sheet->getRowDimension(2)->setRowHeight(300); // Alto para texto rotado
            $sheet->getRowDimension(3)->setRowHeight(20);
            $sheet->getRowDimension(4)->setRowHeight(20);

            // Generar archivo
            $filename = 'registro_evaluacion_' . date('Ymd_His') . '.xlsx';

            $writer = new Xlsx($spreadsheet);

            return response()->streamDownload(function () use ($writer) {
                $writer->save('php://output');
            }, $filename, [
                'Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
                'Access-Control-Expose-Headers' => 'Content-Disposition'
            ]);
        } catch (\Exception $e) {
            Log::error('Error exportando registro:', [
                'error' => $e->getMessage(),
                'line' => $e->getLine()
            ]);

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

    /**
     * ✅ Obtener carreras disponibles
     * GET /api/reportes/carreras
     */
    public function getCarreras(Request $request)
    {
        try {
            $domainId = $request->query('domain_id');

            if (!$domainId) {
                return response()->json([
                    'success' => false,
                    'message' => 'domain_id es requerido'
                ], 400);
            }

            // ✅ Usar 'nombres' (plural) en lugar de 'nombre'
            $carreras = DB::table('carreras')
                ->select('id', 'nombres as nombre', 'codigo') // ✅ Alias 'nombres' como 'nombre'
                ->where('domain_id', $domainId)
                ->orderBy('nombres')
                ->get();

            Log::info('Carreras encontradas:', [
                'total' => $carreras->count(),
                'domain_id' => $domainId
            ]);

            return response()->json([
                'success' => true,
                'data' => $carreras
            ]);
        } catch (\Exception $e) {
            Log::error('Error obteniendo carreras:', [
                'domain_id' => $domainId,
                'error' => $e->getMessage(),
                'line' => $e->getLine(),
                'file' => $e->getFile()
            ]);

            return response()->json([
                'success' => false,
                'message' => 'Error al obtener carreras',
                'error' => config('app.debug') ? $e->getMessage() : null
            ], 500);
        }
    }

    /**
     * ✅ Obtener ciclos disponibles
     * GET /api/reportes/ciclos
     */
    public function getCiclos(Request $request)
    {
        try {
            $domainId = $request->query('domain_id');

            if (!$domainId) {
                return response()->json([
                    'success' => false,
                    'message' => 'domain_id es requerido'
                ], 400);
            }

            // ✅ Usar 'orden' en lugar de 'numero'
            $ciclos = DB::table('ciclos')
                ->select('id', 'nombre', 'orden as numero') // ✅ Alias 'orden' como 'numero'
                ->where('domain_id', $domainId)
                ->whereNull('deleted_at')
                ->orderBy('orden') // ✅ Ordenar por 'orden'
                ->get();

            Log::info('Ciclos encontrados:', [
                'total' => $ciclos->count(),
                'domain_id' => $domainId
            ]);

            return response()->json([
                'success' => true,
                'data' => $ciclos
            ]);
        } catch (\Exception $e) {
            Log::error('Error obteniendo ciclos:', [
                'domain_id' => $domainId,
                'error' => $e->getMessage(),
                'line' => $e->getLine(),
                'file' => $e->getFile()
            ]);

            return response()->json([
                'success' => false,
                'message' => 'Error al obtener ciclos',
                'error' => config('app.debug') ? $e->getMessage() : null
            ], 500);
        }
    }
}
