#include "imagegallery.h"
#include <QMouseEvent>
#include <QFileInfo>
#include <QProcess>
#include <QDesktopServices>
#include <QUrl>
#include <QPainter>
#include <QApplication>
#include <QFrame>
#include <QHBoxLayout>
#include <QTimer>

// ImageThumbnail implementation
ImageThumbnail::ImageThumbnail(const QString &filePath, QWidget *parent)
    : QLabel(parent)
    , m_filePath(filePath)
{
    setFixedSize(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT);
    setAlignment(Qt::AlignCenter);
    setFrameStyle(QFrame::Panel | QFrame::Sunken);
    setLineWidth(2);
    setScaledContents(false);
    setCursor(Qt::PointingHandCursor);
    // We're removing tooltips as requested
    
    // Enable text wrapping and text interaction
    setWordWrap(true);
    setTextInteractionFlags(Qt::TextSelectableByMouse);
    
    // Set a minimum size policy
    setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
}

void ImageThumbnail::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        emit thumbnailClicked(m_filePath);
    }
    QLabel::mousePressEvent(event);
}

// ImageGallery implementation
ImageGallery::ImageGallery(QWidget *parent)
    : QWidget(parent)
    , m_dbManager(nullptr)
{
    // Create scroll area
    m_scrollArea = new QScrollArea(this);
    m_scrollArea->setWidgetResizable(true);
    m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // Prevent horizontal scrollbar
    m_scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
    
    // Create container widget for the grid layout
    m_containerWidget = new QWidget(m_scrollArea);
    
    // Make container expand to fill the available width
    m_containerWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding);
    
    // Create grid layout with minimal spacing
    m_gridLayout = new QGridLayout(m_containerWidget);
    m_gridLayout->setSpacing(THUMBNAIL_SPACING);
    m_gridLayout->setContentsMargins(THUMBNAIL_SPACING, THUMBNAIL_SPACING, THUMBNAIL_SPACING, THUMBNAIL_SPACING);
    
    // Initialize column count based on container width
    m_columnsCount = 4; // Default value, will be updated in updateGridLayout
    
    m_scrollArea->setWidget(m_containerWidget);
    
    // Create layout for the gallery widget
    QVBoxLayout *mainLayout = new QVBoxLayout(this);
    mainLayout->addWidget(m_scrollArea);
    setLayout(mainLayout);
    
    // No need to connect to container widget - we'll use resizeEvent instead
    
    // Initial layout update
    QTimer::singleShot(0, this, &ImageGallery::updateGridLayout);
    
    // Install event filter on viewport to catch resize events
    m_scrollArea->viewport()->installEventFilter(this);
    
    // We'll still keep a periodic check as backup
    QTimer *resizeTimer = new QTimer(this);
    connect(resizeTimer, &QTimer::timeout, this, &ImageGallery::handleContainerResized);
    resizeTimer->start(300); // Check every 300ms
}

ImageGallery::~ImageGallery()
{
    clearGallery();
}

void ImageGallery::setDatabaseManager(DatabaseManager *dbManager)
{
    m_dbManager = dbManager;
}

void ImageGallery::displayImages(const QList<DatabaseManager::ImageItem> &images)
{
    // Clear existing thumbnails
    clearGallery();
    
    // Update grid layout to ensure correct column count before adding images
    updateGridLayout();
    
    const int numImages = images.size();
    int row = 0, col = 0;
    
    for (int i = 0; i < numImages; ++i) {
        const auto &item = images[i];
        
        // Check if file exists before creating thumbnail
        QFileInfo fileInfo(item.filePath);
        if (!fileInfo.exists() || !fileInfo.isReadable()) {
            qDebug() << "Image file does not exist or is not readable:" << item.filePath;
            continue;  // Skip this image
        }
        
        // Create and add thumbnail
        QPixmap thumbnail = createThumbnail(item.filePath, THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT);
        ImageThumbnail *thumbnailLabel = new ImageThumbnail(item.filePath, this);
        thumbnailLabel->setPixmap(thumbnail);
        
        // Add filename overlay at the bottom of the thumbnail
        QFileInfo fileNameInfo(item.filePath);
        QString fileName = fileNameInfo.fileName();
        
        // Create overlay container with dark background
        QFrame* overlay = new QFrame(thumbnailLabel);
        overlay->setStyleSheet("background-color: rgba(0, 0, 0, 0.7);");
        overlay->setFixedHeight(20);
        overlay->setFixedWidth(THUMBNAIL_WIDTH);
        
        // Create label for the filename
        QLabel* fileNameLabel = new QLabel(fileName, overlay);
        fileNameLabel->setStyleSheet("color: white; background: transparent;");
        fileNameLabel->setAlignment(Qt::AlignCenter);
        fileNameLabel->setFixedWidth(THUMBNAIL_WIDTH - 10);
        
        // Layout for the overlay
        QHBoxLayout* overlayLayout = new QHBoxLayout(overlay);
        overlayLayout->setContentsMargins(5, 0, 5, 0);
        overlayLayout->addWidget(fileNameLabel);
        
        // Position the overlay at the bottom of the thumbnail
        overlay->move(0, THUMBNAIL_HEIGHT - overlay->height());
        
        // Connect the thumbnail click signal
        connect(thumbnailLabel, &ImageThumbnail::thumbnailClicked, 
                this, &ImageGallery::handleThumbnailClicked);
        
        // Add to grid
        m_gridLayout->addWidget(thumbnailLabel, row, col);
        m_thumbnails.append(thumbnailLabel);
        
        // Update row and column
        col++;
        if (col >= m_columnsCount) {
            col = 0;
            row++;
        }
    }
    
    // Display a message when no images are found
    if (m_thumbnails.isEmpty()) {
        // Create a special ImageThumbnail for the "no images" message
        ImageThumbnail *noImagesLabel = new ImageThumbnail("", this);
        noImagesLabel->setText("No images found matching your search criteria");
        noImagesLabel->setAlignment(Qt::AlignCenter);
        m_gridLayout->addWidget(noImagesLabel, 0, 0, 1, m_columnsCount);
        m_thumbnails.append(noImagesLabel);
    }
    
    // Add stretch to the bottom of the grid
    m_gridLayout->setRowStretch(row + 1, 1);
}

void ImageGallery::clearGallery()
{
    // Remove all thumbnails
    for (auto thumbnail : m_thumbnails) {
        m_gridLayout->removeWidget(thumbnail);
        disconnect(thumbnail, nullptr, this, nullptr);
        delete thumbnail;
    }
    
    m_thumbnails.clear();
}

void ImageGallery::handleSearchTextChanged(const QString &searchText)
{
    if (m_dbManager) {
        QList<DatabaseManager::ImageItem> images = m_dbManager->searchImages(searchText);
        displayImages(images);
    }
}

void ImageGallery::handleThumbnailClicked(const QString &filePath)
{
    // Show a wait cursor while attempting to open the file
    QApplication::setOverrideCursor(Qt::WaitCursor);
    
    // Check if file exists
    QFileInfo fileInfo(filePath);
    if (fileInfo.exists() && fileInfo.isFile()) {
        try {
            // Use QDesktopServices to open the file with the default application
            bool success = QDesktopServices::openUrl(QUrl::fromLocalFile(filePath));
            if (!success) {
                qDebug() << "Failed to open file with default application:" << filePath;
            }
        } catch (const std::exception &e) {
            qDebug() << "Exception occurred while opening file:" << e.what();
        }
    } else {
        qDebug() << "File does not exist:" << filePath;
    }
    
    // Restore cursor
    QApplication::restoreOverrideCursor();
}

QPixmap ImageGallery::createThumbnail(const QString &filePath, int width, int height)
{
    // Verify file exists before attempting to load
    QFileInfo fileInfo(filePath);
    if (!fileInfo.exists() || !fileInfo.isReadable()) {
        qDebug() << "Image file does not exist or is not readable:" << filePath;
        return createPlaceholderThumbnail(width, height, "File not found");
    }
    
    // Try to load the image
    QPixmap pixmap(filePath);
    
    // If loading failed, create a placeholder
    if (pixmap.isNull()) {
        qDebug() << "Failed to load image:" << filePath;
        return createPlaceholderThumbnail(width, height, "Failed to load");
    }
    
    // Scale pixmap while maintaining aspect ratio
    return pixmap.scaled(width, height, Qt::KeepAspectRatio, Qt::SmoothTransformation);
}

void ImageGallery::resizeEvent(QResizeEvent *event)
{
    QWidget::resizeEvent(event);
    
    // Trigger grid layout update when gallery is resized
    QTimer::singleShot(0, this, &ImageGallery::updateGridLayout);
    
    // Ensure the container widget fills the viewport width
    if (m_scrollArea && m_containerWidget) {
        int viewportWidth = m_scrollArea->viewport()->width();
        m_containerWidget->setMinimumWidth(viewportWidth);
        
        // Immediately update layout to avoid visual glitches during resize
        m_gridLayout->activate();
        m_containerWidget->updateGeometry();
    }
}

// Event filter to catch viewport resize events
bool ImageGallery::eventFilter(QObject *watched, QEvent *event)
{
    // Check if this is a resize event on the viewport
    if (watched == m_scrollArea->viewport() && event->type() == QEvent::Resize) {
        // Update the grid layout
        updateGridLayout();
        return false; // Allow event to propagate
    }
    
    // Pass unhandled events to parent
    return QWidget::eventFilter(watched, event);
}

void ImageGallery::handleContainerResized()
{
    // This will be called periodically to check if container size changed
    static int lastWidth = -1;
    int currentWidth = m_containerWidget->width();
    
    if (currentWidth > 0 && currentWidth != lastWidth) {
        lastWidth = currentWidth;
        updateGridLayout();
    }
}

void ImageGallery::updateGridLayout()
{
    // Get the viewport width to determine available space
    int viewportWidth = m_scrollArea->viewport()->width();
    if (viewportWidth <= 0) {
        return; // Can't determine width yet
    }
    
    // Force container width to match the viewport
    m_containerWidget->setMinimumWidth(viewportWidth);
    
    // Account for left and right margins in the grid layout
    int availableWidth = viewportWidth - (m_gridLayout->contentsMargins().left() + m_gridLayout->contentsMargins().right());
    
    // Calculate how many thumbnails can fit, accounting for spacing between them
    int effectiveThumbnailWidth = THUMBNAIL_WIDTH + THUMBNAIL_SPACING;
    
    // Calculate column count, allowing even very narrow views to show at least 1 column
    int newColumnCount = std::max(1, availableWidth / (THUMBNAIL_WIDTH + 2 * THUMBNAIL_SPACING));
    
    // Only update if column count changes
    if (newColumnCount != m_columnsCount) {
        m_columnsCount = newColumnCount;
        
        // If we have thumbnails, rearrange them in the grid
        if (!m_thumbnails.isEmpty()) {
            // We need to readjust all the thumbnails to the new grid layout
            // First remove all widgets from the grid
            for (auto thumbnail : m_thumbnails) {
                m_gridLayout->removeWidget(thumbnail);
            }
            
            // Then add them back in the new arrangement
            int row = 0, col = 0;
            for (auto thumbnail : m_thumbnails) {
                m_gridLayout->addWidget(thumbnail, row, col);
                col++;
                if (col >= m_columnsCount) {
                    col = 0;
                    row++;
                }
            }
    
            // Force layout update
            m_gridLayout->invalidate();
            m_containerWidget->adjustSize();
            m_containerWidget->updateGeometry();
            
            // Handle single column mode specially
            if (m_columnsCount == 1) {
                // Center the thumbnails in the viewport
                int centeringMargin = (viewportWidth - THUMBNAIL_WIDTH) / 2;
                centeringMargin = std::max(THUMBNAIL_SPACING, centeringMargin);
                m_gridLayout->setContentsMargins(centeringMargin, THUMBNAIL_SPACING, centeringMargin, THUMBNAIL_SPACING);
                
                // Let all thumbnails expand to fill available width in single column mode
                for (auto thumbnail : m_thumbnails) {
                    thumbnail->setMaximumWidth(THUMBNAIL_WIDTH);
                    thumbnail->setAlignment(Qt::AlignCenter);
                }
            } else {
                // For multi-column, use minimal margins
                m_gridLayout->setContentsMargins(THUMBNAIL_SPACING, THUMBNAIL_SPACING, THUMBNAIL_SPACING, THUMBNAIL_SPACING);
                
                // Reset thumbnail constraints
                for (auto thumbnail : m_thumbnails) {
                    thumbnail->setMaximumWidth(QWIDGETSIZE_MAX);
                }
                
                // For multi-column, let the container fill the viewport
                m_containerWidget->setMinimumWidth(viewportWidth);
            }
            
            // Update the layout again after a short delay to handle edge cases
            QTimer::singleShot(10, this, [this](){
                m_gridLayout->update();
                m_containerWidget->update();
            });
        }
    }
}

QPixmap ImageGallery::createPlaceholderThumbnail(int width, int height, const QString &message)
{
    // Create a placeholder image with text
    QPixmap placeholder(width, height);
    placeholder.fill(Qt::lightGray);
    
    // Draw some text on the placeholder
    QPainter painter(&placeholder);
    painter.setPen(Qt::darkGray);
    
    // Use a nice font
    QFont font = painter.font();
    font.setPointSize(12);
    font.setBold(true);
    painter.setFont(font);
    
    // Draw the text centered in the pixmap
    painter.drawText(placeholder.rect(), Qt::AlignCenter, message);
    
    // Add a border
    painter.setPen(QPen(Qt::darkGray, 2));
    painter.drawRect(1, 1, width-2, height-2);
    
    return placeholder;
}