#pragma once
#include "Ronda.h"
#include "Jugador.h"
#include <vector>
#include <memory>
#include <QString>

// ──────────────────────────────────────────────
//  Clase abstracta Torneo
//  Define la interfaz común para cualquier tipo
//  de torneo. Usa el patrón Template Method para
//  la generación de rondas.
// ──────────────────────────────────────────────
class Torneo {
public:
    enum class Estado { CONFIGURACION, EN_CURSO, FINALIZADO };

    explicit Torneo(const QString& nombre, const QString& juego);
    virtual ~Torneo() = default;

    // ── Template Method ──────────────────────
    void iniciarTorneo();                  // Llama a generarRondaInicial()
    void avanzarRonda();                   // Llama a generarSiguienteRonda()
    // ─────────────────────────────────────────

    // Gestión jugadores
    void addJugador(std::shared_ptr<Jugador> j);
    bool removeJugador(const QString& id);

    // Getters
    QString  getNombre()   const { return m_nombre; }
    QString  getJuego()    const { return m_juego; }
    Estado   getEstado()   const { return m_estado; }
    int      getRondaActualIdx() const { return m_rondaActual; }
    bool     isFinalizado() const { return m_estado == Estado::FINALIZADO; }

    const std::vector<std::shared_ptr<Jugador>>& getJugadores() const { return m_jugadores; }
    const std::vector<std::shared_ptr<Ronda>>&   getRondas()    const { return m_rondas; }
    std::shared_ptr<Ronda>  getRondaActual() const;
    std::shared_ptr<Jugador> getCampeon()    const { return m_campeon; }

    // Info
    virtual QString tipo() const = 0;
    QString resumen() const;
    int totalRondasEsperadas() const;

protected:
    // ── Hooks para subclases ─────────────────
    virtual void generarRondaInicial() = 0;
    virtual void generarSiguienteRonda(const std::vector<std::shared_ptr<Jugador>>& ganadores) = 0;
    // ─────────────────────────────────────────

    void agregarRonda(std::shared_ptr<Ronda> r);
    void setCampeon(std::shared_ptr<Jugador> j);

    std::vector<std::shared_ptr<Jugador>> m_jugadores;
    std::vector<std::shared_ptr<Ronda>>   m_rondas;
    QString  m_nombre;
    QString  m_juego;
    Estado   m_estado  = Estado::CONFIGURACION;
    int      m_rondaActual = -1;
    std::shared_ptr<Jugador> m_campeon;
};

// ──────────────────────────────────────────────
//  TorneoEliminatorioSimple
//  Eliminación directa: perder = eliminado.
// ──────────────────────────────────────────────
class TorneoEliminatorioSimple : public Torneo {
public:
    TorneoEliminatorioSimple(const QString& nombre, const QString& juego);
    QString tipo() const override { return "Eliminatorio Simple"; }

protected:
    void generarRondaInicial()  override;
    void generarSiguienteRonda(const std::vector<std::shared_ptr<Jugador>>& ganadores) override;

private:
    std::shared_ptr<Ronda> crearRondaDesdeJugadores(
        const std::vector<std::shared_ptr<Jugador>>& jugadores,
        int numero, const QString& nombreRonda);
};

// ──────────────────────────────────────────────
//  TorneoDobleEliminacion
//  Necesita perder dos veces para quedar fuera.
// ──────────────────────────────────────────────
class TorneoDobleEliminacion : public Torneo {
public:
    TorneoDobleEliminacion(const QString& nombre, const QString& juego);
    QString tipo() const override { return "Doble Eliminación"; }

protected:
    void generarRondaInicial()  override;
    void generarSiguienteRonda(const std::vector<std::shared_ptr<Jugador>>& ganadores) override;

private:
    std::vector<std::shared_ptr<Jugador>> m_bracketPerdedores;
};
