#include "WidgetBracket.h"
#include <QPaintEvent>
#include <QMouseEvent>
#include <QPainterPath>
#include <cmath>

WidgetBracket::WidgetBracket(QWidget* parent) : QWidget(parent) {
    setMinimumSize(600, 400);
    setMouseTracking(true);
}

void WidgetBracket::setTorneo(Torneo* t) {
    m_torneo = t;
    recalcularCeldas();
}

void WidgetBracket::refresh() {
    recalcularCeldas();
    update();
}

void WidgetBracket::recalcularCeldas() {
    m_celdas.clear();
    if (!m_torneo) return;

    const auto& rondas = m_torneo->getRondas();
    int nRondas = (int)rondas.size();
    if (nRondas == 0) return;

    // Calcular cuántas filas necesita la ronda con más partidas
    int maxPartidas = 0;
    for (const auto& r : rondas)
        maxPartidas = std::max(maxPartidas, (int)r->getPartidas().size());

    int altoTotal = PADDING * 2 + maxPartidas * (CARD_H + ROW_GAP);
    int anchoTotal = PADDING * 2 + nRondas * (CARD_W + COL_GAP);

    setMinimumSize(anchoTotal, std::max(altoTotal, 400));

    for (int ri = 0; ri < nRondas; ++ri) {
        const auto& ronda = rondas[ri];
        int nPartidas = (int)ronda->getPartidas().size();
        int x = PADDING + ri * (CARD_W + COL_GAP);
        // Centrar verticalmente dentro del alto total
        int totalH = nPartidas * CARD_H + (nPartidas - 1) * ROW_GAP;
        int startY = PADDING + (height() - 2 * PADDING - totalH) / 2;
        if (startY < PADDING) startY = PADDING;

        for (int pi = 0; pi < nPartidas; ++pi) {
            int y = startY + pi * (CARD_H + ROW_GAP);
            QRect rect(x, y, CARD_W, CARD_H);
            m_celdas.push_back({rect, ri, pi});
        }
    }
}

void WidgetBracket::resizeEvent(QResizeEvent* e) {
    QWidget::resizeEvent(e);
    recalcularCeldas();
}

void WidgetBracket::paintEvent(QPaintEvent*) {
    QPainter p(this);
    p.setRenderHint(QPainter::Antialiasing);

    // Fondo
    p.fillRect(rect(), QColor(26, 26, 46));

    if (!m_torneo || m_torneo->getRondas().empty()) {
        p.setPen(QColor(80, 100, 130));
        p.setFont(QFont("Arial", 14));
        p.drawText(rect(), Qt::AlignCenter,
                   "Inicia el torneo para ver el bracket");
        return;
    }

    const auto& rondas = m_torneo->getRondas();
    int rondaActual = m_torneo->getRondaActualIdx();

    // Dibujar conectores entre rondas
    for (int ri = 0; ri + 1 < (int)rondas.size(); ++ri) {
        auto celdaActual  = [&](int pi) -> QRect* {
            for (auto& c : m_celdas) if (c.ronda == ri   && c.partida == pi) return &c.rect;
            return nullptr;
        };
        auto celdaSig = [&](int pi) -> QRect* {
            for (auto& c : m_celdas) if (c.ronda == ri+1 && c.partida == pi) return &c.rect;
            return nullptr;
        };

        const auto& partidasActual = rondas[ri]->getPartidas();
        int nPart = (int)partidasActual.size();
        for (int pi = 0; pi < nPart; pi += 2) {
            auto* r1 = celdaActual(pi);
            auto* r2 = celdaActual(std::min(pi+1, nPart-1));
            auto* rs = celdaSig(pi / 2);
            if (!r1 || !rs) continue;

            p.setPen(QPen(QColor(40, 80, 120), 2));
            // Línea desde r1 (right-center)
            QPoint p1(r1->right(), r1->center().y());
            QPoint p2(r2 ? r2->right() : r1->right(), r2 ? r2->center().y() : r1->center().y());
            int midX = p1.x() + (rs->left() - p1.x()) / 2;
            p.drawLine(p1, QPoint(midX, p1.y()));
            p.drawLine(p2, QPoint(midX, p2.y()));
            p.drawLine(QPoint(midX, p1.y()), QPoint(midX, p2.y()));
            QPoint midY((p1.y() + p2.y()) / 2, (p1.y() + p2.y()) / 2);
            p.drawLine(QPoint(midX, (p1.y() + p2.y()) / 2), QPoint(rs->left(), rs->center().y()));
        }
    }

    // Dibujar nombre de cada ronda como encabezado
    p.setFont(QFont("Arial", 10, QFont::Bold));
    for (int ri = 0; ri < (int)rondas.size(); ++ri) {
        // Buscar la primera celda de esta ronda para conocer el X
        for (auto& c : m_celdas) {
            if (c.ronda == ri) {
                p.setPen(QColor(180, 200, 240));
                p.drawText(QRect(c.rect.x(), 6, CARD_W, 20),
                           Qt::AlignCenter, rondas[ri]->getNombre());
                break;
            }
        }
    }

    // Dibujar partidas
    for (auto& celda : m_celdas) {
        if (celda.ronda >= (int)rondas.size()) continue;
        const auto& partidas = rondas[celda.ronda]->getPartidas();
        if (celda.partida >= (int)partidas.size()) continue;
        const auto& partida = *partidas[celda.partida];
        bool activa = (celda.ronda == rondaActual);
        dibujarPartida(p, celda.rect, partida, activa);
    }
}

void WidgetBracket::dibujarPartida(QPainter& p, const QRect& rect,
                                    const Partida& partida, bool activa)
{
    // Fondo de la tarjeta
    QColor bgTop, bgBot, border;
    switch (partida.getEstado()) {
    case Partida::Estado::FINALIZADA:
        bgTop = QColor(15, 40, 30); bgBot = QColor(10, 30, 20);
        border = QColor(39, 174, 96); break;
    case Partida::Estado::BYE:
        bgTop = QColor(30, 30, 50); bgBot = QColor(20, 20, 40);
        border = QColor(80, 80, 120); break;
    default:
        if (activa) {
            bgTop = QColor(15, 40, 70); bgBot = QColor(10, 30, 55);
            border = QColor(233, 69, 96);
        } else {
            bgTop = QColor(22, 33, 62); bgBot = QColor(15, 25, 50);
            border = QColor(40, 70, 110);
        }
    }

    QPainterPath path;
    path.addRoundedRect(rect, 8, 8);

    QLinearGradient grad(rect.topLeft(), rect.bottomLeft());
    grad.setColorAt(0, bgTop);
    grad.setColorAt(1, bgBot);
    p.fillPath(path, grad);
    p.setPen(QPen(border, activa ? 2 : 1));
    p.drawPath(path);

    // Separador horizontal (mitad de la tarjeta)
    int mid = rect.top() + rect.height() / 2;
    p.setPen(QPen(border.darker(150), 1));
    p.drawLine(rect.left() + 8, mid, rect.right() - 8, mid);

    auto j1 = partida.getJugador1();
    auto j2 = partida.getJugador2();
    auto ganador = partida.getGanador();

    auto dibujarJugador = [&](const std::shared_ptr<Jugador>& j, QRect fila) {
        if (!j) {
            p.setPen(QColor(70, 90, 120));
            p.setFont(QFont("Arial", 9, QFont::StyleItalic));
            p.drawText(fila.adjusted(8, 0, -8, 0), Qt::AlignVCenter | Qt::AlignLeft, "TBD");
            return;
        }
        bool esGanador = (ganador == j);
        bool esBye = partida.isBye();

        if (esGanador || esBye)
            p.setPen(QColor(80, 220, 130));
        else if (j->isEliminado() && partida.getEstado() == Partida::Estado::FINALIZADA)
            p.setPen(QColor(100, 100, 120));
        else
            p.setPen(QColor(200, 215, 240));

        p.setFont(QFont("Arial", 10, esGanador ? QFont::Bold : QFont::Normal));
        QString label = j->getAlias();
        if (esGanador) label = "🏆 " + label;
        if (esBye)     label = "✓ " + label + " (BYE)";
        p.drawText(fila.adjusted(8, 0, -8, 0), Qt::AlignVCenter | Qt::AlignLeft, label);
    };

    QRect filaTop(rect.left(), rect.top(), rect.width(), rect.height() / 2);
    QRect filaBtm(rect.left(), mid, rect.width(), rect.height() / 2);

    if (partida.isBye()) {
        // Solo mostrar j1 centrado
        p.setPen(QColor(150, 160, 200));
        p.setFont(QFont("Arial", 9, QFont::StyleItalic));
        p.drawText(rect.adjusted(8,0,-8,0), Qt::AlignVCenter | Qt::AlignLeft,
                   QString("✓ %1  (pasa automático)").arg(j1 ? j1->getAlias() : "?"));
    } else {
        dibujarJugador(j1, filaTop);
        dibujarJugador(j2, filaBtm);
    }

    // Indicador de clickeable
    if (activa && partida.getEstado() != Partida::Estado::FINALIZADA && !partida.isBye()) {
        p.setPen(QColor(233, 69, 96, 160));
        p.setFont(QFont("Arial", 8));
        p.drawText(rect.adjusted(0, 0, -4, 0),
                   Qt::AlignRight | Qt::AlignBottom,
                   "click ▸ ");
    }
}

void WidgetBracket::mousePressEvent(QMouseEvent* e) {
    if (!m_torneo) return;
    for (auto& c : m_celdas) {
        if (c.rect.contains(e->pos())) {
            emit partidaSeleccionada(c.ronda, c.partida);
            return;
        }
    }
}
