#include "FunctionListPanel.h"

#include <QtConcurrent/QtConcurrent>
#include <QFileInfo>
#include <QFont>
#include <QProgressBar>

FunctionListPanel::FunctionListPanel(QWidget *parent)
    : QWidget(parent)
{
    m_scanner = new FunctionScanner(this);
    m_watcher = new QFutureWatcher<QList<FunctionScanner::FunctionInfo>>(this);

    connect(m_watcher, &QFutureWatcher<QList<FunctionScanner::FunctionInfo>>::finished,
            this, &FunctionListPanel::onScanFinished);

    setupUi();
}

// ---------------------------------------------------------------------------
// UI
// ---------------------------------------------------------------------------
void FunctionListPanel::setupUi()
{
    QVBoxLayout *root = new QVBoxLayout(this);
    root->setContentsMargins(0, 0, 0, 0);
    root->setSpacing(0);

    // ---- Kopfzeile ----
    QWidget *header = new QWidget(this);
    header->setStyleSheet("background: palette(mid);");
    QHBoxLayout *headerLayout = new QHBoxLayout(header);
    headerLayout->setContentsMargins(6, 4, 6, 4);
    headerLayout->setSpacing(4);

    QLabel *title = new QLabel(tr("Projektfunktionen"), header);
    QFont boldFont = title->font();
    boldFont.setBold(true);
    title->setFont(boldFont);
    headerLayout->addWidget(title);
    headerLayout->addStretch();

    m_btnRefresh = new QPushButton(tr("↻"), header);
    m_btnRefresh->setFixedSize(24, 24);
    m_btnRefresh->setFlat(true);
    m_btnRefresh->setToolTip(tr("Neu scannen"));
    headerLayout->addWidget(m_btnRefresh);

    root->addWidget(header);

    // ---- Filter + Gruppierung ----
    QHBoxLayout *toolRow = new QHBoxLayout();
    toolRow->setContentsMargins(6, 4, 6, 4);
    toolRow->setSpacing(4);

    m_filterEdit = new QLineEdit(this);
    m_filterEdit->setPlaceholderText(tr("Funktion suchen…"));
    m_filterEdit->setClearButtonEnabled(true);
    toolRow->addWidget(m_filterEdit, 1);

    m_groupCombo = new QComboBox(this);
    m_groupCombo->addItem(tr("Nach Datei"), "file");
    m_groupCombo->addItem(tr("Nach Klasse"), "class");
    m_groupCombo->addItem(tr("Alphabetisch"), "alpha");
    m_groupCombo->setFixedWidth(120);
    toolRow->addWidget(m_groupCombo);

    root->addLayout(toolRow);

    // ---- Status ----
    m_statusLabel = new QLabel(this);
    m_statusLabel->setContentsMargins(6, 0, 6, 2);
    m_statusLabel->setStyleSheet("color: palette(mid); font-size: 11px;");
    root->addWidget(m_statusLabel);

    // ---- Ergebnisbaum ----
    m_tree = new QTreeWidget(this);
    m_tree->setHeaderHidden(true);
    m_tree->setRootIsDecorated(true);
    m_tree->setIndentation(14);
    m_tree->setAlternatingRowColors(false);
    m_tree->setAnimated(true);

    // Monospace-Font für Parameter
    QFont monoFont("Monospace", m_tree->font().pointSize());
    monoFont.setStyleHint(QFont::Monospace);
    m_tree->setFont(monoFont);

    root->addWidget(m_tree, 1);

    // ---- Verbindungen ----
    connect(m_btnRefresh,  &QPushButton::clicked,
            this, &FunctionListPanel::refresh);

    connect(m_filterEdit,  &QLineEdit::textChanged,
            this, &FunctionListPanel::onFilterChanged);

    connect(m_groupCombo,  QOverload<int>::of(&QComboBox::currentIndexChanged),
            this, &FunctionListPanel::onGroupingChanged);

    connect(m_tree, &QTreeWidget::itemActivated,
            this, &FunctionListPanel::onItemActivated);
}

// ---------------------------------------------------------------------------
// Öffentliche Schnittstelle
// ---------------------------------------------------------------------------
void FunctionListPanel::setProjectRoot(const QString &path)
{
    m_projectRoot = path;
    if (!path.isEmpty())
    {
        refresh();
    }
    else
    {
        m_tree->clear();
        m_statusLabel->setText(QString());
        m_lastResult.clear();
    }
}

void FunctionListPanel::activate()
{
    m_filterEdit->setFocus();
    m_filterEdit->selectAll();
    if (m_lastResult.isEmpty() && !m_projectRoot.isEmpty())
    {
        refresh();
    }
}

// ---------------------------------------------------------------------------
// Scan starten
// ---------------------------------------------------------------------------
void FunctionListPanel::refresh()
{
    if (m_projectRoot.isEmpty())
    {
        m_statusLabel->setText(tr("Kein Projekt geöffnet."));
        return;
    }

    if (m_watcher->isRunning())
    {
        m_watcher->cancel();
        m_watcher->waitForFinished();
    }

    m_statusLabel->setText(tr("Scanne…"));
    m_btnRefresh->setEnabled(false);

    const QString root    = m_projectRoot;
    FunctionScanner *scanner = m_scanner;

    QFuture<QList<FunctionScanner::FunctionInfo>> future =
        QtConcurrent::run([scanner, root]()
        {
            return scanner->scanDirectory(root);
        });

    m_watcher->setFuture(future);
}

// ---------------------------------------------------------------------------
// Scan abgeschlossen
// ---------------------------------------------------------------------------
void FunctionListPanel::onScanFinished()
{
    m_btnRefresh->setEnabled(true);

    if (m_watcher->isCanceled())
    {
        return;
    }

    m_lastResult = m_watcher->result();
    populateTree(m_lastResult);
}

// ---------------------------------------------------------------------------
// Baum befüllen
// ---------------------------------------------------------------------------
void FunctionListPanel::populateTree(const QList<FunctionScanner::FunctionInfo> &functions)
{
    m_tree->clear();

    const QString groupBy = m_groupCombo->currentData().toString();
    const QString filter  = m_filterEdit->text().trimmed().toLower();

    // Funktionen filtern
    QList<FunctionScanner::FunctionInfo> filtered;
    for (const auto &f : functions)
    {
        if (filter.isEmpty() ||
            f.name.toLower().contains(filter) ||
            f.parameters.toLower().contains(filter) ||
            f.className.toLower().contains(filter))
        {
            filtered.append(f);
        }
    }

    if (groupBy == "alpha")
    {
        // Alphabetisch — keine Gruppen
        std::sort(filtered.begin(), filtered.end(),
            [](const FunctionScanner::FunctionInfo &a,
               const FunctionScanner::FunctionInfo &b)
            {
                return a.name.toLower() < b.name.toLower();
            });

        for (const auto &f : filtered)
        {
            QTreeWidgetItem *item = new QTreeWidgetItem(m_tree);
            formatFunctionItem(item, f);
        }
    }
    else
    {
        // Gruppiert nach Datei oder Klasse
        QMap<QString, QList<FunctionScanner::FunctionInfo>> groups;

        for (const auto &f : filtered)
        {
            QString key;
            if (groupBy == "class")
            {
                key = f.className.isEmpty() ? tr("(global)") : f.className;
            }
            else
            {
                key = QFileInfo(f.filePath).fileName();
            }
            groups[key].append(f);
        }

        for (auto it = groups.begin(); it != groups.end(); ++it)
        {
            QTreeWidgetItem *groupItem = new QTreeWidgetItem(m_tree);
            groupItem->setText(0, QString("%1  (%2)")
                                   .arg(it.key())
                                   .arg(it.value().size()));
            groupItem->setData(0, Qt::UserRole, QString());
            groupItem->setData(0, Qt::UserRole + 1, -1);

            QFont boldFont = groupItem->font(0);
            boldFont.setBold(true);
            groupItem->setFont(0, boldFont);
            groupItem->setExpanded(true);

            // Funktionen innerhalb der Gruppe alphabetisch
            auto &list = it.value();
            std::sort(list.begin(), list.end(),
                [](const FunctionScanner::FunctionInfo &a,
                   const FunctionScanner::FunctionInfo &b)
                {
                    return a.name.toLower() < b.name.toLower();
                });

            for (const auto &f : list)
            {
                QTreeWidgetItem *item = new QTreeWidgetItem(groupItem);
                formatFunctionItem(item, f);
            }
        }
    }

    // Statuszeile
    const int total    = functions.size();
    const int shown    = filtered.size();
    if (filter.isEmpty())
    {
        m_statusLabel->setText(tr("%1 Funktionen gefunden").arg(total));
    }
    else
    {
        m_statusLabel->setText(tr("%1 von %2 Funktionen").arg(shown).arg(total));
    }
}

void FunctionListPanel::formatFunctionItem(QTreeWidgetItem *item,
                                            const FunctionScanner::FunctionInfo &f)
{
    // Anzeige: name(parameter)  — Zeilennummer klein dahinter
    const QString display = QString("%1(%2)")
                                .arg(f.name)
                                .arg(f.parameters);

    item->setText(0, display);
    item->setToolTip(0, QString("%1\nZeile %2").arg(f.filePath).arg(f.line));
    item->setData(0, Qt::UserRole,     f.filePath);
    item->setData(0, Qt::UserRole + 1, f.line);

    // Zeilennummer in gedimmter Farbe als zweite Spalte simulieren
    // (über ToolTip gelöst da wir nur eine Spalte haben)
}

// ---------------------------------------------------------------------------
// Slots
// ---------------------------------------------------------------------------
void FunctionListPanel::onItemActivated(QTreeWidgetItem *item, int /*column*/)
{
    const QString path = item->data(0, Qt::UserRole).toString();
    const int     line = item->data(0, Qt::UserRole + 1).toInt();

    if (path.isEmpty() || line < 0)
    {
        item->setExpanded(!item->isExpanded());
        return;
    }

    emit fileLineRequested(path, line);
}

void FunctionListPanel::onFilterChanged(const QString &text)
{
    Q_UNUSED(text)
    if (!m_lastResult.isEmpty())
    {
        populateTree(m_lastResult);
    }
}

void FunctionListPanel::onGroupingChanged(int /*index*/)
{
    if (!m_lastResult.isEmpty())
    {
        populateTree(m_lastResult);
    }
}
