#include "categorytreewidget.h"
#include "db/dao/categorydao.h"
#include "db/dao/mailitemdao.h"
#include <QInputDialog>
#include <QColorDialog>
#include <QMessageBox>
#include <QDebug>
#include <QApplication>

CategoryTreeWidget::CategoryTreeWidget(QWidget *parent) : QTreeWidget(parent)
{
    setHeaderLabel(tr("Categorías"));
    setContextMenuPolicy(Qt::CustomContextMenu);
    setExpandsOnDoubleClick(false);
    setAnimated(true);
    setIndentation(16);
    
    connect(this, &QTreeWidget::customContextMenuRequested, this, &CategoryTreeWidget::onCategoryContextMenu);
    connect(this, &QTreeWidget::itemDoubleClicked, this, [this](QTreeWidgetItem* item, int) {
        Category cat = itemToCategory(item);
        if (cat.isValid()) emit categoryDoubleClicked(cat);
    });
    connect(this, &QTreeWidget::itemClicked, this, [this](QTreeWidgetItem* item, int) {
        Category cat = itemToCategory(item);
        if (cat.isValid()) emit categorySelected(cat);
    });
    
    setupContextMenu();
}

void CategoryTreeWidget::setupContextMenu()
{
    m_contextMenu = new QMenu(this);
    m_contextMenu->addAction(tr("Nueva categoría"), this, &CategoryTreeWidget::onNewCategory);
    m_contextMenu->addAction(tr("Nueva subcategoría"), this, [this]() {
        QTreeWidgetItem* item = currentItem();
        if (item) onEditCategory(item); // Reuse for subcategory creation
    });
    m_contextMenu->addSeparator();
    m_contextMenu->addAction(tr("Editar"), this, [this]() {
        QTreeWidgetItem* item = currentItem();
        if (item) onEditCategory(item);
    });
    m_contextMenu->addAction(tr("Eliminar"), this, [this]() {
        QTreeWidgetItem* item = currentItem();
        if (item) onDeleteCategory(item);
    });
    m_contextMenu->addSeparator();
    m_contextMenu->addAction(tr("Asignar a correos seleccionados"), this, [this]() {
        QTreeWidgetItem* item = currentItem();
        if (item) onAssignToSelectedMails(item);
    });
}

void CategoryTreeWidget::setAccountId(qint64 accountId)
{
    m_accountId = accountId;
    refresh();
}

void CategoryTreeWidget::refresh()
{
    clear();
    m_categoryItems.clear();
    loadCategories();
    expandAll();
}

void CategoryTreeWidget::loadCategories()
{
    QVector<Category> categories = CategoryDao::findByAccount(m_accountId);
    
    // Build tree: first root categories, then children
    QMap<qint64, QVector<Category>> childrenMap;
    QVector<Category> roots;
    
    for (const Category& cat : categories) {
        if (cat.parentCategoryId >= 0) {
            childrenMap[cat.parentCategoryId].append(cat);
        } else {
            roots.append(cat);
        }
    }
    
    // Sort by sortOrder
    auto sortByOrder = [](const Category& a, const Category& b) {
        return a.sortOrder < b.sortOrder;
    };
    std::sort(roots.begin(), roots.end(), sortByOrder);
    for (auto it = childrenMap.begin(); it != childrenMap.end(); ++it) {
        std::sort(it.value().begin(), it.value().end(), sortByOrder);
    }
    
    for (const Category& root : roots) {
        addCategory(root);
    }
}

void CategoryTreeWidget::addCategory(const Category& cat, QTreeWidgetItem* parent)
{
    QTreeWidgetItem* item = parent ? new QTreeWidgetItem(parent) : new QTreeWidgetItem(this);
    item->setText(0, cat.name);
    item->setData(0, Qt::UserRole, cat.id);
    item->setData(0, Qt::UserRole + 1, cat.accountId);
    item->setData(0, Qt::UserRole + 2, cat.parentCategoryId);
    item->setData(0, Qt::UserRole + 3, cat.sortOrder);
    
    // Color indicator
    QPixmap pix(16, 16);
    pix.fill(cat.color);
    item->setIcon(0, QIcon(pix));
    
    // Tooltip with details
    QString tooltip = QString("%1\nColor: %2\nAccount: %3")
        .arg(cat.name)
        .arg(cat.color.name())
        .arg(cat.isGlobal() ? "Global" : QString::number(cat.accountId));
    item->setToolTip(0, tooltip);
    
    m_categoryItems[cat.id] = item;
    
    // Add children
    QVector<Category> children = CategoryDao::findChildren(cat.id);
    for (const Category& child : children) {
        addCategory(child, item);
    }
}

QTreeWidgetItem* CategoryTreeWidget::findItemByCategoryId(qint64 categoryId)
{
    return m_categoryItems.value(categoryId, nullptr);
}

void CategoryTreeWidget::onMailSelected(qint64 mailId)
{
    // Update checkboxes/selection state for categories this mail belongs to
    QVector<qint64> catIds = CategoryDao::categoriesForMail(mailId);
    
    for (auto it = m_categoryItems.begin(); it != m_categoryItems.end(); ++it) {
        QTreeWidgetItem* item = it.value();
        bool assigned = catIds.contains(it.key());
        item->setCheckState(0, assigned ? Qt::Checked : Qt::Unchecked);
    }
}

void CategoryTreeWidget::onCategoryContextMenu(const QPoint& pos)
{
    QTreeWidgetItem* item = itemAt(pos);
    if (item) setCurrentItem(item);
    
    // Update action states
    bool hasItem = item != nullptr;
    QList<QAction*> actions = m_contextMenu->actions();
    for (QAction* act : actions) {
        QString text = act->text();
        if (text.contains("Editar") || text.contains("Eliminar") || text.contains("Asignar")) {
            act->setEnabled(hasItem);
        }
    }
    
    m_contextMenu->exec(viewport()->mapToGlobal(pos));
}

void CategoryTreeWidget::onNewCategory()
{
    QTreeWidgetItem* parentItem = currentItem();
    qint64 parentId = parentItem ? parentItem->data(0, Qt::UserRole).toLongLong() : -1;
    
    bool ok;
    QString name = QInputDialog::getText(this, tr("Nueva categoría"), tr("Nombre:"), QLineEdit::Normal, QString(), &ok);
    if (!ok || name.trimmed().isEmpty()) return;
    
    QColor color = QColorDialog::getColor(QColor("#1976D2"), this, tr("Color de la categoría"));
    if (!color.isValid()) color = QColor("#1976D2");
    
    Category cat;
    cat.name = name.trimmed();
    cat.color = color;
    cat.accountId = m_accountId;
    cat.parentCategoryId = parentId;
    cat.sortOrder = 0;
    
    if (CategoryDao::insert(cat)) {
        refresh();
        emit categoryCreated(cat);
    } else {
        QMessageBox::warning(this, tr("Error"), tr("No se pudo crear la categoría."));
    }
}

void CategoryTreeWidget::onEditCategory(QTreeWidgetItem* item)
{
    if (!item) return;
    
    qint64 catId = item->data(0, Qt::UserRole).toLongLong();
    auto catOpt = CategoryDao::findById(catId);
    if (!catOpt.has_value()) return;
    
    Category cat = *catOpt;
    
    bool ok;
    QString name = QInputDialog::getText(this, tr("Editar categoría"), tr("Nombre:"), QLineEdit::Normal, cat.name, &ok);
    if (!ok || name.trimmed().isEmpty()) return;
    
    QColor color = QColorDialog::getColor(cat.color, this, tr("Color de la categoría"));
    if (!color.isValid()) color = cat.color;
    
    cat.name = name.trimmed();
    cat.color = color;
    
    if (CategoryDao::update(cat)) {
        refresh();
        emit categoryEdited(cat);
    } else {
        QMessageBox::warning(this, tr("Error"), tr("No se pudo actualizar la categoría."));
    }
}

void CategoryTreeWidget::onDeleteCategory(QTreeWidgetItem* item)
{
    if (!item) return;
    
    qint64 catId = item->data(0, Qt::UserRole).toLongLong();
    
    if (QMessageBox::question(this, tr("Eliminar categoría"), 
        tr("¿Eliminar esta categoría y quitarla de todos los correos?"),
        QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) {
        return;
    }
    
    if (CategoryDao::remove(catId)) {
        refresh();
        emit categoryDeleted(catId);
    } else {
        QMessageBox::warning(this, tr("Error"), tr("No se pudo eliminar la categoría."));
    }
}

void CategoryTreeWidget::onAssignToSelectedMails(QTreeWidgetItem* item)
{
    if (!item) return;
    
    qint64 catId = item->data(0, Qt::UserRole).toLongLong();
    
    // This would need integration with the mail list view to get selected mail IDs
    // For now, emit signal for the main window to handle
    emit assignCategoryRequested(-1, catId); // -1 = use current selection
}

Category CategoryTreeWidget::itemToCategory(QTreeWidgetItem* item) const
{
    if (!item) return Category();
    
    qint64 id = item->data(0, Qt::UserRole).toLongLong();
    auto catOpt = CategoryDao::findById(id);
    return catOpt.value_or(Category());
}