#include "richtexteditor.h"
#include <QFrame>
#include <QFileDialog>
#include <QInputDialog>
#include <QMessageBox>
#include <QDebug>
#include <QDialog>
#include <QVBoxLayout>
#include <QDialogButtonBox>
#include <QLabel>
#include "../../thirdparty/tags/include/tags_line_edit.hpp"
#include <QRegularExpression>
#include <QTimer>
#include <QTextList>
#include <QTextTable>
#include <QTextCursor>
#include <QTextBlockFormat>
#include <QTextCharFormat>
#include <QTextImageFormat>
#include <QTextTableFormat>
#include <QTextLength>
#include <QPixmap>
#include <QMouseEvent>
#include <QContextMenuEvent>
#include <QApplication>
#include <QMenu>
#include <QAction>
#include <QWidget>
#include <QLabel>
#include <QResizeEvent>
#include <QTextTableCell>

// ===================== RichTextEditor =====================

RichTextEditor::RichTextEditor(QWidget *parent) : QTextEdit(parent) {
    setAcceptRichText(true);
    setPlaceholderText("Write your message here...");
    setMouseTracking(true);
}

void RichTextEditor::setupToolbar(QVBoxLayout *layout) {
    m_toolbar = new QToolBar("Formatting");
    m_toolbar->setIconSize(QSize(16, 16));
    m_toolbar->setStyleSheet(
        "QToolBar { background: #f5f5f7; border: 1px solid #d1d1d6; border-radius: 4px; spacing: 2px; padding: 2px; }\n"
        "QToolButton { padding: 4px 6px; border-radius: 3px; }\n"
        "QToolButton:hover { background: #e0e0e0; }\n"
        "QToolButton:checked { background: #bbdefb; }\n"
    );

    // Font family combo
    m_fontCombo = new QFontComboBox();
    m_fontCombo->setFixedWidth(150);
    connect(m_fontCombo, &QFontComboBox::currentFontChanged, this, &RichTextEditor::onFontChanged);
    m_toolbar->addWidget(m_fontCombo);

    // Font size spin
    m_fontSizeSpin = new QSpinBox();
    m_fontSizeSpin->setRange(8, 72);
    m_fontSizeSpin->setValue(11);
    m_fontSizeSpin->setFixedWidth(70);
    m_fontSizeSpin->setFixedHeight(24);
    connect(m_fontSizeSpin, QOverload<int>::of(&QSpinBox::valueChanged), this, &RichTextEditor::onFontSizeChanged);
    m_toolbar->addWidget(m_fontSizeSpin);

    m_toolbar->addSeparator();

    // Bold / Italic / Underline
    QAction *boldAct = m_toolbar->addAction("B");
    boldAct->setCheckable(true);
    boldAct->setIcon(QIcon(QStringLiteral(":/icons/resources/icons/SVG/Bold/Text Formatting/Text Bold.svg")));
    QFont boldFont = boldAct->font(); boldFont.setBold(true); boldAct->setFont(boldFont);
    connect(boldAct, &QAction::triggered, this, &RichTextEditor::onBold);

    QAction *italicAct = m_toolbar->addAction("I");
    italicAct->setCheckable(true);
    italicAct->setIcon(QIcon(QStringLiteral(":/icons/resources/icons/SVG/Outline/Text Formatting/Text Italic.svg")));
    QFont italicFont = italicAct->font(); italicFont.setItalic(true); italicAct->setFont(italicFont);
    connect(italicAct, &QAction::triggered, this, &RichTextEditor::onItalic);

    QAction *underlineAct = m_toolbar->addAction("U");
    underlineAct->setCheckable(true);
    underlineAct->setIcon(QIcon(QStringLiteral(":/icons/resources/icons/SVG/Outline/Text Formatting/Text Underline.svg")));
    QFont uFont = underlineAct->font(); uFont.setUnderline(true); underlineAct->setFont(uFont);
    connect(underlineAct, &QAction::triggered, this, &RichTextEditor::onUnderline);

    m_toolbar->addSeparator();

    // Alignment
    QAction *alignLeft = m_toolbar->addAction("L");
    connect(alignLeft, &QAction::triggered, this, &RichTextEditor::onAlignLeft);

    QAction *alignCenter = m_toolbar->addAction("C");
    connect(alignCenter, &QAction::triggered, this, &RichTextEditor::onAlignCenter);

    QAction *alignRight = m_toolbar->addAction("R");
    connect(alignRight, &QAction::triggered, this, &RichTextEditor::onAlignRight);

    QAction *alignJustify = m_toolbar->addAction("J");
    connect(alignJustify, &QAction::triggered, this, &RichTextEditor::onAlignJustify);

    m_toolbar->addSeparator();

    // Lists
    QAction *bulletAct = m_toolbar->addAction("Bullets");
    connect(bulletAct, &QAction::triggered, this, &RichTextEditor::onBulletList);

    QAction *numAct = m_toolbar->addAction("1. List");
    connect(numAct, &QAction::triggered, this, &RichTextEditor::onNumberedList);

    m_toolbar->addSeparator();

    // Indent / Outdent
    QAction *indentAct = m_toolbar->addAction("Indent");
    connect(indentAct, &QAction::triggered, this, &RichTextEditor::onIndent);

    QAction *outdentAct = m_toolbar->addAction("Outdent");
    connect(outdentAct, &QAction::triggered, this, &RichTextEditor::onOutdent);

    m_toolbar->addSeparator();

    // Insert image
    QAction *imgAct = m_toolbar->addAction("Img");
    connect(imgAct, &QAction::triggered, this, &RichTextEditor::onInsertImage);

    // Insert table
    QAction *tableAct = m_toolbar->addAction("Tbl");
    connect(tableAct, &QAction::triggered, this, &RichTextEditor::onInsertTable);

    // Signature button
    m_signatureButton = new QToolButton();
    m_signatureButton->setText("Signature");
    m_signatureButton->setToolButtonStyle(Qt::ToolButtonTextOnly);
    m_signatureButton->setPopupMode(QToolButton::MenuButtonPopup);
    m_signatureMenu = new QMenu(m_signatureButton);
    m_signatureButton->setMenu(m_signatureMenu);
    m_signatureButton->setStyleSheet(
        "QToolButton { background: #f5f5f7; border: 1px solid #d1d1d6; border-radius: 3px; padding: 4px 6px; }\n"
        "QToolButton:hover { background: #e0e0e0; }\n"
        "QToolButton::menu-button { border-left: 1px solid rgba(0,0,0,0.1); width: 12px; }\n"
    );
    connect(m_signatureButton, &QToolButton::clicked, this, &RichTextEditor::signatureClicked);
    m_toolbar->addWidget(m_signatureButton);
    QAction *editSigAct = m_signatureMenu->addAction(tr("Editar firmas"));
    connect(editSigAct, &QAction::triggered, this, &RichTextEditor::signatureEditRequested);

    m_toolbar->addSeparator();

    layout->addWidget(m_toolbar);
}

void RichTextEditor::onBold() {
    QTextCharFormat fmt;
    fmt.setFontWeight(textCursor().charFormat().fontWeight() == QFont::Bold ? QFont::Normal : QFont::Bold);
    mergeCurrentCharFormat(fmt);
    setFocus();
}

void RichTextEditor::onItalic() {
    QTextCharFormat fmt;
    fmt.setFontItalic(!textCursor().charFormat().fontItalic());
    mergeCurrentCharFormat(fmt);
    setFocus();
}

void RichTextEditor::onUnderline() {
    QTextCharFormat fmt;
    fmt.setFontUnderline(!textCursor().charFormat().fontUnderline());
    mergeCurrentCharFormat(fmt);
    setFocus();
}

void RichTextEditor::onBulletList() {
    QTextCursor cursor = textCursor();
    QTextList *list = cursor.currentList();
    if (list && list->format().style() == QTextListFormat::ListDisc) {
        // Remove list
        QTextBlockFormat bfmt;
        bfmt.setIndent(0);
        cursor.setBlockFormat(bfmt);
        list->remove(cursor.block());
    } else {
        QTextListFormat listFormat;
        listFormat.setStyle(QTextListFormat::ListDisc);
        cursor.createList(listFormat);
    }
}

void RichTextEditor::onNumberedList() {
    QTextCursor cursor = textCursor();
    QTextList *list = cursor.currentList();
    if (list && list->format().style() == QTextListFormat::ListDecimal) {
        QTextBlockFormat bfmt;
        bfmt.setIndent(0);
        cursor.setBlockFormat(bfmt);
        list->remove(cursor.block());
    } else {
        QTextListFormat listFormat;
        listFormat.setStyle(QTextListFormat::ListDecimal);
        cursor.createList(listFormat);
    }
}

void RichTextEditor::onIndent() {
    QTextCursor cursor = textCursor();
    QTextBlockFormat bfmt = cursor.blockFormat();
    bfmt.setIndent(bfmt.indent() + 1);
    cursor.setBlockFormat(bfmt);
}

void RichTextEditor::onOutdent() {
    QTextCursor cursor = textCursor();
    QTextBlockFormat bfmt = cursor.blockFormat();
    int indent = bfmt.indent();
    if (indent > 0) {
        bfmt.setIndent(indent - 1);
        cursor.setBlockFormat(bfmt);
    }
}

void RichTextEditor::onAlignLeft() {
    QTextCursor cursor = textCursor();
    QTextBlockFormat bfmt = cursor.blockFormat();
    bfmt.setAlignment(Qt::AlignLeft);
    cursor.setBlockFormat(bfmt);
}

void RichTextEditor::onAlignCenter() {
    QTextCursor cursor = textCursor();
    QTextBlockFormat bfmt = cursor.blockFormat();
    bfmt.setAlignment(Qt::AlignCenter);
    cursor.setBlockFormat(bfmt);
}

void RichTextEditor::onAlignRight() {
    QTextCursor cursor = textCursor();
    QTextBlockFormat bfmt = cursor.blockFormat();
    bfmt.setAlignment(Qt::AlignRight);
    cursor.setBlockFormat(bfmt);
}

void RichTextEditor::onAlignJustify() {
    QTextCursor cursor = textCursor();
    QTextBlockFormat bfmt = cursor.blockFormat();
    bfmt.setAlignment(Qt::AlignJustify);
    cursor.setBlockFormat(bfmt);
}

void RichTextEditor::onFontChanged(const QFont &font) {
    QTextCharFormat fmt;
    fmt.setFontFamilies({font.family()});
    mergeCurrentCharFormat(fmt);
}

void RichTextEditor::onFontSizeChanged(int size) {
    QTextCharFormat fmt;
    fmt.setFontPointSize(size);
    mergeCurrentCharFormat(fmt);
}

void RichTextEditor::onInsertImage() {
    QString filePath = QFileDialog::getOpenFileName(this, "Insert Image", QString(), "Images (*.png *.jpg *.jpeg *.gif *.bmp)");
    if (filePath.isEmpty()) return;
    QTextCursor cursor = textCursor();
    QTextImageFormat imgFmt;
    imgFmt.setName(filePath);
    // Scale down if too large
    QPixmap pm(filePath);
    if (pm.width() > 600) {
        imgFmt.setWidth(600);
        imgFmt.setHeight(pm.height() * 600 / pm.width());
    }
    cursor.insertImage(imgFmt);
}

void RichTextEditor::onInsertTable() {
    bool ok;
    int rows = QInputDialog::getInt(this, "Table Rows", "Rows:", 3, 1, 50, 1, &ok);
    if (!ok) return;
    int cols = QInputDialog::getInt(this, "Table Columns", "Columns:", 3, 1, 20, 1, &ok);
    if (!ok) return;

    QTextCursor cursor = textCursor();
    QTextTableFormat tableFmt;
    tableFmt.setBorder(1);
    tableFmt.setBorderStyle(QTextFrameFormat::BorderStyle_Solid);
    tableFmt.setCellPadding(4);
    tableFmt.setCellSpacing(0);
    tableFmt.setWidth(QTextLength(QTextLength::PercentageLength, 100));
    cursor.insertTable(rows, cols, tableFmt);
}

/* ===================== Mouse events for image/table resizing ===================== */
void RichTextEditor::mousePressEvent(QMouseEvent *event) {
    if (event->button() == Qt::LeftButton) {
        QPoint pos = event->pos();
        QTextCursor cursor = cursorForPosition(pos);
        // Image
        if (cursor.charFormat().isImageFormat()) {
            qDebug() << "Mouse press on image";
            m_resizingImage = true;
            m_resizeStartPos = pos;
            QTextImageFormat imgFormat = cursor.charFormat().toImageFormat();
            m_imageStartSize = QSize(imgFormat.width(), imgFormat.height());
            if (m_imageStartSize.isEmpty()) {
                QPixmap pm(imgFormat.name());
                if (!pm.isNull())
                    m_imageStartSize = pm.size();
            }
            // Change cursor to indicate resizing
            setCursor(Qt::SizeAllCursor);
            event->accept();
            return;
        }
        // Table
        QTextTable *table = cursor.currentTable();
        if (table) {
            qDebug() << "Mouse press on table";
            m_resizingTable = true;
            m_tableStartPos = pos;
            m_currentTable = table;
            QTextTableFormat fmt = table->format();
            m_tableStartSize = QSizeF(fmt.width().rawValue(), fmt.height().rawValue());
            setCursor(Qt::SizeAllCursor);
            event->accept();
            return;
        }
    }
    QTextEdit::mousePressEvent(event);
}

void RichTextEditor::mouseMoveEvent(QMouseEvent *event) {
    if (m_resizingImage) {
        qDebug() << "Mouse move resizing image";
        QPoint delta = event->pos() - m_resizeStartPos;
        int newWidth = qMax(20, m_imageStartSize.width() + delta.x());
        int newHeight = qMax(20, m_imageStartSize.height() + delta.y());
        QTextCursor cursor = cursorForPosition(m_resizeStartPos);
        if (cursor.charFormat().isImageFormat()) {
            QTextImageFormat fmt = cursor.charFormat().toImageFormat();
            fmt.setWidth(newWidth);
            fmt.setHeight(newHeight);
            cursor.mergeCharFormat(fmt);
            setTextCursor(cursor);
        }
        event->accept();
        return;
    }
    if (m_resizingTable) {
        qDebug() << "Mouse move resizing table";
        QPoint delta = event->pos() - m_tableStartPos;
        qreal newWidth = qMax(10.0, m_tableStartSize.width() + delta.x());
        qreal newHeight = qMax(10.0, m_tableStartSize.height() + delta.y());
        QTextTableFormat fmt = m_currentTable->format();
        fmt.setWidth(QTextLength(QTextLength::FixedLength, newWidth));
        fmt.setHeight(QTextLength(QTextLength::FixedLength, newHeight));
        m_currentTable->setFormat(fmt);
        event->accept();
        return;
    }
    QTextEdit::mouseMoveEvent(event);
}

void RichTextEditor::mouseReleaseEvent(QMouseEvent *event) {
    if (event->button() == Qt::LeftButton) {
        if (m_resizingImage) {
            qDebug() << "Mouse release image resize";
            m_resizingImage = false;
            setCursor(Qt::ArrowCursor);
            event->accept();
            return;
        }
        if (m_resizingTable) {
            qDebug() << "Mouse release table resize";
            m_resizingTable = false;
            setCursor(Qt::ArrowCursor);
            event->accept();
            return;
        }
    }
    QTextEdit::mouseReleaseEvent(event);
}

void RichTextEditor::contextMenuEvent(QContextMenuEvent *event) {
    QPoint pos = event->pos();
    QTextCursor cursor = cursorForPosition(pos);
    QTextTable *table = cursor.currentTable();
    if (table) {
        showTableContextMenu(pos);
        event->accept();
        return;
    }
    QTextEdit::contextMenuEvent(event);
}

/* ===================== Helper functions ===================== */
void RichTextEditor::showTableContextMenu(const QPoint &pos) {
    if (!m_tableContextMenu) {
        m_tableContextMenu = new QMenu(this);
        m_tableContextMenu->addAction(tr("Insert row above"), this, &RichTextEditor::addTableRow);
        m_tableContextMenu->addAction(tr("Insert row below"), this, &RichTextEditor::addTableRow);
        m_tableContextMenu->addAction(tr("Insert column left"), this, &RichTextEditor::addTableColumn);
        m_tableContextMenu->addAction(tr("Insert column right"), this, &RichTextEditor::addTableColumn);
        m_tableContextMenu->addSeparator();
        m_tableContextMenu->addAction(tr("Delete selected rows"), this, &RichTextEditor::removeTableRow);
        m_tableContextMenu->addAction(tr("Delete selected columns"), this, &RichTextEditor::removeTableColumn);
        m_tableContextMenu->addSeparator();
        m_tableContextMenu->addAction(tr("Border..."), this, &RichTextEditor::modifyTableBorder);
    }
    m_tableContextMenu->exec(mapToGlobal(pos));
}

void RichTextEditor::addTableRow() {
    if (!m_currentTable) return;
    QTextCursor cursor = textCursor();
    QTextTable *table = cursor.currentTable();
    if (!table) return;
    QTextTableCell cell = table->cellAt(cursor.position());
    int row = cell.row();
    table->insertRows(row, 1);
}

void RichTextEditor::removeTableRow() {
    if (!m_currentTable) return;
    QTextCursor cursor = textCursor();
    QTextTable *table = cursor.currentTable();
    if (!table) return;
    QTextTableCell cell = table->cellAt(cursor.position());
    int row = cell.row();
    table->removeRows(row, 1);
}

void RichTextEditor::addTableColumn() {
    if (!m_currentTable) return;
    QTextCursor cursor = textCursor();
    QTextTable *table = cursor.currentTable();
    if (!table) return;
    QTextTableCell cell = table->cellAt(cursor.position());
    int col = cell.column();
    table->insertColumns(col, 1);
}

void RichTextEditor::removeTableColumn() {
    if (!m_currentTable) return;
    QTextCursor cursor = textCursor();
    QTextTable *table = cursor.currentTable();
    if (!table) return;
    QTextTableCell cell = table->cellAt(cursor.position());
    int col = cell.column();
    table->removeColumns(col, 1);
}

void RichTextEditor::modifyTableBorder() {
    if (!m_currentTable) return;
    bool ok;
    int border = QInputDialog::getInt(this, tr("Table Border"), tr("Border width (px):"), 
                                      m_currentTable->format().border(), 0, 20, 1, &ok);
    if (!ok) return;
    QTextTableFormat fmt = m_currentTable->format();
    fmt.setBorder(border);
    m_currentTable->setFormat(fmt);
}