#include "ShipStatsPanel.h"

#include <QLabel>
#include <QString>
#include <QVBoxLayout>

#include "GameConfig.h"
#include "ShipStatsCalculator.h"
#include "ThreatCostCalculator.h"

namespace
{

QString fmt(float value)
{
    return QString::number(static_cast<double>(value), 'f', 1);
}

QLabel* makeSectionHeader(const QString& text, QWidget* parent)
{
    QLabel* label = new QLabel(text, parent);
    QFont f = label->font();
    f.setBold(true);
    label->setFont(f);
    return label;
}

QLabel* makeStatLabel(QWidget* parent)
{
    return new QLabel(parent);
}

}  // namespace


ShipStatsPanel::ShipStatsPanel(const GameConfig* config, QWidget* parent)
    : QWidget(parent)
    , m_config(config)
{
    QVBoxLayout* layout = new QVBoxLayout(this);
    layout->setContentsMargins(4, 4, 4, 4);
    layout->setSpacing(2);
    layout->setAlignment(Qt::AlignTop);

    // Hull stats — always visible.
    m_hpLabel               = makeStatLabel(this);
    m_speedLabel            = makeStatLabel(this);
    m_sensorRangeLabel      = makeStatLabel(this);
    m_mainAccelLabel        = makeStatLabel(this);
    m_maneuveringAccelLabel = makeStatLabel(this);
    m_angularAccelLabel     = makeStatLabel(this);
    m_maxRotSpeedLabel      = makeStatLabel(this);
    m_cargoCapacityLabel    = makeStatLabel(this);
    m_cargoCapacityLabel->setVisible(false);

    layout->addWidget(m_hpLabel);
    layout->addWidget(m_speedLabel);
    layout->addWidget(m_sensorRangeLabel);
    layout->addWidget(m_mainAccelLabel);
    layout->addWidget(m_maneuveringAccelLabel);
    layout->addWidget(m_angularAccelLabel);
    layout->addWidget(m_maxRotSpeedLabel);
    layout->addWidget(m_cargoCapacityLabel);

    // Weapon capability section.
    m_weaponSection = new QWidget(this);
    {
        QVBoxLayout* sl = new QVBoxLayout(m_weaponSection);
        sl->setContentsMargins(0, 4, 0, 0);
        sl->setSpacing(2);
        sl->addWidget(makeSectionHeader(tr("Weapons"), m_weaponSection));
        m_weaponDpsLabel   = makeStatLabel(m_weaponSection);
        m_weaponRangeLabel = makeStatLabel(m_weaponSection);
        sl->addWidget(m_weaponDpsLabel);
        sl->addWidget(m_weaponRangeLabel);
    }
    m_weaponSection->setVisible(false);
    layout->addWidget(m_weaponSection);

    // Salvage capability section.
    m_salvageSection = new QWidget(this);
    {
        QVBoxLayout* sl = new QVBoxLayout(m_salvageSection);
        sl->setContentsMargins(0, 4, 0, 0);
        sl->setSpacing(2);
        sl->addWidget(makeSectionHeader(tr("Salvage"), m_salvageSection));
        m_salvageRateLabel  = makeStatLabel(m_salvageSection);
        m_salvageRangeLabel = makeStatLabel(m_salvageSection);
        sl->addWidget(m_salvageRateLabel);
        sl->addWidget(m_salvageRangeLabel);
    }
    m_salvageSection->setVisible(false);
    layout->addWidget(m_salvageSection);

    // Repair capability section.
    m_repairSection = new QWidget(this);
    {
        QVBoxLayout* sl = new QVBoxLayout(m_repairSection);
        sl->setContentsMargins(0, 4, 0, 0);
        sl->setSpacing(2);
        sl->addWidget(makeSectionHeader(tr("Repair"), m_repairSection));
        m_repairRateLabel  = makeStatLabel(m_repairSection);
        m_repairRangeLabel = makeStatLabel(m_repairSection);
        sl->addWidget(m_repairRateLabel);
        sl->addWidget(m_repairRangeLabel);
    }
    m_repairSection->setVisible(false);
    layout->addWidget(m_repairSection);

	// Current behavior — live entities only; hidden in the static design
	// preview (REQ-UI-SHIP-BEHAVIOR).
	m_behaviorLabel = makeSectionHeader(QString(), this);
	m_behaviorLabel->setVisible(false);
	layout->addWidget(m_behaviorLabel);

    // Threat cost — debug-only, initially hidden.
    m_threatCostLabel = makeStatLabel(this);
    m_threatCostLabel->setVisible(false);
    layout->addWidget(m_threatCostLabel);

    layout->addStretch();
}

void ShipStatsPanel::refresh(const std::string& shipId,
                              const std::vector<PlacedModule>& modules)
{
    const ShipStats stats = calculateShipStats(*m_config, shipId, modules);
    const QString hpText = tr("HP: %1").arg(static_cast<int>(stats.hp + 0.5f));
    applyStats(stats, hpText);

    const double threat = calculateShipThreatCost(m_config->threatCosts, *m_config,
                                                  shipId, modules);
    setThreatCost(threat);

    // The static design preview has no live behavior to show.
    m_behaviorLabel->setVisible(false);
}

void ShipStatsPanel::refreshFromLive(const ShipStats& stats, float currentHp)
{
    const QString hpText = tr("HP: %1 / %2")
        .arg(static_cast<int>(currentHp + 0.5f))
        .arg(static_cast<int>(stats.hp + 0.5f));
    applyStats(stats, hpText);
}

void ShipStatsPanel::applyStats(const ShipStats& stats, const QString& hpText)
{
    m_hpLabel->setText(hpText);
    m_speedLabel->setText(
        tr("Max Speed: %1 tiles/s").arg(fmt(stats.maxSpeed_tps)));
    m_sensorRangeLabel->setText(
        tr("Sensor Range: %1 tiles").arg(fmt(stats.sensorRange_tiles)));
    m_mainAccelLabel->setText(
        tr("Main Accel: %1 tiles/s\xc2\xb2").arg(fmt(stats.mainAcceleration_tpss)));
    m_maneuveringAccelLabel->setText(
        tr("Maneuvering Accel: %1 tiles/s\xc2\xb2").arg(fmt(stats.maneuveringAcceleration_tpss)));
    m_angularAccelLabel->setText(
        tr("Angular Accel: %1 rad/s\xc2\xb2").arg(fmt(stats.angularAcceleration_radpss)));
    m_maxRotSpeedLabel->setText(
        tr("Max Rotation: %1 rad/s").arg(fmt(stats.maxRotationSpeed_radps)));

    // Cargo capacity is shown only when the ship can actually hold cargo
    // (REQ-MOD-UI-STATS-PANEL).
    if (stats.cargoCapacity > 0)
    {
        m_cargoCapacityLabel->setText(
            tr("Cargo Capacity: %1").arg(stats.cargoCapacity));
        m_cargoCapacityLabel->setVisible(true);
    }
    else
    {
        m_cargoCapacityLabel->setVisible(false);
    }

    if (stats.weapons.has_value())
    {
        m_weaponDpsLabel->setText(
            tr("DPS: %1").arg(fmt(stats.weapons->combinedDps)));
        m_weaponRangeLabel->setText(
            tr("Range: %1 tiles").arg(fmt(stats.weapons->maxRange_tiles)));
        m_weaponSection->setVisible(true);
    }
    else
    {
        m_weaponSection->setVisible(false);
    }

    if (stats.salvage.has_value())
    {
        m_salvageRateLabel->setText(
            tr("Collection Rate: %1/s").arg(fmt(stats.salvage->combinedCollectionRate)));
        m_salvageRangeLabel->setText(
            tr("Range: %1 tiles").arg(fmt(stats.salvage->maxRange_tiles)));
        m_salvageSection->setVisible(true);
    }
    else
    {
        m_salvageSection->setVisible(false);
    }

    if (stats.repair.has_value())
    {
        m_repairRateLabel->setText(
            tr("Repair Rate: %1 HP/s").arg(fmt(stats.repair->combinedRepairRate_hps)));
        m_repairRangeLabel->setText(
            tr("Range: %1 tiles").arg(fmt(stats.repair->maxRange_tiles)));
        m_repairSection->setVisible(true);
    }
    else
    {
        m_repairSection->setVisible(false);
    }
}

void ShipStatsPanel::setBehavior(BehaviorKind kind)
{
    QString label;
    switch (kind)
    {
        case BehaviorKind::Retreat:      label = tr("Retreating"); break;
        case BehaviorKind::Attack:       label = tr("Engaging");   break;
        case BehaviorKind::SalvageScrap:
        case BehaviorKind::DeliverScrap: label = tr("Salvaging");  break;
        case BehaviorKind::Repair:       label = tr("Repairing");  break;
        case BehaviorKind::Rally:        label = tr("Rallying");   break;
        case BehaviorKind::Standby:      label = tr("Standby");    break;
        case BehaviorKind::Advance:      label = tr("Advancing");  break;
        case BehaviorKind::None:         break;
    }

    if (label.isEmpty())
    {
        m_behaviorLabel->setVisible(false);
        return;
    }

    m_behaviorLabel->setText(tr("Behavior: %1").arg(label));
    m_behaviorLabel->setVisible(true);
}

void ShipStatsPanel::setThreatCost(double cost)
{
    m_threatCostLabel->setText(tr("Threat Cost: %1").arg(cost, 0, 'f', 1));
    m_threatCostLabel->setVisible(m_debugDraw);
}

void ShipStatsPanel::setDebugDrawEnabled(bool enabled)
{
    m_debugDraw = enabled;
    m_threatCostLabel->setVisible(m_debugDraw);
}
