#include "Ramo.h"
#include "Semestre.h"
#include "ActividadAcademica.h" // Incluir la nueva clase unificada
#include <QDebug>
#include <QtMath> // Para qIsNaN y qFabs

int Ramo::nextId = 0;

Ramo::Ramo(int id, const QString& nombre, const QString& codigo, int creditos,
           Semestre* semestreAsociado, const QString& profesor, const QColor& color
        )
    : idRamo(id), nombre(nombre), codigo(codigo), creditos(creditos),
      semestreAsociado(semestreAsociado), profesor(profesor), colorAsociado(color)
{
    if (id == 0) {
        this->idRamo = ++nextId;
    } else if (id > nextId) {
        nextId = id;
    }
}

Ramo::~Ramo() {
    // Las actividades evaluativas no se eliminan aquí porque son propiedad del Calendario
    // a través de la lista global de Eventos/ActividadesAcademicas.
    // Esta lista `actividadesEvaluativas` en Ramo solo contiene punteros a ellas.
    actividadesEvaluativas.clear();
}


// Getters existentes
int Ramo::getIdRamo() const { return idRamo; }
QString Ramo::getNombre() const { return nombre; }
QString Ramo::getCodigo() const { return codigo; }
int Ramo::getCreditos() const { return creditos; }
Semestre* Ramo::getSemestreAsociado() const { return semestreAsociado; }
QString Ramo::getProfesor() const { return profesor; }
QColor Ramo::getColorAsociado() const { return colorAsociado; }

// ¡Nuevos Getters para TOTALES DE HORAS!
float Ramo::getTotalHorasCatedra() const { return m_totalHorasCatedra; }
float Ramo::getTotalHorasAyudantiaPresencial() const { return m_totalHorasAyudantiaPresencial; }
float Ramo::getTotalHorasEvaluacionesPresencial() const { return m_totalHorasEvaluacionesPresencial; }
float Ramo::getTotalHorasOtrasPresencial() const { return m_totalHorasOtrasPresencial; }

float Ramo::getTotalHorasEstudioNoPresencial() const { return m_totalHorasEstudioNoPresencial; }
float Ramo::getTotalHorasProyectosNoPresencial() const { return m_totalHorasProyectosNoPresencial; }

// Calculadoras de totales (ahora usan los atributos directos)
float Ramo::getTotalHorasPresencialEstimado() const {
    return m_totalHorasCatedra + m_totalHorasAyudantiaPresencial +
           m_totalHorasEvaluacionesPresencial + m_totalHorasOtrasPresencial;
}

float Ramo::getTotalHorasNoPresencialEstimado() const {
    // Las horas de tareas no presenciales no se incluyen aquí en el Ramo,
    // se gestionan directamente en cada Tarea.
    return m_totalHorasEstudioNoPresencial + m_totalHorasProyectosNoPresencial;
}

float Ramo::getTotalHorasRelojEstimado() const {
    return getTotalHorasPresencialEstimado() + getTotalHorasNoPresencialEstimado();
}

// Setters existentes
void Ramo::setNombre(const QString& nombre) { this->nombre = nombre; }
void Ramo::setCodigo(const QString& codigo) { this->codigo = codigo; }
void Ramo::setCreditos(int creditos) { this->creditos = creditos; }
void Ramo::setSemestreAsociado(Semestre* semestre) { this->semestreAsociado = semestre; }
void Ramo::setProfesor(const QString& profesor) { this->profesor = profesor; }
void Ramo::setColorAsociado(const QColor& color) { this->colorAsociado = color; }

// ¡CORRECCIÓN AQUÍ! Asegurarse de la sintaxis "void Ramo::" para todos los setters
void Ramo::setTotalHorasCatedra(float horas) { m_totalHorasCatedra = horas; }
void Ramo::setTotalHorasAyudantiaPresencial(float horas) { m_totalHorasAyudantiaPresencial = horas; }
void Ramo::setTotalHorasEvaluacionesPresencial(float horas) { m_totalHorasEvaluacionesPresencial = horas; }
void Ramo::setTotalHorasOtrasPresencial(float horas) { m_totalHorasOtrasPresencial = horas; }
void Ramo::setTotalHorasEstudioNoPresencial(float horas) { m_totalHorasEstudioNoPresencial = horas; }
void Ramo::setTotalHorasProyectosNoPresencial(float horas) { m_totalHorasProyectosNoPresencial = horas; }

// Métodos para gestionar actividades evaluativas (sin cambios en la lógica interna)
void Ramo::agregarActividadEvaluativa(ActividadAcademica* actividad) { // Aceptar ActividadAcademica*
    if (actividad) { // Solo si tiene ponderación
        actividadesEvaluativas.append(actividad);
        qDebug() << "Actividad evaluativa '" << actividad->getNombre() << "' agregada al ramo " << nombre;
    } else if (actividad) {
        qDebug() << "Advertencia: Actividad '" << actividad->getNombre() << "' no tiene ponderación, no se agrega a la lista evaluativa del ramo.";
    }
}

void Ramo::eliminarActividadEvaluativa(int idActividad) {
    for (int i = 0; i < actividadesEvaluativas.size(); ++i) {
        if (actividadesEvaluativas.at(i)->getId() == idActividad) { // Usar getId() de ActividadAcademica
            // No deleteamos el objeto, solo lo removemos de esta lista de punteros.
            // La eliminación real ocurre cuando se libera la lista principal de Eventos/ActividadesAcademicas en Calendario.
            actividadesEvaluativas.removeAt(i);
            qDebug() << "Actividad evaluativa con ID" << idActividad << "eliminada del ramo " << nombre;
            return;
        }
    }
    qWarning() << "Actividad evaluativa con ID" << idActividad << "no encontrada en el ramo " << nombre;
}

ActividadAcademica* Ramo::obtenerActividadEvaluativaPorId(int idActividad) const { // Devuelve ActividadAcademica*
    for (ActividadAcademica* act : actividadesEvaluativas) {
        if (act->getId() == idActividad) {
            return act;
        }
    }
    return nullptr;
}

QList<ActividadAcademica*> Ramo::getActividadesEvaluativas() const { // Devuelve QList<ActividadAcademica*>
    return actividadesEvaluativas;
}

float Ramo::calcularNotaFinal() const {
    float notaAcumulada = 0.0f;
    float ponderacionTotalCompleta = 0.0f;
    float ponderacionTotalDefinida = 0.0f; // Suma de todas las ponderaciones definidas

    for (ActividadAcademica* act : actividadesEvaluativas) { // Iterar sobre ActividadAcademica
        if (!act || act->getPonderacion() <= 0) continue; // Solo actividades válidas con ponderación

        ponderacionTotalDefinida += act->getPonderacion();
        if (act->estaCompletada() && act->tieneNota()) { // Usar estaCompletada() y tieneNota()
            notaAcumulada += act->getNotaObtenida() * act->getPonderacion();
            ponderacionTotalCompleta += act->getPonderacion();
        }
    }

    if (ponderacionTotalCompleta == 0.0f) {
        return 0.0f;
    }
    return notaAcumulada / ponderacionTotalCompleta;
}

float Ramo::calcularAvance() const {
    if (actividadesEvaluativas.isEmpty()) {
        return 0.0f;
    }
    int completadas = 0;
    for (ActividadAcademica* act : actividadesEvaluativas) { // Iterar sobre ActividadAcademica
        if (act->estaCompletada()) { // Usar estaCompletada()
            completadas++;
        }
    }
    return (static_cast<float>(completadas) / actividadesEvaluativas.size()) * 100.0f;
}