// script.js - COMPLETO CON TODOS LOS MÓDULOS
function origin() {
  const { ADMIN_BASE_URL } = window.API_CONFIG || {};
// frontend/script.js
// Navigation for Student Portal
document.addEventListener("DOMContentLoaded", () => {
  // Mobile menu toggle
  const mobileMenuToggle = document.getElementById("mobileMenuToggleStudent")
  const sidebar = document.getElementById("sidebarStudent")

  // ==========================
  // Helpers de llamadas al API
  // ==========================

  async function apiRequest(path, options = {}) {
    const base = ADMIN_BASE_URL || "http://localhost:3000/api/admin";
    const url = `${base}${path}`;
    const headers = window.buildAuthHeaders
      ? window.buildAuthHeaders(options.headers || {})
      : {
          "Content-Type": "application/json",
          ...(options.headers || {}),
        };

    const config = {
      method: options.method || "GET",
      headers,
    };

    if (options.body !== undefined) {
      config.body = JSON.stringify(options.body);
    }

    try {
      console.log("🔍 Haciendo petición a:", url);
      const resp = await fetch(url, config);

      if (resp.status === 204) {
        return null;
      }

      const data = await resp.json().catch(() => ({}));

      if (!resp.ok) {
        const msg = data?.message || data?.error || `Error ${resp.status}`;
        throw new Error(msg);
      }

      return data;
    } catch (err) {
      console.error("❌ Error en apiRequest:", err);
      alert(
        err.message || "Error inesperado en la comunicación con el servidor"
      );
      throw err;
    }
  }

  const apiGet = (path) => apiRequest(path, { method: "GET" });
  const apiPost = (path, body) => apiRequest(path, { method: "POST", body });
  const apiPut = (path, body) => apiRequest(path, { method: "PUT", body });
  const apiDelete = (path) => apiRequest(path, { method: "DELETE" });

  // ===================================
  // Navegación y sidebar del panel admin
  // ===================================

  function initNavigation() {
    const mobileMenuToggle = document.getElementById("mobileMenuToggle");
    const sidebar = document.getElementById("sidebar");
    const navItems = document.querySelectorAll(".nav-item[data-view]");
    const views = document.querySelectorAll(".view");

    const viewIdMap = {
      renovacion: "renovaciones-view",
      renovaciones: "renovaciones-view",
    };

    if (mobileMenuToggle && sidebar) {
      mobileMenuToggle.addEventListener("click", () => {
        sidebar.classList.toggle("open");
      });

      document.addEventListener("click", (e) => {
        if (window.innerWidth <= 1024) {
          if (
            !sidebar.contains(e.target) &&
            !mobileMenuToggle.contains(e.target)
          ) {
            sidebar.classList.remove("open");
          }
        }
      });
    }

    if (navItems.length && views.length) {
      navItems.forEach((item) => {
        item.addEventListener("click", function (e) {
          e.preventDefault();

          const viewName = this.getAttribute("data-view");
          if (!viewName) {
            console.warn("nav-item sin data-view, se ignora");
            return;
          }

          const viewId = viewIdMap[viewName] || `${viewName}-view`;

          navItems.forEach((n) => n.classList.remove("active"));
          this.classList.add("active");

          views.forEach((v) => v.classList.remove("active"));

          const selectedView = document.getElementById(viewId);
          if (selectedView) {
            selectedView.classList.add("active");

            // Cargar datos específicos de la vista cuando se activa
            cargarDatosVista(viewName);
          } else {
            console.warn("No se encontró la vista con id:", viewId);
          }

          if (window.innerWidth <= 1024 && sidebar) {
            sidebar.classList.remove("open");
          }
        });
      });
    }

    // Animación de tarjetas al hacer scroll
    const cards = document.querySelectorAll(
      ".card, .stat-card, .quick-action-card, .notification-item"
    );
    if (cards.length) {
      const observerOptions = {
        threshold: 0.1,
        rootMargin: "0px 0px -50px 0px",
      };

      const observer = new IntersectionObserver((entries) => {
        entries.forEach((entry) => {
          if (entry.isIntersecting) {
            entry.target.style.opacity = "1";
            entry.target.style.transform = "translateY(0)";
          }
        });
      }, observerOptions);

      cards.forEach((card) => {
        card.style.opacity = "0";
        card.style.transform = "translateY(20px)";
        card.style.transition = "opacity 0.5s ease, transform 0.5s ease";
        observer.observe(card);
      });
    }
  }

  // ======================
  // Cargar datos por vista
  // ======================

  function cargarDatosVista(viewName) {
    switch (viewName) {
      case "convocatoria":
        cargarConvocatorias();
        break;
      case "solicitudes":
        cargarSolicitudes();
        break;
      case "socioeconomico":
        cargarCasosSocioeconomicos();
        break;
      case "academico":
        cargarEvaluacionAcademica();
        break;
      case "comunicacion":
        cargarApelaciones();
        cargarComunicaciones();
        break;
      case "reportes":
        // Los reportes se cargan al hacer click
        break;
      case "administrativo":
        cargarRevisionAdministrativa();
        break;
      case "comite":
        cargarDatosComite();
        break;
      case "formalizacion":
        cargarContratosFormalizacion();
        break;
      case "seguimiento":
        cargarSeguimiento();
        break;
      case "renovaciones":
        cargarRenovaciones();
        break;
      case "archivo":
        cargarArchivo();
        break;
    }
  }

  // ======================
  // Módulo: CONVOCATORIAS
  // ======================

  async function cargarConvocatorias() {
    const grid = document.getElementById("convocatoriaGrid");
    const cronogramaHeader = document.getElementById(
      "cronogramaConvocatoriaHeader"
    );
    if (!grid) return;

    grid.innerHTML = `<p class="text-muted">Cargando convocatorias...</p>`;

    try {
      const convs = await apiGet("/convocatorias");

      if (!convs || !convs.length) {
        grid.innerHTML = `<p class="text-muted">No hay convocatorias registradas.</p>`;
        if (cronogramaHeader) {
          cronogramaHeader.textContent =
            "Cronograma (no hay convocatorias activas)";
        }
        return;
      }

      grid.innerHTML = "";

      const abierta = convs.find((c) => c.estado === "ABIERTO");

      if (cronogramaHeader) {
        if (abierta) {
          cronogramaHeader.textContent = `Cronograma - ${abierta.nombre} (${abierta.fecha_inicio} a ${abierta.fecha_cierre})`;
        } else {
          cronogramaHeader.textContent =
            "Cronograma - No hay convocatoria abierta";
        }
      }

      convs.forEach((c) => {
        const card = document.createElement("div");
        card.className = "convocatoria-card";

        const estadoClase =
          c.estado === "ABIERTO"
            ? "badge badge-success"
            : c.estado === "CERRADO"
            ? "badge badge-danger"
            : "badge badge-warning";

        card.innerHTML = `
          <div class="convocatoria-card-header">
            <h4>${c.nombre || "Convocatoria #" + c.id_convocatoria}</h4>
            <span class="${estadoClase}">${c.estado || "SIN_ESTADO"}</span>
          </div>
          <div class="convocatoria-card-body">
            <p><strong>Año:</strong> ${c.anio || "-"}</p>
            <p><strong>Ciclo:</strong> ${c.ciclo || "-"}</p>
            <p><strong>Fecha inicio:</strong> ${c.fecha_inicio || "-"}</p>
            <p><strong>Fecha cierre:</strong> ${c.fecha_cierre || "-"}</p>
          </div>
          <div class="convocatoria-card-footer">
            <button class="btn btn-secondary btn-sm btn-abrir-conv" data-id="${
              c.id_convocatoria
            }">
              Abrir
            </button>
            <button class="btn btn-secondary btn-sm btn-cerrar-conv" data-id="${
              c.id_convocatoria
            }">
              Cerrar
            </button>
          </div>
        `;

        grid.appendChild(card);
      });

      grid.querySelectorAll(".btn-abrir-conv").forEach((btn) => {
        btn.addEventListener("click", async () => {
          const id = btn.getAttribute("data-id");
          await apiPut(`/convocatorias/${id}/abrir`, {});
          await cargarConvocatorias();
        });
      });

      grid.querySelectorAll(".btn-cerrar-conv").forEach((btn) => {
        btn.addEventListener("click", async () => {
          const id = btn.getAttribute("data-id");
          await apiPut(`/convocatorias/${id}/cerrar`, {});
          await cargarConvocatorias();
        });
      });
    } catch (error) {
      console.error("❌ Error cargando convocatorias:", error);
      grid.innerHTML = `<p class="text-danger">Error al cargar convocatorias</p>`;
    }
  }

  function initNuevaConvocatoria() {
    const btnNueva = document.getElementById("btnNuevaConvocatoria");
    if (!btnNueva) return;

    btnNueva.addEventListener("click", async () => {
      try {
        const nombre =
          prompt("Nombre de la convocatoria:", "Convocatoria Becas 2025 - I") ||
          "";
        if (!nombre.trim()) {
          alert("Nombre requerido.");
          return;
        }

        const idPeriodoStr = prompt("ID de periodo (ej: 1):", "1") || "1";
        const id_periodo = parseInt(idPeriodoStr, 10);
        if (isNaN(id_periodo)) {
          alert("ID de periodo inválido.");
          return;
        }

        const fecha_inicio =
          prompt("Fecha de inicio (YYYY-MM-DD):", "2025-02-01") || "";
        const fecha_cierre =
          prompt("Fecha de cierre (YYYY-MM-DD):", "2025-03-15") || "";
        const estado =
          prompt(
            "Estado (ABIERTO / CERRADO / PROGRAMADO):",
            "ABIERTO"
          ) || "ABIERTO";

        const body = { nombre, id_periodo, fecha_inicio, fecha_cierre, estado };
        const result = await apiPost("/convocatorias", body);
        console.log("✅ Convocatoria creada:", result);
        alert("Convocatoria creada correctamente.");
        await cargarConvocatorias();
      } catch (err) {
        console.error("❌ Error creando convocatoria:", err);
      }
    });
  }

  // ======================
  // Módulo: APELACIONES
  // ======================

  function crearCardApelacion(apelacion) {
    const div = document.createElement("div");
    div.className = "appeal-card";

    const estadoClase =
      apelacion.estado === "ACEPTADA"
        ? "badge badge-success"
        : apelacion.estado === "RECHAZADA"
        ? "badge badge-danger"
        : "badge badge-warning";

    div.innerHTML = `
      <div class="appeal-card-header">
        <h4>Apelación #${apelacion.id_apelacion}</h4>
        <span class="${estadoClase}">${apelacion.estado}</span>
      </div>
      <div class="appeal-card-body">
        <p><strong>Solicitud:</strong> ${
          apelacion.id_solicitud || "-"
        }</p>
        <p><strong>Fecha:</strong> ${apelacion.fecha || "-"}</p>
        <p><strong>Motivo:</strong> ${
          apelacion.motivo || "Sin motivo registrado"
        }</p>
        ${
          apelacion.resolucion
            ? `<p><strong>Resolución:</strong> ${apelacion.resolucion}</p>`
            : ""
        }
      </div>
      <div class="appeal-card-footer">
        ${
          apelacion.estado === "PENDIENTE"
            ? `
          <button class="btn btn-primary btn-sm btn-aceptar-apelacion" data-id="${apelacion.id_apelacion}">
            Aceptar
          </button>
          <button class="btn btn-secondary btn-sm btn-rechazar-apelacion" data-id="${apelacion.id_apelacion}">
            Rechazar
          </button>
        `
            : `<span class="text-muted">Apelación ya resuelta.</span>`
        }
      </div>
    `;

    if (apelacion.estado === "PENDIENTE") {
      const btnAceptar = div.querySelector(".btn-aceptar-apelacion");
      const btnRechazar = div.querySelector(".btn-rechazar-apelacion");

      if (btnAceptar) {
        btnAceptar.addEventListener("click", async () => {
          const id = btnAceptar.getAttribute("data-id");
          const resolucion =
            prompt(
              "Escribe la resolución para ACEPTAR esta apelación:"
            ) || "Apelación aceptada";
          await apiPut(`/apelaciones/${id}/resolver`, {
            estado: "ACEPTADA",
            resolucion,
          });
          await cargarApelaciones();
        });
      }

      if (btnRechazar) {
        btnRechazar.addEventListener("click", async () => {
          const id = btnRechazar.getAttribute("data-id");
          const resolucion =
            prompt(
              "Escribe la resolución para RECHAZAR esta apelación:"
            ) || "Apelación rechazada";
          await apiPut(`/apelaciones/${id}/resolver`, {
            estado: "RECHAZADA",
            resolucion,
          });
          await cargarApelaciones();
        });
      }
    }

    return div;
  }

  async function cargarApelaciones() {
    const container = document.getElementById("appealsList");
    if (!container) return;

  // Observe all cards
  document.querySelectorAll(".card, .stat-card, .quick-action-card, .notification-item").forEach((card) => {
    card.style.opacity = "0"
    card.style.transform = "translateY(20px)"
    card.style.transition = "opacity 0.5s ease, transform 0.5s ease"
    observer.observe(card)
  })


     document.addEventListener('DOMContentLoaded', function() {
        // Manejar click en items de navegación
        const navItems = document.querySelectorAll('.nav-item');
        const views = document.querySelectorAll('.view');

        navItems.forEach(item => {
            item.addEventListener('click', function(e) {
                // Si es un submenu, expandir/contraer
                if (this.classList.contains('nav-submenu')) {
                    e.preventDefault();
                    this.classList.toggle('open');
                    return;
                }

                // Si es un subitem del submenu
                if (this.classList.contains('nav-subitem')) {
                    e.preventDefault();
                    const viewName = this.getAttribute('data-view');
                    showView(viewName);
                    
                    // Actualizar activos
                    navItems.forEach(nav => nav.classList.remove('active'));
                    this.classList.add('active');
                    return;
                }

                // Items normales de navegación
                e.preventDefault();
                const viewName = this.getAttribute('data-view');
                
                if (!viewName) return;

                // Mostrar la vista correspondiente
                showView(viewName);

                // Actualizar item activo
                navItems.forEach(nav => {
                    nav.classList.remove('active');
                });
                this.classList.add('active');
            });
        });

        function showView(viewName) {
            // Ocultar todas las vistas
            views.forEach(view => view.classList.remove('active'));

            // Mostrar la vista solicitada
            const view = document.getElementById(viewName + '-view');
            if (view) {
                view.classList.add('active');
            }
        }

        // Cerrar sidebar en móvil al hacer click en un item
        const mobileMenuToggle = document.getElementById('mobileMenuToggle');
        const sidebar = document.getElementById('sidebar');

        if (mobileMenuToggle) {
            mobileMenuToggle.addEventListener('click', function() {
                sidebar.classList.toggle('open');
            });
        }

        function togglePerspectiva(headerElement) {
            const perspectiva = headerElement.closest('.perspectiva');
            perspectiva.classList.toggle('expanded');
            
            const toggle = headerElement.querySelector('.perspectiva-toggle');
            toggle.textContent = perspectiva.classList.contains('expanded') ? '▼' : '▶';
        }

        function toggleObjetivo(headerElement) {
            const objetivo = headerElement.closest('.objetivo');
            objetivo.classList.toggle('expanded');
            
            const toggle = headerElement.querySelector('.objetivo-toggle');
            toggle.textContent = objetivo.classList.contains('expanded') ? '▼' : '▶';
        }

        // Load data when filter is applied
        document.getElementById('btnAplicarFiltro')?.addEventListener('click', function() {
            const periodo = document.getElementById('filtroPeriodo').value;
            console.log('Cargando datos para el período:', periodo);
            // Here you would load data from the server
        });

        // --- CMI Perspectives View Logic ---

        const modalPerspectiva = document.getElementById('modalPerspectiva');
        const btnNuevaPerspectiva = document.getElementById('btnNuevaPerspectiva');
        const btnCerrarModal = document.getElementById('btnCerrarModal');
        const btnCancelarPerspectiva = document.getElementById('btnCancelarPerspectiva');
        const formPerspectiva = document.getElementById('formPerspectiva');
        const idPerspectivaInput = document.getElementById('id_perspectiva');
        const nombrePerspectivaInput = document.getElementById('nombrePerspectiva');
        const descripcionPerspectivaInput = document.getElementById('descripcionPerspectiva');
        const tablaPerspectivasBody = document.querySelector('#tablaPerspectivas tbody');

        // Function to open modal for adding a new perspective
        btnNuevaPerspectiva.addEventListener('click', () => {
            formPerspectiva.reset();
            idPerspectivaInput.value = '';
            modalPerspectiva.style.display = 'flex';
            document.querySelector('#modalPerspectiva h2').textContent = 'Nueva Perspectiva';
        });

        // Function to close modal
        const closeModal = () => {
            modalPerspectiva.style.display = 'none';
        };

        btnCerrarModal.addEventListener('click', closeModal);
        btnCancelarPerspectiva.addEventListener('click', closeModal);

        // Handle form submission (add/edit perspective)
        formPerspectiva.addEventListener('submit', (e) => {
            e.preventDefault();

            const id = idPerspectivaInput.value;
            const nombre = nombrePerspectivaInput.value;
            const descripcion = descripcionPerspectivaInput.value;

            if (id) {
                // Edit existing perspective
                const row = tablaPerspectivasBody.querySelector(`tr[data-perspectiva-id="${id}"]`);
                row.querySelector('td:nth-child(1) strong').textContent = nombre;
                row.querySelector('td:nth-child(2)').textContent = descripcion;
                row.querySelector('.btn-editar').dataset.id = id; // Ensure data-id is updated if needed
                row.querySelector('.btn-eliminar').dataset.id = id;
            } else {
                // Add new perspective
                const newId = Date.now(); // Simple way to generate a unique ID
                const newRow = `
                    <tr data-perspectiva-id="${newId}">
                        <td><strong>${nombre}</strong></td>
                        <td>${descripcion}</td>
                        <td>
                            <button class="btn btn-sm btn-secondary btn-editar" data-id="${newId}">Editar</button>
                            <button class="btn btn-sm btn-danger btn-eliminar" data-id="${newId}">Eliminar</button>
                        </td>
                    </tr>
                `;
                tablaPerspectivasBody.insertAdjacentHTML('beforeend', newRow);
            }

            closeModal();
        });

        // Event delegation for edit and delete buttons
        tablaPerspectivasBody.addEventListener('click', (e) => {
            const target = e.target;

            if (target.classList.contains('btn-editar')) {
                const id = target.dataset.id;
                const row = target.closest('tr');
                const nombre = row.querySelector('td:nth-child(1) strong').textContent;
                const descripcion = row.querySelector('td:nth-child(2)').textContent;

                idPerspectivaInput.value = id;
                nombrePerspectivaInput.value = nombre;
                descripcionPerspectivaInput.value = descripcion;
                modalPerspectiva.style.display = 'flex';
                document.querySelector('#modalPerspectiva h2').textContent = 'Editar Perspectiva';
            } else if (target.classList.contains('btn-eliminar')) {
                if (confirm('¿Estás seguro de que deseas eliminar esta perspectiva?')) {
                    const id = target.dataset.id;
                    target.closest('tr').remove();
                }
            }
        });

        // --- CMI Objectives View Logic ---
        const modalObjetivo = document.getElementById('modalObjetivo');
        const btnNuevoObjetivo = document.getElementById('btnNuevoObjetivo');
        const btnCerrarModalObjetivo = document.getElementById('btnCerrarModalObjetivo');
        const btnCancelarObjetivo = document.getElementById('btnCancelarObjetivo');
        const formObjetivo = document.getElementById('formObjetivo');
        const idObjetivoInput = document.getElementById('id_objetivo');
        const selectPerspectivaObjetivo = document.getElementById('selectPerspectivaObjetivo');
        const nombreObjetivoInput = document.getElementById('nombreObjetivo');
        const descripcionObjetivoInput = document.getElementById('descripcionObjetivo');
        const tablaObjetivosBody = document.querySelector('#tablaObjetivos tbody');

        // Function to open modal for adding a new objective
        btnNuevoObjetivo.addEventListener('click', () => {
            formObjetivo.reset();
            idObjetivoInput.value = '';
            modalObjetivo.style.display = 'flex';
            document.querySelector('#modalObjetivo h2').textContent = 'Nuevo Objetivo';
        });

        // Function to close objective modal
        const closeModalObjetivo = () => {
            modalObjetivo.style.display = 'none';
        };

        btnCerrarModalObjetivo.addEventListener('click', closeModalObjetivo);
        btnCancelarObjetivo.addEventListener('click', closeModalObjetivo);

        // Handle form submission (add/edit objective)
        formObjetivo.addEventListener('submit', (e) => {
            e.preventDefault();

            const id = idObjetivoInput.value;
            const perspectivaId = selectPerspectivaObjetivo.value;
            const nombre = nombreObjetivoInput.value;
            const descripcion = descripcionObjetivoInput.value;

            // Get perspective name from selected option
            const perspectivaName = selectPerspectivaObjetivo.options[selectPerspectivaObjetivo.selectedIndex].text;

            if (id) {
                // Edit existing objective
                const row = tablaObjetivosBody.querySelector(`tr[data-objetivo-id="${id}"]`);
                row.querySelector('td:nth-child(1) strong').textContent = nombre;
                row.querySelector('td:nth-child(2)').textContent = descripcion;
                row.querySelector('td:nth-child(3)').textContent = perspectivaName;
                row.querySelector('.btn-editar-objetivo').dataset.id = id;
                row.querySelector('.btn-eliminar-objetivo').dataset.id = id;
            } else {
                // Add new objective
                const newId = Date.now(); // Simple way to generate a unique ID
                const newRow = `
                    <tr data-objetivo-id="${newId}">
                        <td><strong>${nombre}</strong></td>
                        <td>${descripcion}</td>
                        <td>${perspectivaName}</td>
                        <td>
                            <button class="btn btn-sm btn-secondary btn-editar-objetivo" data-id="${newId}">Editar</button>
                            <button class="btn btn-sm btn-danger btn-eliminar-objetivo" data-id="${newId}">Eliminar</button>
                        </td>
                    </tr>
                `;
                tablaObjetivosBody.insertAdjacentHTML('beforeend', newRow);
            }

            closeModalObjetivo();
        });

        // Event delegation for edit and delete objective buttons
        tablaObjetivosBody.addEventListener('click', (e) => {
            const target = e.target;

            if (target.classList.contains('btn-editar-objetivo')) {
                const id = target.dataset.id;
                const row = target.closest('tr');
                const nombre = row.querySelector('td:nth-child(1) strong').textContent;
                const descripcion = row.querySelector('td:nth-child(2)').textContent;
                const perspectiva = row.querySelector('td:nth-child(3)').textContent;

                idObjetivoInput.value = id;
                nombreObjetivoInput.value = nombre;
                descripcionObjetivoInput.value = descripcion;

                // Set the selected option for perspective
                const option = Array.from(selectPerspectivaObjetivo.options).find(opt => opt.text === perspectiva);
                if (option) {
                    selectPerspectivaObjetivo.value = option.value;
                }

                modalObjetivo.style.display = 'flex';
                document.querySelector('#modalObjetivo h2').textContent = 'Editar Objetivo';
            } else if (target.classList.contains('btn-eliminar-objetivo')) {
                if (confirm('¿Estás seguro de que deseas eliminar este objetivo?')) {
                    const id = target.dataset.id;
                    target.closest('tr').remove();
                }
            }
        });

        // --- CMI Indicators View Logic ---
        const modalIndicador = document.getElementById('modalIndicador');
        const btnNuevoIndicador = document.getElementById('btnNuevoIndicador');
        const btnCerrarModalIndicador = document.getElementById('btnCerrarModalIndicador');
        const btnCancelarIndicador = document.getElementById('btnCancelarIndicador');
        const formIndicador = document.getElementById('formIndicador');
        const idIndicadorInput = document.getElementById('id_indicador');
        const selectObjetivoIndicador = document.getElementById('selectObjetivoIndicador');
        const nombreIndicadorInput = document.getElementById('nombreIndicador');
        const formulaSpNombreInput = document.getElementById('formulaSpNombre');
        const unidadMedidaInput = document.getElementById('unidadMedida');
        const activoIndicadorInput = document.getElementById('activoIndicador');
        const tablaIndicadoresBody = document.querySelector('#tablaIndicadores tbody');

        // Function to open modal for adding a new indicator
        btnNuevoIndicador.addEventListener('click', () => {
            formIndicador.reset();
            idIndicadorInput.value = '';
            activoIndicadorInput.checked = true; // Set default to checked
            modalIndicador.style.display = 'flex';
            document.querySelector('#modalIndicador h2').textContent = 'Nuevo Indicador';
        });

        // Function to close indicator modal
        const closeModalIndicador = () => {
            modalIndicador.style.display = 'none';
        };

        btnCerrarModalIndicador.addEventListener('click', closeModalIndicador);
        btnCancelarIndicador.addEventListener('click', closeModalIndicador);

        // Handle form submission (add/edit indicator)
        formIndicador.addEventListener('submit', (e) => {
            e.preventDefault();

            const id = idIndicadorInput.value;
            const objetivoId = selectObjetivoIndicador.value;
            const nombre = nombreIndicadorInput.value;
            const formulaSp = formulaSpNombreInput.value;
            const unidad = unidadMedidaInput.value;
            const activo = activoIndicadorInput.checked ? 'Sí' : 'No';

            // Get objective name from selected option
            const objetivoName = selectObjetivoIndicador.options[selectObjetivoIndicador.selectedIndex].text;

            if (id) {
                // Edit existing indicator
                const row = tablaIndicadoresBody.querySelector(`tr[data-indicador-id="${id}"]`);
                row.querySelector('td:nth-child(1) strong').textContent = nombre;
                row.querySelector('td:nth-child(2)').textContent = objetivoName;
                row.querySelector('td:nth-child(3)').textContent = formulaSp;
                row.querySelector('td:nth-child(4)').textContent = unidad;
                row.querySelector('td:nth-child(5)').textContent = activo;
                row.querySelector('.btn-editar-indicador').dataset.id = id;
                row.querySelector('.btn-eliminar-indicador').dataset.id = id;
            } else {
                // Add new indicator
                const newId = Date.now();
                const newRow = `
                    <tr data-indicador-id="${newId}">
                        <td><strong>${nombre}</strong></td>
                        <td>${objetivoName}</td>
                        <td>${formulaSp}</td>
                        <td>${unidad}</td>
                        <td>${activo}</td>
                        <td>
                            <button class="btn btn-sm btn-secondary btn-editar-indicador" data-id="${newId}">Editar</button>
                            <button class="btn btn-sm btn-danger btn-eliminar-indicador" data-id="${newId}">Eliminar</button>
                        </td>
                    </tr>
                `;
                tablaIndicadoresBody.insertAdjacentHTML('beforeend', newRow);
            }

            closeModalIndicador();
        });

        // Event delegation for edit and delete indicator buttons
        tablaIndicadoresBody.addEventListener('click', (e) => {
            const target = e.target;

            if (target.classList.contains('btn-editar-indicador')) {
                const id = target.dataset.id;
                const row = target.closest('tr');
                const nombre = row.querySelector('td:nth-child(1) strong').textContent;
                const objetivo = row.querySelector('td:nth-child(2)').textContent;
                const formulaSp = row.querySelector('td:nth-child(3)').textContent;
                const unidad = row.querySelector('td:nth-child(4)').textContent;
                const activo = row.querySelector('td:nth-child(5)').textContent;

                idIndicadorInput.value = id;
                nombreIndicadorInput.value = nombre;
                formulaSpNombreInput.value = formulaSp;
                unidadMedidaInput.value = unidad;
                activoIndicadorInput.checked = activo === 'Sí';

                // Set the selected option for objetivo
                const option = Array.from(selectObjetivoIndicador.options).find(opt => opt.text === objetivo);
                if (option) {
                    selectObjetivoIndicador.value = option.value;
                }

                modalIndicador.style.display = 'flex';
                document.querySelector('#modalIndicador h2').textContent = 'Editar Indicador';
            } else if (target.classList.contains('btn-eliminar-indicador')) {
                if (confirm('¿Estás seguro de que deseas eliminar este indicador?')) {
                    const id = target.dataset.id;
                    target.closest('tr').remove();
                }
            }
        });

            // --- CMI Metas View Logic ---
        const modalMeta = document.getElementById('modalMeta');
        const btnNuevaMeta = document.getElementById('btnNuevaMeta');
        const btnCerrarModalMeta = document.getElementById('btnCerrarModalMeta');
        const btnCancelarMeta = document.getElementById('btnCancelarMeta');
        const formMeta = document.getElementById('formMeta');
        const idMetaInput = document.getElementById('id_meta');
        const selectIndicadorMeta = document.getElementById('selectIndicadorMeta');
        const selectPeriodoMeta = document.getElementById('selectPeriodoMeta');
        const valorMetaInput = document.getElementById('valorMeta');
        const fechaVigenciaMetaInput = document.getElementById('fechaVigenciaMeta');
        const tablaMetasBody = document.querySelector('#tablaMetas tbody');

        if (!btnNuevaMeta || !modalMeta || !formMeta || !tablaMetasBody) {
            console.log('[v0] Error: Elementos de metas no encontrados en el DOM');
            return;
        }

        console.log('[v0] Elementos de metas encontrados correctamente');

        // Function to open modal for adding a new meta
        btnNuevaMeta.addEventListener('click', () => {
            console.log('[v0] Botón Nueva Meta clickeado');
            formMeta.reset();
            idMetaInput.value = '';
            modalMeta.style.display = 'flex';
            document.querySelector('#modalMeta h2').textContent = 'Nueva Meta';
        });

        // Function to close modal
        const closeModalMeta = () => {
            console.log('[v0] Cerrando modal de Metas');
            modalMeta.style.display = 'none';
        };

        if (btnCerrarModalMeta) {
            btnCerrarModalMeta.addEventListener('click', closeModalMeta);
        }
        
        if (btnCancelarMeta) {
            btnCancelarMeta.addEventListener('click', closeModalMeta);
        }

        formMeta.addEventListener('submit', (e) => {
            e.preventDefault();
            console.log('[v0] Formulario de metas enviado');

            const id = idMetaInput.value;
            const indicadorId = selectIndicadorMeta.value;
            const periodoId = selectPeriodoMeta.value;
            const valor = valorMetaInput.value;
            const vigencia = fechaVigenciaMetaInput.value;

            // Validar que los campos requeridos estén llenos
            if (!indicadorId || !periodoId || !valor) {
                alert('Por favor completa todos los campos requeridos');
                return;
            }

            // Get indicator name from selected option
            const indicadorName = selectIndicadorMeta.options[selectIndicadorMeta.selectedIndex].text;
            // Get period name from selected option
            const periodoName = selectPeriodoMeta.options[selectPeriodoMeta.selectedIndex].text;

            if (id) {
                // Edit existing meta
                console.log('[v0] Editando meta con ID:', id);
                const row = tablaMetasBody.querySelector(`tr[data-meta-id="${id}"]`);
                if (row) {
                    row.querySelector('td:nth-child(1) strong').textContent = indicadorName;
                    row.querySelector('td:nth-child(2)').textContent = periodoName;
                    row.querySelector('td:nth-child(3)').textContent = valor;
                    row.querySelector('td:nth-child(4)').textContent = vigencia;
                    row.querySelector('.btn-editar-meta').dataset.id = id;
                    row.querySelector('.btn-eliminar-meta').dataset.id = id;
                }
            } else {
                // Add new meta
                console.log('[v0] Agregando nueva meta');
                const newId = Date.now(); // Simple way to generate a unique ID
                const newRow = `
                    <tr data-meta-id="${newId}">
                        <td><strong>${indicadorName}</strong></td>
                        <td>${periodoName}</td>
                        <td>${valor}</td>
                        <td>${vigencia || '-'}</td>
                        <td>
                            <button class="btn btn-sm btn-secondary btn-editar-meta" data-id="${newId}">Editar</button>
                            <button class="btn btn-sm btn-danger btn-eliminar-meta" data-id="${newId}">Eliminar</button>
                        </td>
                    </tr>
                `;
                tablaMetasBody.insertAdjacentHTML('beforeend', newRow);
            }

            closeModalMeta();
        });

        tablaMetasBody.addEventListener('click', (e) => {
            const target = e.target;

            if (target.classList.contains('btn-editar-meta')) {
                console.log('[v0] Botón editar clickeado');
                const id = target.dataset.id;
                const row = target.closest('tr');
                
                if (!row) return;
                
                const indicador = row.querySelector('td:nth-child(1) strong').textContent;
                const periodo = row.querySelector('td:nth-child(2)').textContent;
                const valor = row.querySelector('td:nth-child(3)').textContent;
                const vigencia = row.querySelector('td:nth-child(4)').textContent;

                idMetaInput.value = id;
                valorMetaInput.value = valor;
                fechaVigenciaMetaInput.value = vigencia !== '-' ? vigencia : '';

                // Set the selected option for indicador
                const optionIndicador = Array.from(selectIndicadorMeta.options).find(opt => opt.text === indicador);
                if (optionIndicador) {
                    selectIndicadorMeta.value = optionIndicador.value;
                }

                // Set the selected option for periodo
                const optionPeriodo = Array.from(selectPeriodoMeta.options).find(opt => opt.text === periodo);
                if (optionPeriodo) {
                    selectPeriodoMeta.value = optionPeriodo.value;
                }

                modalMeta.style.display = 'flex';
                document.querySelector('#modalMeta h2').textContent = 'Editar Meta';
            } else if (target.classList.contains('btn-eliminar-meta')) {
                console.log('[v0] Botón eliminar clickeado');
                if (confirm('¿Estás seguro de que deseas eliminar esta meta?')) {
                    const id = target.dataset.id;
                    target.closest('tr').remove();
                    console.log('[v0] Meta eliminada con ID:', id);
                }
            }
        });

            // --- CMI Acciones (Strategic Actions) View Logic ---
        const modalAccion = document.getElementById('modalAccion');
        const btnNuevaAccion = document.getElementById('btnNuevaAccion');
        const btnCerrarModalAccion = document.getElementById('btnCerrarModalAccion');
        const btnCancelarAccion = document.getElementById('btnCancelarAccion');
        const formAccion = document.getElementById('formAccion');
        const idAccionInput = document.getElementById('id_accion');
        const selectObjetivoAccion = document.getElementById('selectObjetivoAccion');
        const descripcionAccionInput = document.getElementById('descripcionAccion');
        const responsableRolInput = document.getElementById('responsableRol');
        const fechaInicioAccionInput = document.getElementById('fechaInicioAccion');
        const fechaFinAccionInput = document.getElementById('fechaFinAccion');
        const selectEstadoAccion = document.getElementById('selectEstadoAccion');
        const tablaAccionesBody = document.querySelector('#tablaAcciones tbody');

        if (btnNuevaAccion && modalAccion && formAccion && tablaAccionesBody) {
            console.log('[v0] Elementos de acciones encontrados correctamente');

            // Function to open modal for adding a new action
            btnNuevaAccion.addEventListener('click', () => {
                console.log('[v0] Botón Nueva Acción clickeado');
                formAccion.reset();
                idAccionInput.value = '';
                modalAccion.style.display = 'flex';
                document.querySelector('#modalAccion h2').textContent = 'Nueva Acción Estratégica';
            });

            // Function to close modal
            const closeModalAccion = () => {
                console.log('[v0] Cerrando modal de Acciones');
                modalAccion.style.display = 'none';
            };

            if (btnCerrarModalAccion) {
                btnCerrarModalAccion.addEventListener('click', closeModalAccion);
            }
            
            if (btnCancelarAccion) {
                btnCancelarAccion.addEventListener('click', closeModalAccion);
            }

            formAccion.addEventListener('submit', (e) => {
                e.preventDefault();
                console.log('[v0] Formulario de acciones enviado');

                const id = idAccionInput.value;
                const objetivo = selectObjetivoAccion.value;
                const descripcion = descripcionAccionInput.value;
                const responsable = responsableRolInput.value;
                const fechaInicio = fechaInicioAccionInput.value;
                const fechaFin = fechaFinAccionInput.value;
                const estado = selectEstadoAccion.value;

                // Validar que los campos requeridos estén llenos
                if (!objetivo || !descripcion || !estado) {
                    alert('Por favor completa los campos requeridos: Objetivo, Descripción y Estado');
                    return;
                }

                // Get objective name from selected option
                const objetivoName = selectObjetivoAccion.options[selectObjetivoAccion.selectedIndex].text;
                
                // Function to get badge class based on estado
                const getEstadoBadgeClass = (estado) => {
                    switch(estado) {
                        case 'Pendiente': return 'badge-info';
                        case 'En Progreso': return 'badge-warning';
                        case 'Completada': return 'badge-success';
                        default: return 'badge-secondary';
                    }
                };

                // Format dates for display
                const fechasDisplay = fechaInicio && fechaFin ? `${fechaInicio} - ${fechaFin}` : (fechaInicio || '-');

                if (id) {
                    // Edit existing action
                    console.log('[v0] Editando acción con ID:', id);
                    const row = tablaAccionesBody.querySelector(`tr[data-accion-id="${id}"]`);
                    if (row) {
                        row.querySelector('td:nth-child(1) strong').textContent = descripcion;
                        row.querySelector('td:nth-child(2)').textContent = objetivoName;
                        row.querySelector('td:nth-child(3)').textContent = responsable || '-';
                        row.querySelector('td:nth-child(4) .badge').textContent = estado;
                        row.querySelector('td:nth-child(4) .badge').className = `badge ${getEstadoBadgeClass(estado)}`;
                        row.querySelector('td:nth-child(5)').textContent = fechasDisplay;
                        row.querySelector('.btn-editar-accion').dataset.id = id;
                        row.querySelector('.btn-eliminar-accion').dataset.id = id;
                    }
                } else {
                    // Add new action
                    console.log('[v0] Agregando nueva acción');
                    const newId = Date.now(); // Simple way to generate a unique ID
                    const newRow = `
                        <tr data-accion-id="${newId}">
                            <td><strong>${descripcion}</strong></td>
                            <td>${objetivoName}</td>
                            <td>${responsable || '-'}</td>
                            <td><span class="badge ${getEstadoBadgeClass(estado)}">${estado}</span></td>
                            <td>${fechasDisplay}</td>
                            <td>
                                <button class="btn btn-sm btn-secondary btn-editar-accion" data-id="${newId}">Editar</button>
                                <button class="btn btn-sm btn-danger btn-eliminar-accion" data-id="${newId}">Eliminar</button>
                            </td>
                        </tr>
                    `;
                    tablaAccionesBody.insertAdjacentHTML('beforeend', newRow);
                }

                closeModalAccion();
            });

            tablaAccionesBody.addEventListener('click', (e) => {
                const target = e.target;

                if (target.classList.contains('btn-editar-accion')) {
                    console.log('[v0] Botón editar acción clickeado');
                    const id = target.dataset.id;
                    const row = target.closest('tr');
                    
                    if (!row) return;
                    
                    const descripcion = row.querySelector('td:nth-child(1) strong').textContent;
                    const objetivo = row.querySelector('td:nth-child(2)').textContent;
                    const responsable = row.querySelector('td:nth-child(3)').textContent;
                    const estado = row.querySelector('td:nth-child(4) .badge').textContent;
                    const fechasText = row.querySelector('td:nth-child(5)').textContent;

                    // Parse dates
                    const fechasArray = fechasText.split(' - ');
                    const fechaInicio = fechasArray[0] ? fechasArray[0].trim() : '';
                    const fechaFin = fechasArray[1] ? fechasArray[1].trim() : '';

                    idAccionInput.value = id;
                    descripcionAccionInput.value = descripcion;
                    responsableRolInput.value = responsable !== '-' ? responsable : '';
                    fechaInicioAccionInput.value = fechaInicio;
                    fechaFinAccionInput.value = fechaFin;
                    selectEstadoAccion.value = estado;

                    // Set the selected option for objetivo
                    const optionObjetivo = Array.from(selectObjetivoAccion.options).find(opt => opt.text === objetivo);
                    if (optionObjetivo) {
                        selectObjetivoAccion.value = optionObjetivo.value;
                    }

                    modalAccion.style.display = 'flex';
                    document.querySelector('#modalAccion h2').textContent = 'Editar Acción Estratégica';
                } else if (target.classList.contains('btn-eliminar-accion')) {
                    console.log('[v0] Botón eliminar acción clickeado');
                    if (confirm('¿Estás seguro de que deseas eliminar esta acción?')) {
                        const id = target.dataset.id;
                        target.closest('tr').remove();
                        console.log('[v0] Acción eliminada con ID:', id);
                    }
                }
            });
        } else {console.log('El asunto es no dejar un else sin qué hacer...');}});

    // Dashboard CMI Variables
    const dashboardCMI = document.getElementById('dashboardCMI');
    const filterPeriodo = document.getElementById('filterPeriodo');
    const filterEstado = document.getElementById('filterEstado');
    const btnExportarDatos = document.getElementById('btnExportarDatos');
    const btnRefrescarDatos = document.getElementById('btnRefrescarDatos');

    if (dashboardCMI && filterPeriodo && filterEstado) {
        console.log('[v0] Elementos del Dashboard CMI encontrados');

        // Toggle perspectivas
        document.querySelectorAll('.perspectiva-header').forEach(header => {
            header.addEventListener('click', (e) => {
                const perspectiva = header.closest('.perspectiva');
                perspectiva.classList.toggle('expanded');
                console.log('[v0] Perspectiva toggled:', perspectiva.dataset.perspectiva);
            });
        });

        // Toggle objetivos
        document.querySelectorAll('.objetivo-header').forEach(header => {
            header.addEventListener('click', (e) => {
                if (e.target.closest('.objetivo-toggle')) {
                    const objetivo = header.closest('.objetivo');
                    objetivo.classList.toggle('expanded');
                    console.log('[v0] Objetivo toggled:', objetivo.dataset.objetivo);
                }
            });
        });

        // Expandir todas las perspectivas por defecto
        document.querySelectorAll('.perspectiva').forEach(p => {
            p.classList.add('expanded');
            p.querySelectorAll('.objetivo').forEach(o => {
                o.classList.add('expanded');
            });
        });

        // Filter by period
        filterPeriodo.addEventListener('change', (e) => {
            const periodo = e.target.value;
            console.log('[v0] Filtrando por período:', periodo);
            // Aquí iría la lógica para filtrar datos según el período
        });

        // Filter by state
        filterEstado.addEventListener('change', (e) => {
            const estado = e.target.value;
            console.log('[v0] Filtrando por estado:', estado);
            
            // Ejemplo de filtrado: resaltar filas según estado
            if (estado === 'crítico') {
                document.querySelectorAll('.indicadores-table tbody tr').forEach(row => {
                    const semaforo = row.querySelector('.semaforo');
                    if (semaforo && semaforo.classList.contains('rojo')) {
                        row.style.backgroundColor = 'rgba(239, 68, 68, 0.1)';
                    } else {
                        row.style.backgroundColor = 'transparent';
                    }
                });
            } else if (estado === 'alerta') {
                document.querySelectorAll('.indicadores-table tbody tr').forEach(row => {
                    const semaforo = row.querySelector('.semaforo');
                    if (semaforo && semaforo.classList.contains('amarillo')) {
                        row.style.backgroundColor = 'rgba(245, 158, 11, 0.1)';
                    } else {
                        row.style.backgroundColor = 'transparent';
                    }
                });
            } else if (estado === 'cumplido') {
                document.querySelectorAll('.indicadores-table tbody tr').forEach(row => {
                    const semaforo = row.querySelector('.semaforo');
                    if (semaforo && semaforo.classList.contains('verde')) {
                        row.style.backgroundColor = 'rgba(16, 185, 129, 0.1)';
                    } else {
                        row.style.backgroundColor = 'transparent';
                    }
                });
            } else {
                document.querySelectorAll('.indicadores-table tbody tr').forEach(row => {
                    row.style.backgroundColor = 'transparent';
                });
            }
        });

        // Export data
        if (btnExportarDatos) {
            btnExportarDatos.addEventListener('click', () => {
                console.log('[v0] Exportando reporte CMI');
                alert('Funcionalidad de exportación en desarrollo\nSe generará un archivo CSV/PDF con los datos del CMI');
            });
        }

        // Refresh data
        if (btnRefrescarDatos) {
            btnRefrescarDatos.addEventListener('click', () => {
                console.log('[v0] Actualizando datos del Dashboard CMI');
                alert('Datos actualizados correctamente');
                // Aquí iría la lógica para recargar datos de la BD
            });
        }

        console.log('[v0] Dashboard CMI inicializado correctamente');
    } else {
        console.log('[v0] Error: Elementos del Dashboard CMI no encontrados');
    }
    container.innerHTML = `<p class="text-muted">Cargando apelaciones...</p>`;

    try {
      const data = await apiGet("/apelaciones");

      if (!data || !data.length) {
        container.innerHTML =
          `<p class="text-muted">No hay apelaciones registradas.</p>`;
        return;
      }

      container.innerHTML = "";
      data.forEach((apelacion) => {
        const card = crearCardApelacion(apelacion);
        container.appendChild(card);
      });
    } catch (error) {
      console.error("❌ Error cargando apelaciones:", error);
      container.innerHTML =
        `<p class="text-danger">Error al cargar apelaciones</p>`;
    }
  }

  // =======================
  // Módulo: SOLICITUDES
  // =======================

  async function cargarSolicitudes() {
    const grid = document.getElementById("solicitudesGrid");
    if (!grid) return;

    grid.innerHTML = `<p class="text-muted">Cargando solicitudes...</p>`;

    try {
      const estado = document.getElementById("filtroEstado")?.value || "";
      const tipo = document.getElementById("filtroTipo")?.value || "";
      const fecha = document.getElementById("filtroFecha")?.value || "";

      const params = new URLSearchParams();
      if (estado) params.append("estado", estado);
      if (tipo) params.append("tipo", tipo);
      if (fecha) params.append("fecha", fecha);

      const data = await apiGet(`/solicitudes?${params.toString()}`);

      if (!data || !data.length) {
        grid.innerHTML =
          `<p class="text-muted">No hay solicitudes registradas.</p>`;
        return;
      }

      grid.innerHTML = "";

      data.forEach((sol) => {
        const card = document.createElement("div");
        card.className = "application-card";

        const estadoClase =
          sol.estado === "APROBADA"
            ? "badge-success"
            : sol.estado === "DENEGADA"
            ? "badge-danger"
            : sol.estado === "EN_REVISION"
            ? "badge-warning"
            : "badge-secondary";

        card.innerHTML = `
          <div class="application-card-header">
            <h4>Solicitud #${sol.id_solicitud}</h4>
            <span class="badge ${estadoClase}">${
          sol.estado || "SIN_ESTADO"
        }</span>
          </div>
          <div class="application-card-body">
            <p><strong>Estudiante:</strong> ${
              sol.nombre_estudiante || "-"
            }</p>
            <p><strong>Convocatoria:</strong> ${sol.nombre_conv || "-"}</p>
            <p><strong>Fecha:</strong> ${sol.creado || "-"}</p>
            <p><strong>Total:</strong> ${sol.total || "-"}</p>
          </div>
          <div class="application-card-footer">
            <button class="btn btn-primary btn-sm btn-ver-solicitud" data-id="${
              sol.id_solicitud
            }">
              Ver Detalles
            </button>
            <button class="btn btn-secondary btn-sm btn-cambiar-estado" data-id="${
              sol.id_solicitud
            }">
              Cambiar Estado
            </button>
          </div>
        `;

        grid.appendChild(card);
      });

      grid.querySelectorAll(".btn-ver-solicitud").forEach((btn) => {
        btn.addEventListener("click", (e) => {
          const id = e.target.getAttribute("data-id");
          verDetallesSolicitud(id);
        });
      });

      grid.querySelectorAll(".btn-cambiar-estado").forEach((btn) => {
        btn.addEventListener("click", (e) => {
          const id = e.target.getAttribute("data-id");
          cambiarEstadoSolicitud(id);
        });
      });
    } catch (error) {
      console.error("❌ Error cargando solicitudes:", error);
      grid.innerHTML =
        `<p class="text-danger">Error al cargar solicitudes</p>`;
    }
  }

  function initFiltrosSolicitudes() {
    const btnAplicar = document.getElementById("btnAplicarFiltros");
    const btnLimpiar = document.getElementById("btnLimpiarFiltros");

    if (btnAplicar) {
      btnAplicar.addEventListener("click", () => cargarSolicitudes());
    }

    if (btnLimpiar) {
      btnLimpiar.addEventListener("click", () => {
        document.getElementById("filtroEstado").value = "";
        document.getElementById("filtroTipo").value = "";
        document.getElementById("filtroFecha").value = "";
        cargarSolicitudes();
      });
    }
  }

  async function verDetallesSolicitud(idSolicitud) {
    try {
      const solicitud = await apiGet(`/solicitudes/${idSolicitud}`);
      alert(
        `Detalles de Solicitud #${idSolicitud}:\n\n` +
          `Estudiante: ${solicitud.nombre_estudiante}\n` +
          `Estado: ${solicitud.estado}\n` +
          `Fecha: ${solicitud.creado}\n` +
          `Convocatoria: ${solicitud.nombre_conv}`
      );
    } catch (error) {
      console.error("Error cargando detalles:", error);
    }
  }

  async function cambiarEstadoSolicitud(idSolicitud) {
    const nuevoEstado = prompt(
      "Nuevo estado (CREADA/EN_REVISION_TS/EN_COMITE/APROBADA/DENEGADA/CERRADA):"
    );
    if (!nuevoEstado) return;

    try {
      await apiPut(`/solicitudes/${idSolicitud}/estado`, {
        estado: nuevoEstado,
      });
      alert("Estado actualizado correctamente");
      cargarSolicitudes();
    } catch (error) {
      console.error("Error cambiando estado:", error);
    }
  }

  // ======================
  // Módulo: ANÁLISIS SOCIOECONÓMICO
  // ======================

  async function cargarCasosSocioeconomicos() {
    const tbody = document.getElementById("socioeconomicoTableBody");
    if (!tbody) return;

    tbody.innerHTML =
      `<tr><td colspan="5" class="text-muted">Cargando...</td></tr>`;

    try {
      const data = await apiGet("/socioeconomico/casos");

      if (!data.length) {
        tbody.innerHTML =
          `<tr><td colspan="5" class="text-muted">No hay casos pendientes.</td></tr>`;
        return;
      }

      tbody.innerHTML = "";
      data.forEach((caso) => {
        const tr = document.createElement("tr");

        const estadoClase =
          caso.estado === "COMPLETADO"
            ? "badge-success"
            : caso.estado === "EN_PROCESO"
            ? "badge-warning"
            : "badge-secondary";

        tr.innerHTML = `
          <td>${caso.estudiante || caso.nombre_estudiante || "-"}</td>
          <td>${caso.fecha_solicitud || caso.creado || "-"}</td>
          <td>${caso.trabajador_social || "-"}</td>
          <td><span class="badge ${estadoClase}">${caso.estado}</span></td>
          <td>
            <button class="btn btn-primary btn-sm btn-evaluar-socio" data-id="${
              caso.id_solicitud
            }">
              Evaluar
            </button>
            <button class="btn btn-secondary btn-sm btn-programar-visita" data-id="${
              caso.id_solicitud
            }">
              Visita
            </button>
          </td>
        `;
        tbody.appendChild(tr);
      });

      tbody.querySelectorAll(".btn-evaluar-socio").forEach((btn) => {
        btn.addEventListener("click", (e) => {
          const id = e.target.getAttribute("data-id");
          evaluarCasoSocioeconomico(id);
        });
      });

      tbody.querySelectorAll(".btn-programar-visita").forEach((btn) => {
        btn.addEventListener("click", (e) => {
          const id = e.target.getAttribute("data-id");
          programarVisitaDomiciliaria(id);
        });
      });
    } catch (err) {
      console.error("❌ Error cargando casos socioeconómicos", err);
      tbody.innerHTML =
        `<tr><td colspan="5" class="text-danger">Error cargando datos</td></tr>`;
    }
  }

  function initSocioeconomicoButtons() {
    const btnNuevo = document.querySelector(
      "#socioeconomico-view .btn.btn-primary"
    );
    if (btnNuevo) {
      btnNuevo.addEventListener("click", () => {
        alert(
          "Aquí se debería abrir la creación de un nuevo informe socioeconómico."
        );
      });
    }

    const findButtonByText = (text) =>
      Array.from(document.querySelectorAll("#socioeconomico-view button")).find(
        (btn) => btn.textContent.trim().includes(text)
      );

    const btnEncuesta = findButtonByText("Aplicar");
    if (btnEncuesta) {
      btnEncuesta.addEventListener("click", () => {
        aplicarEncuestaSocioeconomica();
      });
    }

    const btnVisita = findButtonByText("Programar");
    if (btnVisita) {
      btnVisita.addEventListener("click", () => {
        programarVisitaGeneral();
      });
    }

    const btnCalcular = findButtonByText("Calcular");
    if (btnCalcular) {
      btnCalcular.addEventListener("click", () => {
        calcularNivelSocioeconomico();
      });
    }

    const btnGenerar = findButtonByText("Generar");
    if (btnGenerar) {
      btnGenerar.addEventListener("click", () => {
        generarInformeSocioeconomico();
      });
    }
  }

  async function evaluarCasoSocioeconomico(idSolicitud) {
    try {
      const metodo = prompt(
        "Método de evaluación socioeconómica:",
        "ENTREVISTA"
      );
      const observaciones = prompt("Observaciones:");

      await apiPost(`/solicitudes/${idSolicitud}/evaluar-socio`, {
        metodo_socio: metodo,
        observaciones: observaciones,
      });

      alert("Evaluación socioeconómica registrada");
      cargarCasosSocioeconomicos();
    } catch (error) {
      console.error("Error evaluando caso:", error);
    }
  }

  async function programarVisitaDomiciliaria(idSolicitud) {
    const fecha = prompt("Fecha para la visita (YYYY-MM-DD):");
    if (!fecha) return;

    try {
      await apiPost(`/solicitudes/${idSolicitud}/visita`, {
        fecha_programada: fecha,
        observaciones: "Visita programada desde el panel",
      });
      alert("Visita domiciliaria programada");
    } catch (error) {
      console.error("Error programando visita:", error);
    }
  }

  function aplicarEncuestaSocioeconomica() {
    alert("Abriendo encuesta socioeconómica...");
  }

  function programarVisitaGeneral() {
    alert("Programando visita domiciliaria general...");
  }

  function calcularNivelSocioeconomico() {
    alert("Calculando nivel socioeconómico automáticamente...");
  }

  function generarInformeSocioeconomico() {
    alert("Generando informe socioeconómico...");
  }

  // ===============================
  // Módulo: EVALUACIÓN ACADÉMICA
  // ===============================

  async function cargarEvaluacionAcademica() {
    const tbody = document.getElementById("academicoTableBody");
    if (!tbody) return;

    tbody.innerHTML =
      `<tr><td colspan="8" class="text-muted">Cargando estudiantes...</td></tr>`;

    try {
      const quarterSelect = document.getElementById("academicQuarterFilter");
      const cuatrimestre = quarterSelect ? quarterSelect.value : "all";

      const data = await apiGet(`/academico/estudiantes?cuatri=${cuatrimestre}`);

      if (!data.length) {
        tbody.innerHTML =
          `<tr><td colspan="8" class="text-muted">No hay estudiantes en evaluación.</td></tr>`;
        return;
      }

      tbody.innerHTML = "";

      data.forEach((est) => {
        const tr = document.createElement("tr");

        const estadoClase =
          est.estado === "APROBADO" ? "badge-success" : "badge-warning";
        const promedioClase =
          parseFloat(est.promedio) >= 8.0 ? "badge-success" : "badge-danger";

        tr.innerHTML = `
          <td>${est.nombre || "-"}</td>
          <td>${est.cuatrimestre || "-"}</td>
          <td><span class="badge ${promedioClase}">${
          est.promedio || "-"
        }</span></td>
          <td>${est.creditos || "-"}</td>
          <td>${est.materias_aprobadas || "-"}</td>
          <td>${est.sanciones || "Ninguna"}</td>
          <td><span class="badge ${estadoClase}">${est.estado}</span></td>
          <td>
            <button class="btn btn-primary btn-sm btn-ver-evaluacion" data-id="${
              est.id_estudiante
            }">
              Ver
            </button>
            <button class="btn btn-secondary btn-sm btn-evaluar-academico" data-id="${
              est.id_estudiante
            }">
              Evaluar
            </button>
          </td>
        `;
        tbody.appendChild(tr);
      });

      tbody.querySelectorAll(".btn-ver-evaluacion").forEach((btn) => {
        btn.addEventListener("click", (e) => {
          const id = e.target.getAttribute("data-id");
          verEvaluacionAcademica(id);
        });
      });

      tbody.querySelectorAll(".btn-evaluar-academico").forEach((btn) => {
        btn.addEventListener("click", (e) => {
          const id = e.target.getAttribute("data-id");
          evaluarEstudianteAcademico(id);
        });
      });
    } catch (err) {
      console.error("❌ Error cargando evaluación académica:", err);
      tbody.innerHTML =
        `<tr><td colspan='8' class='text-danger'>Error cargando datos</td></tr>`;
    }
  }

  function initEvaluacionAcademica() {
    const select = document.getElementById("academicQuarterFilter");
    if (select) {
      select.addEventListener("change", () => {
        cargarEvaluacionAcademica();
      });
    }

    const btnComparar = document.getElementById("compareQuartersBtn");
    if (btnComparar) {
      btnComparar.addEventListener("click", () => {
        document.getElementById("quarterComparisonModal").style.display =
          "block";
      });
    }
  }

  async function verEvaluacionAcademica(idEstudiante) {
    try {
      const evaluacion = await apiGet(`/academico/estudiantes/${idEstudiante}`);
      alert(
        `Evaluación Académica:\n\n` +
          `Promedio: ${evaluacion.promedio}\n` +
          `Créditos: ${evaluacion.creditos}\n` +
          `Materias Aprobadas: ${evaluacion.materias_aprobadas}\n` +
          `Estado: ${evaluacion.estado}`
      );
    } catch (error) {
      console.error("Error cargando evaluación:", error);
    }
  }

  async function evaluarEstudianteAcademico(idEstudiante) {
    const promedio = prompt("Promedio actual:");
    const reprobadas = prompt("Materias reprobadas:");
    const observaciones = prompt("Observaciones:");

    if (!promedio) return;

    try {
      await apiPost(`/academico/estudiantes/${idEstudiante}/evaluar`, {
        promedio: promedio,
        reprobadas: reprobadas,
        observaciones: observaciones,
      });
      alert("Evaluación académica registrada");
      cargarEvaluacionAcademica();
    } catch (error) {
      console.error("Error evaluando estudiante:", error);
    }
  }

  // ======================
  // Módulo: REVISIÓN ADMINISTRATIVA (FAKE)
  // ======================

  async function cargarRevisionAdministrativa() {
    await cargarEstadisticasAdministrativas();
    await cargarValidacionRequisitos();
  }

  async function cargarEstadisticasAdministrativas() {
    const stats = {
      expedientesCompletos: 42,
      expedientesCompletosPercent: 68,
      documentacionPendiente: 7,
      becasIncompatibles: 3,
      dentroPlazo: 55,
      dentroPlazoPercent: 82,
    };

    if (document.getElementById("expedientesCompletosCount")) {
      document.getElementById("expedientesCompletosCount").textContent =
        stats.expedientesCompletos;
      document.getElementById("expedientesCompletosPercent").textContent =
        `${stats.expedientesCompletosPercent}% del total`;

      document.getElementById("documentacionPendienteCount").textContent =
        stats.documentacionPendiente;
      document.getElementById("documentacionPendienteDetail").textContent =
        "Requieren seguimiento";

      document.getElementById("becasIncompatiblesCount").textContent =
        stats.becasIncompatibles;
      document.getElementById("becasIncompatiblesDetail").textContent =
        "Detectadas";

      document.getElementById("dentroPlazoCount").textContent =
        stats.dentroPlazo;
      document.getElementById("dentroPlazoPercent").textContent =
        `${stats.dentroPlazoPercent}% del total`;
    }
  }

  async function cargarValidacionRequisitos() {
    const tbody = document.getElementById("administrativoValidacionBody");
    if (!tbody) return;

    const data = [
      {
        id_solicitud: 101,
        nombre_estudiante: "María Pérez",
        tipo_beca: "Socioeconómica",
        documentacion_completa: true,
        becas_conflicto: false,
        fecha_limite: "2025-03-15",
        estado: "APROBADO",
      },
      {
        id_solicitud: 102,
        nombre_estudiante: "Juan Rodríguez",
        tipo_beca: "Excelencia Académica",
        documentacion_completa: false,
        becas_conflicto: false,
        fecha_limite: "2025-03-20",
        estado: "PENDIENTE",
      },
      {
        id_solicitud: 103,
        nombre_estudiante: "Ana López",
        tipo_beca: "Cultural",
        documentacion_completa: true,
        becas_conflicto: true,
        fecha_limite: "2025-03-10",
        estado: "RECHAZADO",
      },
    ];

    tbody.innerHTML = "";

    if (!data.length) {
      tbody.innerHTML =
        `<tr><td colspan="7" class="text-muted">No hay casos para validación.</td></tr>`;
      return;
    }

    data.forEach((item) => {
      const tr = document.createElement("tr");

      const docEstado = item.documentacion_completa
        ? "badge-success"
        : "badge-warning";
      const becasEstado = item.becas_conflicto
        ? "badge-danger"
        : "badge-success";
      const estadoGeneral =
        item.estado === "APROBADO"
          ? "badge-success"
          : item.estado === "PENDIENTE"
          ? "badge-warning"
          : "badge-danger";

      tr.innerHTML = `
        <td>
          <div class="user-cell">
            <span>${item.nombre_estudiante}</span>
          </div>
        </td>
        <td>${item.tipo_beca}</td>
        <td><span class="badge ${docEstado}">${
        item.documentacion_completa ? "Completa" : "Pendiente"
      }</span></td>
        <td><span class="badge ${becasEstado}">${
        item.becas_conflicto ? "Con conflictos" : "Sin conflictos"
      }</span></td>
        <td>${item.fecha_limite || "-"}</td>
        <td><span class="badge ${estadoGeneral}">${item.estado}</span></td>
        <td>
          <button class="btn btn-secondary btn-sm btn-ver-expediente" data-id="${
            item.id_solicitud
          }">
            Ver Expediente
          </button>
        </td>
      `;
      tbody.appendChild(tr);
    });
  }

  // ======================
  // Módulo: COMITÉ DE BECAS (FAKE)
  // ======================

  async function cargarDatosComite() {
    await cargarProximaSesion();
    await cargarCasosComite();
    await cargarHistorialSesiones();
  }

  async function cargarProximaSesion() {
    const container = document.getElementById("proximaSesionContainer");
    if (!container) return;

    const sesion = {
      nombre: "Sesión Comité Becas 01-2025",
      fecha: "2025-03-05",
      hora: "10:00",
      lugar: "Sala de Juntas 2",
      casos_pendientes: 8,
    };

    container.innerHTML = `
      <div class="session-card">
        <h4>${sesion.nombre}</h4>
        <p><strong>Fecha:</strong> ${sesion.fecha}</p>
        <p><strong>Hora:</strong> ${sesion.hora}</p>
        <p><strong>Lugar:</strong> ${sesion.lugar}</p>
        <p><strong>Casos a revisar:</strong> ${sesion.casos_pendientes}</p>
        <button class="btn btn-primary btn-sm">Ver Agenda</button>
      </div>
    `;
  }

  async function cargarCasosComite() {
    const tbody = document.getElementById("comiteCasosTableBody");
    if (!tbody) return;

    const casos = [
      {
        id_solicitud: 201,
        nombre_estudiante: "Carlos Jiménez",
        tipo_beca: "Socioeconómica",
        informe_socioeconomico: true,
        evaluacion_academica: true,
      },
      {
        id_solicitud: 202,
        nombre_estudiante: "Laura Gómez",
        tipo_beca: "Excelencia Académica",
        informe_socioeconomico: true,
        evaluacion_academica: false,
      },
      {
        id_solicitud: 203,
        nombre_estudiante: "Pedro Sánchez",
        tipo_beca: "Deportiva",
        informe_socioeconomico: false,
        evaluacion_academica: true,
      },
    ];

    tbody.innerHTML = "";

    if (!casos.length) {
      tbody.innerHTML =
        `<tr><td colspan="6" class="text-muted">No hay casos pendientes para el comité.</td></tr>`;
      return;
    }

    casos.forEach((caso) => {
      const tr = document.createElement("tr");

      const estadoSocio = caso.informe_socioeconomico
        ? "badge-success"
        : "badge-warning";
      const estadoAcademico = caso.evaluacion_academica
        ? "badge-success"
        : "badge-warning";

      tr.innerHTML = `
        <td>#${caso.id_solicitud}</td>
        <td>${caso.nombre_estudiante}</td>
        <td>${caso.tipo_beca}</td>
        <td><span class="badge ${estadoSocio}">${
        caso.informe_socioeconomico ? "Completo" : "Pendiente"
      }</span></td>
        <td><span class="badge ${estadoAcademico}">${
        caso.evaluacion_academica ? "Completo" : "Pendiente"
      }</span></td>
        <td>
          <button class="btn btn-primary btn-sm btn-revisar-caso" data-id="${
            caso.id_solicitud
          }">
            Revisar
          </button>
        </td>
      `;
      tbody.appendChild(tr);
    });
  }

  async function cargarHistorialSesiones() {
    const container = document.getElementById("comiteHistorialList");
    if (!container) return;

    const sesiones = [
      {
        id_sesion: 1,
        nombre: "Sesión 2024-II",
        estado: "CERRADA",
        fecha: "2024-11-10",
        casos_revisados: 25,
        aprobadas: 18,
        denegadas: 7,
      },
      {
        id_sesion: 2,
        nombre: "Sesión Extraordinaria 2024",
        estado: "CERRADA",
        fecha: "2024-12-01",
        casos_revisados: 10,
        aprobadas: 6,
        denegadas: 4,
      },
    ];

    container.innerHTML = "";

    if (!sesiones.length) {
      container.innerHTML =
        `<p class="text-muted">No hay sesiones en el historial.</p>`;
      return;
    }

    sesiones.forEach((sesion) => {
      const div = document.createElement("div");
      div.className = "session-item";

      div.innerHTML = `
        <div class="session-header">
          <h4>${sesion.nombre}</h4>
          <span class="badge">${sesion.estado}</span>
        </div>
        <div class="session-body">
          <p><strong>Fecha:</strong> ${sesion.fecha}</p>
          <p><strong>Casos revisados:</strong> ${
            sesion.casos_revisados || 0
          }</p>
          <p><strong>Resoluciones:</strong> ${
            sesion.aprobadas || 0
          } aprobadas, ${sesion.denegadas || 0} denegadas</p>
        </div>
        <div class="session-footer">
          <button class="btn btn-secondary btn-sm btn-ver-acta" data-id="${
            sesion.id_sesion
          }">
            Ver Acta
          </button>
        </div>
      `;
      container.appendChild(div);
    });
  }

  // ======================
  // Módulo: COMUNICACIÓN (FAKE)
  // ======================

  async function cargarComunicaciones() {
    await cargarEstadisticasComunicacion();
    await cargarHistorialComunicaciones();
  }

  async function cargarEstadisticasComunicacion() {
    const stats = {
      notificacionesEnviadas: 150,
      tasaApertura: 72,
      pendientesEnvio: 12,
      respuestasRecibidas: 34,
    };

    if (document.getElementById("notificacionesEnviadasCount")) {
      document.getElementById("notificacionesEnviadasCount").textContent =
        stats.notificacionesEnviadas;
      document.getElementById("tasaAperturaValue").textContent =
        `${stats.tasaApertura}%`;
      document.getElementById("pendientesEnvioCount").textContent =
        stats.pendientesEnvio;
      document.getElementById("respuestasRecibidasCount").textContent =
        stats.respuestasRecibidas;
    }
  }

  async function cargarHistorialComunicaciones() {
    const tbody = document.getElementById("comunicacionesHistorialBody");
    if (!tbody) return;

    const comunicaciones = [
      {
        id_comunicacion: 1,
        fecha: "2025-02-01",
        destinatario: "maria.perez@cuc.ac.cr",
        tipo: "APROBACION",
        asunto: "Aprobación de beca socioeconómica",
        estado: "ENTREGADO",
      },
      {
        id_comunicacion: 2,
        fecha: "2025-02-03",
        destinatario: "juan.rodri@cuc.ac.cr",
        tipo: "RECHAZO",
        asunto: "Resultado de solicitud de beca",
        estado: "ENVIADO",
      },
      {
        id_comunicacion: 3,
        fecha: "2025-02-05",
        destinatario: "ana.lopez@cuc.ac.cr",
        tipo: "DOCS_PENDIENTES",
        asunto: "Documentación faltante",
        estado: "ENTREGADO",
      },
    ];

    tbody.innerHTML = "";

    if (!comunicaciones.length) {
      tbody.innerHTML =
        `<tr><td colspan="6" class="text-muted">No hay comunicaciones registradas.</td></tr>`;
      return;
    }

    comunicaciones.forEach((com) => {
      const tr = document.createElement("tr");

      const tipoClase =
        com.tipo === "APROBACION"
          ? "badge-success"
          : com.tipo === "RECHAZO"
          ? "badge-danger"
          : "badge-secondary";

      const estadoClase =
        com.estado === "ENTREGADO" ? "badge-success" : "badge-warning";

      tr.innerHTML = `
        <td>${com.fecha}</td>
        <td>${com.destinatario}</td>
        <td><span class="badge ${tipoClase}">${com.tipo}</span></td>
        <td>${com.asunto}</td>
        <td><span class="badge ${estadoClase}">${com.estado}</span></td>
        <td>
          <button class="btn-icon btn-ver-comunicacion" title="Ver" data-id="${
            com.id_comunicacion
          }">👁</button>
          <button class="btn-icon btn-reenviar" title="Reenviar" data-id="${
            com.id_comunicacion
          }">📧</button>
        </td>
      `;
      tbody.appendChild(tr);
    });
  }

  function initComunicacionTemplates() {
    const botones = document.querySelectorAll(".btn-use-template");
    botones.forEach((btn) => {
      btn.addEventListener("click", (e) => {
        const tipo = e.target.getAttribute("data-template-type");
        usarPlantillaComunicacion(tipo);
      });
    });
  }

  function usarPlantillaComunicacion(tipo) {
    const plantillas = {
      APROBADA: "Su beca ha sido aprobada. Por favor revise los detalles...",
      DENEGADA:
        "Lamentamos informarle que su solicitud de beca no fue aprobada...",
      DOCS_PENDIENTES:
        "Se requieren documentos adicionales para completar su solicitud...",
      CONVOCATORIA: "Nueva convocatoria de becas disponible...",
    };

    const contenido = plantillas[tipo] || "Plantilla de comunicación";
    alert(`Usando plantilla: ${tipo}\n\n${contenido}`);
  }

  // ======================
  // Módulo: FORMALIZACIÓN (FAKE)
  // ======================

  async function cargarContratosFormalizacion() {
    await cargarEstadisticasFormalizacion();
    await cargarContratosPendientes();
  }

  async function cargarEstadisticasFormalizacion() {
    const stats = {
      contratosFirmados: 35,
      contratosFirmadosPorcentaje: 70,
      contratosPendientesFirma: 15,
      contratosRegistrados: 50,
      montoTotalFormalizado: 1250000,
    };

    if (document.getElementById("contratosFirmadosCount")) {
      document.getElementById("contratosFirmadosCount").textContent =
        stats.contratosFirmados;
      document.getElementById(
        "contratosFirmadosPorcentaje"
      ).textContent = `${stats.contratosFirmadosPorcentaje}% completado`;
      document.getElementById(
        "contratosPendientesFirmaCount"
      ).textContent = stats.contratosPendientesFirma;
      document.getElementById("contratosRegistradosCount").textContent =
        stats.contratosRegistrados;
      document.getElementById("montoTotalFormalizado").textContent =
        `$${stats.montoTotalFormalizado}`;
    }
  }

  async function cargarContratosPendientes() {
    const tbody = document.getElementById("contratosPendientesBody");
    if (!tbody) return;

    const contratos = [
      {
        id_contrato: 1,
        nombre_estudiante: "María Pérez",
        tipo_beca: "Socioeconómica",
        porcentaje: 50,
        monto: 150000,
        fecha_generacion: "2025-02-01",
        estado: "PENDIENTE",
      },
      {
        id_contrato: 2,
        nombre_estudiante: "Juan Rodríguez",
        tipo_beca: "Excelencia Académica",
        porcentaje: 75,
        monto: 200000,
        fecha_generacion: "2025-02-03",
        estado: "PENDIENTE",
      },
    ];

    tbody.innerHTML = "";

    if (!contratos.length) {
      tbody.innerHTML =
        `<tr><td colspan="7" class="text-muted">No hay contratos pendientes de firma.</td></tr>`;
      return;
    }

    contratos.forEach((contrato) => {
      const tr = document.createElement("tr");

      const estadoClase =
        contrato.estado === "PENDIENTE"
          ? "badge-warning"
          : "badge-success";

      tr.innerHTML = `
        <td>
          <div class="user-cell">
            <span>${contrato.nombre_estudiante}</span>
          </div>
        </td>
        <td>${contrato.tipo_beca}</td>
        <td>${contrato.porcentaje}%</td>
        <td>$${contrato.monto}</td>
        <td>${contrato.fecha_generacion}</td>
        <td><span class="badge ${estadoClase}">${contrato.estado}</span></td>
        <td>
          <button class="btn btn-primary btn-sm btn-enviar-firma" data-id="${
            contrato.id_contrato
          }">
            Enviar a Firma
          </button>
          <button class="btn-icon btn-ver-contrato" title="Ver" data-id="${
            contrato.id_contrato
          }">👁</button>
        </td>
      `;
      tbody.appendChild(tr);
    });
  }

  // ======================
  // Módulo: SEGUIMIENTO (FAKE)
  // ======================

  async function cargarSeguimiento() {
    await cargarEstadisticasSeguimiento();
    await cargarBecadosActivos();
  }

  async function cargarEstadisticasSeguimiento() {
    const quarterSelect = document.getElementById("monitoringQuarterFilter");
    const cuatrimestre = quarterSelect ? quarterSelect.value : "actual";

    const stats = {
      promedioGeneral: 8.4,
      tasaAprobacion: 89,
      desercion: 5,
      becasSuspendidas: 3,
      becadosActivos: 120,
      enRiesgo: 9,
      suspendidos: 3,
      montoDesembolsado: 540000,
    };

    if (document.getElementById("seguimientoPromedioGeneral")) {
      document.getElementById("seguimientoPromedioGeneral").textContent =
        stats.promedioGeneral;
      document.getElementById(
        "seguimientoTasaAprobacion"
      ).textContent = `${stats.tasaAprobacion}%`;
      document.getElementById("seguimientoDesercion").textContent =
        `${stats.desercion}%`;
      document.getElementById("seguimientoSuspendidas").textContent =
        stats.becasSuspendidas;

      document.getElementById("seguimientoBecadosActivos").textContent =
        stats.becadosActivos;
      document.getElementById("seguimientoEnRiesgo").textContent =
        stats.enRiesgo;
      document.getElementById("seguimientoSuspendidosResumen").textContent =
        stats.suspendidos;
      document.getElementById("seguimientoMontoDesembolsado").textContent =
        `$${stats.montoDesembolsado}`;

      document.getElementById(
        "seguimientoQuarterLabel"
      ).textContent = `(${cuatrimestre})`;
    }
  }

  async function cargarBecadosActivos() {
    const tbody = document.getElementById("seguimientoBecadosTableBody");
    if (!tbody) return;

    const filtroEstado =
      document.getElementById("seguimientoFiltroEstado")?.value || "todos";

    const becadosBase = [
      {
        id_beca: 1,
        nombre_estudiante: "María Pérez",
        tipo_beca: "Socioeconómica",
        cuatrimestre: "2025-I",
        promedio_actual: 8.7,
        asistencia: "95%",
        estado: "CUMPLIENDO",
      },
      {
        id_beca: 2,
        nombre_estudiante: "Juan Rodríguez",
        tipo_beca: "Excelencia Académica",
        cuatrimestre: "2025-I",
        promedio_actual: 7.8,
        asistencia: "88%",
        estado: "EN_RIESGO",
      },
      {
        id_beca: 3,
        nombre_estudiante: "Ana López",
        tipo_beca: "Deportiva",
        cuatrimestre: "2025-I",
        promedio_actual: 6.9,
        asistencia: "80%",
        estado: "SUSPENDIDA",
      },
    ];

    const becados =
      filtroEstado === "todos"
        ? becadosBase
        : becadosBase.filter((b) => b.estado === filtroEstado);

    tbody.innerHTML = "";

    if (!becados.length) {
      tbody.innerHTML =
        `<tr><td colspan="7" class="text-muted">No hay becados activos.</td></tr>`;
      return;
    }

    becados.forEach((becado) => {
      const tr = document.createElement("tr");

      const estadoClase =
        becado.estado === "CUMPLIENDO"
          ? "badge-success"
          : becado.estado === "EN_RIESGO"
          ? "badge-warning"
          : "badge-danger";

      const promedioClase =
        parseFloat(becado.promedio_actual) >= 8.0
          ? "badge-success"
          : "badge-danger";

      tr.innerHTML = `
        <td>${becado.nombre_estudiante}</td>
        <td>${becado.tipo_beca}</td>
        <td>${becado.cuatrimestre}</td>
        <td><span class="badge ${promedioClase}">${
        becado.promedio_actual
      }</span></td>
        <td>${becado.asistencia || "100%"}</td>
        <td><span class="badge ${estadoClase}">${becado.estado}</span></td>
        <td>
          <button class="btn btn-primary btn-sm btn-ver-seguimiento" data-id="${
            becado.id_beca
          }">
            Ver Detalles
          </button>
        </td>
      `;
      tbody.appendChild(tr);
    });
  }

  // ======================
  // Módulo: RENOVACIONES (FAKE)
  // ======================

  async function cargarRenovaciones() {
    await cargarSolicitudesRenovacion();
  }

  async function cargarSolicitudesRenovacion() {
    const tbody = document.getElementById("renovacionesTableBody");
    if (!tbody) return;

    const renovaciones = [
      {
        id_renovacion: 1,
        id_beca: 1,
        nombre_estudiante: "María Pérez",
        beca_actual: "Socioeconómica 50%",
        promedio_anterior: 8.5,
        promedio_actual: 8.9,
        situacion_socioeconomica: "Sin cambios",
        recomendacion: "RENOVAR_100%",
      },
      {
        id_renovacion: 2,
        id_beca: 2,
        nombre_estudiante: "Juan Rodríguez",
        beca_actual: "Excelencia 75%",
        promedio_anterior: 8.2,
        promedio_actual: 7.6,
        situacion_socioeconomica: "Mejoró",
        recomendacion: "RENOVAR_50%",
      },
      {
        id_renovacion: 3,
        id_beca: 3,
        nombre_estudiante: "Ana López",
        beca_actual: "Deportiva 50%",
        promedio_anterior: 7.0,
        promedio_actual: 6.5,
        situacion_socioeconomica: "Sin cambios",
        recomendacion: "NO_RENOVAR",
      },
    ];

    tbody.innerHTML = "";

    if (!renovaciones.length) {
      tbody.innerHTML =
        `<tr><td colspan="8" class="text-muted">No hay solicitudes de renovación.</td></tr>`;
      return;
    }

    renovaciones.forEach((renovacion) => {
      const tr = document.createElement("tr");

      const tendencia =
        parseFloat(renovacion.promedio_actual) >
        parseFloat(renovacion.promedio_anterior)
          ? "positive"
          : "negative";

      const tendenciaIcono = tendencia === "positive" ? "📈" : "📉";
      const tendenciaDiferencia = (
        parseFloat(renovacion.promedio_actual) -
        parseFloat(renovacion.promedio_anterior)
      ).toFixed(1);

      const recomendacionClase =
        renovacion.recomendacion === "RENOVAR_100%"
          ? "badge-success"
          : renovacion.recomendacion === "RENOVAR_50%"
          ? "badge-warning"
          : "badge-danger";

      tr.innerHTML = `
        <td>
          <div class="user-cell">
            <span>${renovacion.nombre_estudiante}</span>
          </div>
        </td>
        <td>${renovacion.beca_actual}</td>
        <td><span class="badge badge-success">${
          renovacion.promedio_anterior
        }</span></td>
        <td><span class="badge badge-success">${
          renovacion.promedio_actual
        }</span></td>
        <td><span class="trend-indicator ${tendencia}">${tendenciaIcono} ${tendenciaDiferencia}</span></td>
        <td><span class="badge badge-success">${
          renovacion.situacion_socioeconomica
        }</span></td>
        <td><span class="badge ${recomendacionClase}">${
        renovacion.recomendacion
      }</span></td>
        <td>
          <button class="btn btn-primary btn-sm btn-aprobar-renovacion" data-id="${
            renovacion.id_renovacion
          }">
            Aprobar
          </button>
          <button class="btn btn-secondary btn-sm btn-ver-historial" data-id="${
            renovacion.id_beca
          }">
            Ver Historial
          </button>
        </td>
      `;
      tbody.appendChild(tr);
    });
  }

  // ======================
  // Módulo: ARCHIVO (FAKE)
  // ======================

  async function cargarArchivo() {
    await cargarEstadisticasArchivo();
    await cargarExpedientesRecientes();
  }

  async function cargarEstadisticasArchivo() {
    const stats = {
      expedientesArchivados: 80,
      becasCompletadas: 65,
      tasaExito: 81,
      inversionTotal: 3200000,
      promedioGeneral: 8.3,
    };

    if (document.getElementById("expedientesArchivadosCount")) {
      document.getElementById("expedientesArchivadosCount").textContent =
        stats.expedientesArchivados;
      document.getElementById("becasCompletadasCount").textContent =
        stats.becasCompletadas;
      document.getElementById(
        "becasCompletadasPorcentaje"
      ).textContent = `${stats.tasaExito}% tasa de éxito`;
      document.getElementById("inversionTotalHistorica").textContent =
        `$${stats.inversionTotal}`;
      document.getElementById("promedioGeneralHistorico").textContent =
        stats.promedioGeneral;
    }
  }

  async function cargarExpedientesRecientes() {
    const tbody = document.getElementById("archivoExpedientesBody");
    if (!tbody) return;

    const expedientes = [
      {
        id_solicitud: 301,
        nombre_estudiante: "María Pérez",
        tipo_beca: "Socioeconómica",
        periodo: "2023-2024",
        estado_final: "COMPLETADA",
        fecha_cierre: "2024-12-15",
      },
      {
        id_solicitud: 302,
        nombre_estudiante: "Juan Rodríguez",
        tipo_beca: "Excelencia Académica",
        periodo: "2023-2024",
        estado_final: "SUSPENDIDA",
        fecha_cierre: "2024-11-30",
      },
      {
        id_solicitud: 303,
        nombre_estudiante: "Ana López",
        tipo_beca: "Deportiva",
        periodo: "2022-2023",
        estado_final: "RENUNCIADA",
        fecha_cierre: "2023-07-10",
      },
    ];

    tbody.innerHTML = "";

    if (!expedientes.length) {
      tbody.innerHTML =
        `<tr><td colspan="7" class="text-muted">No hay expedientes archivados.</td></tr>`;
      return;
    }

    expedientes.forEach((expediente) => {
      const tr = document.createElement("tr");

      const estadoClase =
        expediente.estado_final === "COMPLETADA"
          ? "badge-success"
          : expediente.estado_final === "SUSPENDIDA"
          ? "badge-warning"
          : "badge-danger";

      tr.innerHTML = `
        <td>#${expediente.id_solicitud}</td>
        <td>${expediente.nombre_estudiante}</td>
        <td>${expediente.tipo_beca}</td>
        <td>${expediente.periodo}</td>
        <td><span class="badge ${estadoClase}">${expediente.estado_final}</span></td>
        <td>${expediente.fecha_cierre}</td>
        <td>
          <button class="btn btn-secondary btn-sm btn-ver-expediente" data-id="${
            expediente.id_solicitud
          }">
            Ver Expediente
          </button>
        </td>
      `;
      tbody.appendChild(tr);
    });
  }

  // ======================
  // Módulo: REPORTES (usa APIs reales)
  // ======================

  function initReportes() {
    const view = document.getElementById("reportes-view");
    if (!view) return;

    const globalQuarterSelect = document.getElementById("reportsQuarterFilter");
    const globalBtn = document.getElementById("btnGenerateGlobalReport");

    if (globalBtn) {
      globalBtn.addEventListener("click", async () => {
        try {
          const data = await apiGet("/informes/estadisticos");
          console.log("📊 Informe estadístico global:", data);
          alert("Informe estadístico generado. Revisa la consola del navegador.");
        } catch (e) {
          // apiRequest ya mostró alert
        }
      });
    }

    const botones = view.querySelectorAll(".btn-generate-report");
    botones.forEach((btn) => {
      btn.addEventListener("click", async () => {
        const tipo = btn.getAttribute("data-report-type");
        const scopeSelect = btn
          .closest(".report-card")
          .querySelector(".report-scope-select");
        const scope = scopeSelect ? scopeSelect.value : "current";

        const periodo =
          (globalQuarterSelect && globalQuarterSelect.value !== "all"
            ? globalQuarterSelect.value
            : null) || null;

        const query = new URLSearchParams();
        if (tipo) query.set("tipo", tipo);
        if (periodo) query.set("periodo", periodo);
        if (scope) query.set("scope", scope);

        try {
          const data = await apiGet(
            `/informes/detalle?${query.toString()}`
          );
          console.log("📈 Informe detallado:", {
            tipo,
            scope,
            periodo,
            data,
          });
          alert(
            `Informe '${tipo}' generado (scope=${scope}${
              periodo ? ", periodo=" + periodo : ""
            }). Revisa la consola.`
          );
        } catch (e) {
          // apiRequest ya mostró alert
        }
      });
    });
  }

  // ======================
  // Inicialización global
  // ======================

  document.addEventListener("DOMContentLoaded", () => {
    initNavigation();

    if (document.getElementById("convocatoriaGrid")) {
      cargarConvocatorias();
      initNuevaConvocatoria();
    }

    if (document.getElementById("appealsList")) {
      cargarApelaciones();
    }

    if (document.getElementById("solicitudesGrid")) {
      initFiltrosSolicitudes();
      cargarSolicitudes();
    }

    if (document.getElementById("socioeconomico-view")) {
      initSocioeconomicoButtons();
      cargarCasosSocioeconomicos();
    }

    if (document.getElementById("academico-view")) {
      initEvaluacionAcademica();
      cargarEvaluacionAcademica();
    }

    if (document.getElementById("reportes-view")) {
      initReportes();
    }

    if (document.getElementById("comunicacion-view")) {
      initComunicacionTemplates();
    }

    const seguimientoFiltro = document.getElementById(
      "seguimientoFiltroEstado"
    );
    if (seguimientoFiltro) {
      seguimientoFiltro.addEventListener("change", () => {
        cargarBecadosActivos();
      });
    }

    const monitoringQuarterFilter = document.getElementById(
      "monitoringQuarterFilter"
    );
    if (monitoringQuarterFilter) {
      monitoringQuarterFilter.addEventListener("change", () => {
        cargarSeguimiento();
      });
    }

    const renovacionesQuarterFilter = document.getElementById(
      "renovacionesQuarterFilter"
    );
    if (renovacionesQuarterFilter) {
      renovacionesQuarterFilter.addEventListener("change", () => {
        cargarRenovaciones();
      });
    }
  });

  // Exponer helpers para debug
  window.AdminTS = {
    apiGet,
    apiPost,
    apiPut,
    apiDelete,
    cargarConvocatorias,
    cargarApelaciones,
    cargarSolicitudes,
    cargarCasosSocioeconomicos,
    cargarEvaluacionAcademica,
    cargarRevisionAdministrativa,
    cargarDatosComite,
    cargarComunicaciones,
    cargarContratosFormalizacion,
    cargarSeguimiento,
    cargarRenovaciones,
    cargarArchivo,
  };
})();
    }
