#include "previewpdfwidget.h"
#include "../controller/maincontroller.h"
#include "../controller/pdfcontroller.h"
#include "../model/perechentablemodel.h"
#include "../model/specificationpcbtablemodel.h"
#include "../model/specificationtablemodel.h"
#include "../model/vedomosttablemodel.h"
#include "../model/titleinscriptionsmodel.h"
#include "../model/projectparamtablemodel.h"
#include <QApplication>
#include <QScreen>
#include <QDebug> // Added for qDebug

// Константы
const int PreviewPdfWidget::ZOOM_LEVELS[] = {25, 50, 75, 100, 125, 150, 200};
const QStringList PreviewPdfWidget::DOCUMENT_TYPES = {"Перечень элементов", "Спецификация PCB", "Спецификация", "Ведомость покупных изделий"};

// Дополнительные константы для мелкого масштабирования
const int PreviewPdfWidget::FINE_ZOOM_STEP = 5; // Шаг для Ctrl+колесико (5%)
const int PreviewPdfWidget::MIN_ZOOM = 10;      // Минимальный масштаб 10%
const int PreviewPdfWidget::MAX_ZOOM = 400;     // Максимальный масштаб 400%

// Реализация ZoomableScrollArea
ZoomableScrollArea::ZoomableScrollArea(QWidget *parent)
    : QScrollArea(parent)
{
}

void ZoomableScrollArea::wheelEvent(QWheelEvent *event)
{
    // Проверяем, нажат ли Ctrl
    if (event->modifiers() & Qt::ControlModifier) {
        // Отправляем сигнал для масштабирования
        emit zoomRequested(event->angleDelta().y());
        event->accept();
    } else {
        // Если Ctrl не нажат, используем стандартную прокрутку
        QScrollArea::wheelEvent(event);
    }
}

PreviewPdfWidget::PreviewPdfWidget(QWidget *parent)
    : QWidget{parent}
    , m_mainController(nullptr)
    , m_pdfController(nullptr)
    , m_currentPage(0)
    , m_currentZoom(100)
    , m_currentDocumentType("Перечень элементов")
{
    setUp();    
}

void PreviewPdfWidget::setUp(){
    setWidgets();
    setUpLayout();
    setUpConnections();
}

void PreviewPdfWidget::setWidgets(){
    // Создаем элементы управления
    m_documentTypeCombo = new QComboBox(this);
    m_documentTypeCombo->addItems(DOCUMENT_TYPES);
    
    m_zoomCombo = new QComboBox(this);
    for (int zoom : ZOOM_LEVELS) {
        m_zoomCombo->addItem(QString("%1%").arg(zoom), zoom);
    }
    m_zoomCombo->setCurrentText("100%");
    
    m_pageCombo = new QComboBox(this);
    
    m_prevPageBtn = new QPushButton("←", this);
    m_nextPageBtn = new QPushButton("→", this);
    m_refreshBtn = new QPushButton("Обновить", this);
    m_pageInfoLabel = new QLabel("Страница 1 из 1", this);
    
    // Создаем область прокрутки для страниц
    m_scrollArea = new ZoomableScrollArea(this);
    m_scrollArea->setWidgetResizable(true);
    m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
    m_scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
    
    // Создаем контейнер для страниц
    m_pagesContainer = new QFrame(this);
    m_pagesLayout = new QVBoxLayout(m_pagesContainer);
    m_pagesLayout->setAlignment(Qt::AlignCenter);
    m_pagesLayout->setSpacing(20);
    m_pagesLayout->setContentsMargins(20, 20, 20, 20);
    
    m_scrollArea->setWidget(m_pagesContainer);
}

void PreviewPdfWidget::setUpLayout(){
    m_mainLayout = new QVBoxLayout(this);
    m_controlsLayout = new QHBoxLayout();
    
    // Настройка стилей
    this->setStyleSheet("background-color: #f0f0f0; border: 1px solid #ccc;");
    this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    
    // Добавляем элементы управления
    m_controlsLayout->addWidget(new QLabel("Тип документа:"));
    m_controlsLayout->addWidget(m_documentTypeCombo);
    m_controlsLayout->addSpacing(20);
    
    m_controlsLayout->addWidget(new QLabel("Масштаб:"));
    m_controlsLayout->addWidget(m_zoomCombo);
    m_controlsLayout->addSpacing(20);
    
    m_controlsLayout->addWidget(new QLabel("Страница:"));
    m_controlsLayout->addWidget(m_prevPageBtn);
    m_controlsLayout->addWidget(m_pageCombo);
    m_controlsLayout->addWidget(m_nextPageBtn);
    m_controlsLayout->addWidget(m_pageInfoLabel);
    
    m_controlsLayout->addSpacing(20);
    m_controlsLayout->addWidget(m_refreshBtn);
    
    m_controlsLayout->addStretch();
    
    // Добавляем все в основной layout
    m_mainLayout->addLayout(m_controlsLayout);
    m_mainLayout->addWidget(m_scrollArea);
    
    m_mainLayout->setContentsMargins(10, 10, 10, 10);
    m_mainLayout->setSpacing(10);
}

void PreviewPdfWidget::setUpConnections(){
    connect(m_documentTypeCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
            this, [this](int index) {
                if (index >= 0 && index < DOCUMENT_TYPES.size()) {
                    onDocumentTypeChanged(DOCUMENT_TYPES[index]);
                }
            });
    connect(m_zoomCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
            this, &PreviewPdfWidget::onZoomChanged);
    connect(m_pageCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
            this, &PreviewPdfWidget::onPageChanged);
    connect(m_prevPageBtn, &QPushButton::clicked, [this]() {
        if (m_currentPage > 0) {
            m_currentPage = m_currentPage - 1;
            m_pageCombo->setCurrentIndex(m_currentPage);
            renderPage(m_currentPage);
        }
    });
    connect(m_nextPageBtn, &QPushButton::clicked, [this]() {
        if (m_currentPage < m_pagesInfo.size() - 1) {
            m_currentPage = m_currentPage + 1;
            m_pageCombo->setCurrentIndex(m_currentPage);
            renderPage(m_currentPage);
        }
    });
    connect(m_refreshBtn, &QPushButton::clicked, this, &PreviewPdfWidget::updatePreview);
    
    // Подключаем сигнал масштабирования от ZoomableScrollArea
    connect(m_scrollArea, &ZoomableScrollArea::zoomRequested,
            this, [this](int delta) {
                // Определяем направление масштабирования
                int zoomChange = (delta > 0) ? FINE_ZOOM_STEP : -FINE_ZOOM_STEP;
                
                // Вычисляем новый масштаб
                int newZoom = m_currentZoom + zoomChange;
                
                // Ограничиваем масштаб
                newZoom = qBound(MIN_ZOOM, newZoom, MAX_ZOOM);
                
                // Применяем новый масштаб
                setZoom(newZoom);
            });
}

void PreviewPdfWidget::setMainController(MainController *mainController)
{
    m_mainController = mainController;
    
    // Получаем PDFController из MainController
    if (m_mainController) {
        m_pdfController = m_mainController->pdfController();
        qDebug() << "PreviewPdfWidget::setMainController: PDFController получен из MainController:" << m_pdfController;
    } else {
        m_pdfController = nullptr;
    }
    
    // Обновляем превью при первой установке контроллера
    updatePreview();
}

void PreviewPdfWidget::setPdfController(PDFController *pdfController)
{
    // Этот метод больше не нужен, так как PDFController получается из MainController
    qDebug() << "PreviewPdfWidget::setPdfController: Метод устарел, используйте setMainController";
}

void PreviewPdfWidget::updatePreview()
{
    qDebug() << "PreviewPdfWidget::updatePreview: Начинаем обновление предварительного просмотра";
    qDebug() << "PreviewPdfWidget::updatePreview: m_mainController =" << m_mainController;
    qDebug() << "PreviewPdfWidget::updatePreview: m_pdfController =" << m_pdfController;
    
    if (!m_mainController || !m_pdfController) {
        qDebug() << "PreviewPdfWidget::updatePreview: Контроллеры не установлены";
        return;
    }
    
    // Проверяем данные в моделях
    if (m_mainController->perechenTableModel()) {
        qDebug() << "PreviewPdfWidget::updatePreview: Количество строк в перечне:" << m_mainController->perechenTableModel()->rowCount();
    }
    if (m_mainController->specificationPCBTableModel()) {
        qDebug() << "PreviewPdfWidget::updatePreview: Количество строк в спецификации PCB:" << m_mainController->specificationPCBTableModel()->rowCount();
    }
    if (m_mainController->specificationTableModel()) {
        qDebug() << "PreviewPdfWidget::updatePreview: Количество строк в спецификации:" << m_mainController->specificationTableModel()->rowCount();
    }
    if (m_mainController->vedomostTableModel()) {
        qDebug() << "PreviewPdfWidget::updatePreview: Количество строк в ведомости покупных изделий:" << m_mainController->vedomostTableModel()->rowCount();
    }
    
    // Сохраняем текущую страницу перед обновлением
    int savedPage = m_currentPage;
    qDebug() << "PreviewPdfWidget::updatePreview: Сохраняем текущую страницу:" << savedPage;
    
    generatePages();
    updatePageNavigation();
    
    // Восстанавливаем сохраненную страницу, если она все еще валидна
    if (!m_pagesInfo.isEmpty()) {
        // Если сохраненная страница больше не существует, используем последнюю доступную
        int pageToShow = savedPage;
        if (savedPage >= m_pagesInfo.size()) {
            pageToShow = m_pagesInfo.size() - 1;
            qDebug() << "PreviewPdfWidget::updatePreview: Сохраненная страница больше не существует, показываем последнюю:" << pageToShow;
        } else if (savedPage < 0) {
            pageToShow = 0;
            qDebug() << "PreviewPdfWidget::updatePreview: Сохраненная страница невалидна, показываем первую:" << pageToShow;
        } else {
            qDebug() << "PreviewPdfWidget::updatePreview: Восстанавливаем сохраненную страницу:" << pageToShow;
        }
        
        m_currentPage = pageToShow;
        renderPage(pageToShow);
        qDebug() << "PreviewPdfWidget::updatePreview: Предварительный просмотр обновлен, страниц:" << m_pagesInfo.size() << ", текущая страница:" << pageToShow;
    } else {
        qDebug() << "PreviewPdfWidget::updatePreview: Нет страниц для отображения";
    }
}

void PreviewPdfWidget::generatePages()
{
    qDebug() << "PreviewPdfWidget::generatePages: Начинаем генерацию страниц";
    
    m_pagesInfo.clear();
    m_pagePixmaps.clear();
    clearPages();
    
    if (!m_mainController || !m_pdfController) {
        qDebug() << "PreviewPdfWidget::generatePages: Контроллеры не установлены";
        return;
    }
    
    qDebug() << "PreviewPdfWidget::generatePages: Генерируем страницы для типа документа:" << m_currentDocumentType;
    
    // Получаем информацию о страницах в зависимости от типа документа
    if (m_currentDocumentType == "Перечень элементов") {
        qDebug() << "PreviewPdfWidget::generatePages: Вызываем getPerechenPagesInfo";
        m_pagesInfo = m_pdfController->getPerechenPagesInfo(m_mainController);
        qDebug() << "PreviewPdfWidget::generatePages: Получено страниц перечня:" << m_pagesInfo.size();
    } else if (m_currentDocumentType == "Спецификация PCB") {
        qDebug() << "PreviewPdfWidget::generatePages: Вызываем getSpecificationPcbPagesInfo";
        m_pagesInfo = m_pdfController->getSpecificationPcbPagesInfo(m_mainController);
        qDebug() << "PreviewPdfWidget::generatePages: Получено страниц спецификации PCB:" << m_pagesInfo.size();
    } else if (m_currentDocumentType == "Спецификация") {
        qDebug() << "PreviewPdfWidget::generatePages: Вызываем getSpecificationPagesInfo";
        m_pagesInfo = m_pdfController->getSpecificationPagesInfo(m_mainController);
        qDebug() << "PreviewPdfWidget::generatePages: Получено страниц спецификации:" << m_pagesInfo.size();
    } else if (m_currentDocumentType == "Ведомость покупных изделий") {
        qDebug() << "PreviewPdfWidget::generatePages: Вызываем getVedomostPagesInfo";
        m_pagesInfo = m_pdfController->getVedomostPagesInfo(m_mainController);
        qDebug() << "PreviewPdfWidget::generatePages: Получено страниц ведомости:" << m_pagesInfo.size();
    } else {
        qDebug() << "PreviewPdfWidget::generatePages: Неизвестный тип документа:" << m_currentDocumentType;
    }
    
    // Создаем pixmap'ы для каждой страницы
    for (int i = 0; i < m_pagesInfo.size(); ++i) {
        const PageInfo &pageInfo = m_pagesInfo[i];
        qDebug() << "PreviewPdfWidget::generatePages: Создаем pixmap для страницы" << (i + 1) << "из" << m_pagesInfo.size();
        QPixmap pagePixmap = createPagePixmap(pageInfo);
        m_pagePixmaps.append(pagePixmap);
    }
    
    qDebug() << "PreviewPdfWidget::generatePages: Создано pixmap'ов:" << m_pagePixmaps.size();
}

QPixmap PreviewPdfWidget::createPagePixmap(const PageInfo &pageInfo)
{
    qDebug() << "PreviewPdfWidget::createPagePixmap: Создаем pixmap для страницы" << pageInfo.pageNumber;
    
    // Определяем размер страницы в зависимости от типа документа
    int pageWidth, pageHeight;
    if (m_currentDocumentType == "Ведомость покупных изделий") {
        // Размер страницы А3 в альбомной ориентации в пикселях (фиксированный, не зависит от масштаба)
        // A3: 420mm x 297mm, в альбомной ориентации: 420mm x 297mm
        // При 96 DPI: 420 * 96 / 25.4 = 1587 пикселей, 297 * 96 / 25.4 = 1123 пикселей
        pageWidth = 1587;  // A3 width in pixels at 96 DPI (альбомная ориентация)
        pageHeight = 1123; // A3 height in pixels at 96 DPI (альбомная ориентация)
        qDebug() << "PreviewPdfWidget::createPagePixmap: Используем формат A3 в альбомной ориентации для ведомости";
    } else {
        // Размер страницы А4 в пикселях (фиксированный, не зависит от масштаба)
        pageWidth = 794;   // A4 width in pixels at 96 DPI
        pageHeight = 1123; // A4 height in pixels at 96 DPI
        qDebug() << "PreviewPdfWidget::createPagePixmap: Используем формат A4 для других документов";
    }
    
    qDebug() << "PreviewPdfWidget::createPagePixmap: Базовый размер страницы:" << pageWidth << "x" << pageHeight;
    
    // Создаем pixmap для страницы (фиксированный размер)
    QPixmap pixmap(pageWidth, pageHeight);
    pixmap.fill(Qt::white);
    
    QPainter painter(&pixmap);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setRenderHint(QPainter::TextAntialiasing);
    
    // Устанавливаем viewport для painter
    painter.setViewport(0, 0, pageWidth, pageHeight);
    
    // Рисуем страницу
    bool success = false;
    if (m_currentDocumentType == "Перечень элементов") {
        success = m_pdfController->drawPerechenPage(painter, pageInfo, m_mainController);
        qDebug() << "PreviewPdfWidget::createPagePixmap: Результат рисования перечня:" << success;
    } else if (m_currentDocumentType == "Спецификация PCB") {
        success = m_pdfController->drawSpecificationPcbPage(painter, pageInfo, m_mainController);
        qDebug() << "PreviewPdfWidget::createPagePixmap: Результат рисования спецификации PCB:" << success;
    } else if (m_currentDocumentType == "Спецификация") {
        success = m_pdfController->drawSpecificationPage(painter, pageInfo, m_mainController);
        qDebug() << "PreviewPdfWidget::createPagePixmap: Результат рисования спецификации:" << success;
    } else if (m_currentDocumentType == "Ведомость покупных изделий") {
        success = m_pdfController->drawVedomostPage(painter, pageInfo, m_mainController);
        qDebug() << "PreviewPdfWidget::createPagePixmap: Результат рисования ведомости:" << success;
    }
    
    painter.end();
    
    qDebug() << "PreviewPdfWidget::createPagePixmap: Pixmap создан, размер:" << pixmap.size();
    return pixmap;
}

void PreviewPdfWidget::renderPage(int pageIndex)
{
    qDebug() << "PreviewPdfWidget::renderPage: Отображаем страницу" << pageIndex;
    qDebug() << "PreviewPdfWidget::renderPage: Всего pixmap'ов:" << m_pagePixmaps.size();
    
    if (pageIndex < 0 || pageIndex >= m_pagePixmaps.size()) {
        qDebug() << "PreviewPdfWidget::renderPage: Неверный индекс страницы:" << pageIndex;
        return;
    }
    
    // Обновляем текущую страницу
    m_currentPage = pageIndex;
    
    // Очищаем контейнер страниц
    clearPages();
    
    // Создаем label для отображения страницы
    QLabel *pageLabel = new QLabel(m_pagesContainer);
    QPixmap originalPixmap = m_pagePixmaps[pageIndex];
    qDebug() << "PreviewPdfWidget::renderPage: Оригинальный размер pixmap:" << originalPixmap.size();
    
    // Применяем масштабирование через QTransform
    qreal scale = m_currentZoom / 100.0;
    QTransform transform;
    transform.scale(scale, scale);
    
    QPixmap scaledPixmap = originalPixmap.transformed(transform, Qt::SmoothTransformation);
    qDebug() << "PreviewPdfWidget::renderPage: Масштабированный размер pixmap:" << scaledPixmap.size() << "масштаб:" << m_currentZoom << "%";
    
    pageLabel->setPixmap(scaledPixmap);
    pageLabel->setAlignment(Qt::AlignCenter);
    pageLabel->setStyleSheet("border: 1px solid #ccc; background-color: white;");
    
    // Добавляем тень для страницы
    QFrame *pageFrame = new QFrame(m_pagesContainer);
    QVBoxLayout *frameLayout = new QVBoxLayout(pageFrame);
    frameLayout->addWidget(pageLabel);
    frameLayout->setContentsMargins(10, 10, 10, 10);
    pageFrame->setStyleSheet("QFrame { background-color: #e0e0e0; border-radius: 5px; }");
    
    m_pagesLayout->addWidget(pageFrame);
    
    // Обновляем информацию о странице
    if (pageIndex < m_pagesInfo.size()) {
        const PageInfo &pageInfo = m_pagesInfo[pageIndex];
        m_pageInfoLabel->setText(QString("Страница %1 из %2").arg(pageInfo.pageNumber).arg(pageInfo.totalPages));
        qDebug() << "PreviewPdfWidget::renderPage: Обновлена информация о странице:" << pageInfo.pageNumber << "из" << pageInfo.totalPages;
    }
    
    // Обновляем состояние кнопок навигации
    m_prevPageBtn->setEnabled(m_currentPage > 0);
    m_nextPageBtn->setEnabled(m_currentPage < m_pagesInfo.size() - 1);
    
    // Обновляем комбобокс страниц
    if (m_currentPage >= 0 && m_currentPage < m_pageCombo->count()) {
        m_pageCombo->blockSignals(true);
        m_pageCombo->setCurrentIndex(m_currentPage);
        m_pageCombo->blockSignals(false);
    }
    
    qDebug() << "PreviewPdfWidget::renderPage: Страница отображена успешно";
}

void PreviewPdfWidget::updatePageNavigation()
{
    m_pageCombo->clear();
    
    for (int i = 0; i < m_pagesInfo.size(); ++i) {
        const PageInfo &pageInfo = m_pagesInfo[i];
        m_pageCombo->addItem(QString("Страница %1").arg(pageInfo.pageNumber), i);
    }
    
    // Устанавливаем текущую страницу в комбобоксе
    if (m_currentPage >= 0 && m_currentPage < m_pageCombo->count()) {
        m_pageCombo->setCurrentIndex(m_currentPage);
    }
}

void PreviewPdfWidget::clearPages()
{
    // Удаляем все виджеты из layout
    QLayoutItem *item;
    while ((item = m_pagesLayout->takeAt(0)) != nullptr) {
        if (item->widget()) {
            item->widget()->deleteLater();
        }
        delete item;
    }
}

void PreviewPdfWidget::onDocumentTypeChanged(const QString &documentType)
{
    qDebug() << "PreviewPdfWidget::onDocumentTypeChanged: Изменен тип документа на:" << documentType;
    
    // Проверяем, поддерживается ли этот тип документа
    if (DOCUMENT_TYPES.contains(documentType)) {
        m_currentDocumentType = documentType;
        
        // Обновляем выбранный элемент в комбобоксе
        int index = DOCUMENT_TYPES.indexOf(documentType);
        if (index >= 0) {
            m_documentTypeCombo->setCurrentIndex(index);
        }
        
        updatePreview();
        emit documentTypeChanged(m_currentDocumentType);
    } else {
        qDebug() << "PreviewPdfWidget::onDocumentTypeChanged: Неподдерживаемый тип документа:" << documentType;
    }
}

void PreviewPdfWidget::onZoomChanged(int index)
{
    if (index >= 0 && index < m_zoomCombo->count()) {
        // Получаем значение из комбобокса (может быть как из стандартного списка, так и произвольное)
        QVariant data = m_zoomCombo->itemData(index);
        if (data.isValid()) {
            int newZoom = data.toInt();
            setZoom(newZoom);
        } else {
            // Если данных нет, пытаемся извлечь значение из текста
            QString text = m_zoomCombo->currentText();
            text.remove('%'); // Убираем символ процента
            bool ok;
            int newZoom = text.toInt(&ok);
            if (ok) {
                setZoom(newZoom);
            }
        }
    }
}

void PreviewPdfWidget::onPageChanged(int page)
{
    if (page >= 0 && page < m_pagesInfo.size()) {
        renderPage(page);
        emit pageChanged(page);
    }
}

void PreviewPdfWidget::setZoom(int zoom)
{
    // Ограничиваем масштаб
    zoom = qBound(MIN_ZOOM, zoom, MAX_ZOOM);
    
    // Обновляем текущий масштаб
    m_currentZoom = zoom;
    
    qDebug() << "PreviewPdfWidget::setZoom: Установлен масштаб:" << m_currentZoom << "%";
    
    // Временно блокируем сигналы комбобокса
    m_zoomCombo->blockSignals(true);
    
    // Очищаем произвольные значения из комбобокса (оставляем только стандартные)
    while (m_zoomCombo->count() > sizeof(ZOOM_LEVELS) / sizeof(ZOOM_LEVELS[0])) {
        m_zoomCombo->removeItem(0);
    }
    
    // Обновляем комбобокс масштаба
    // Сначала проверяем, есть ли точное значение в списке
    bool found = false;
    for (int i = 0; i < sizeof(ZOOM_LEVELS) / sizeof(ZOOM_LEVELS[0]); ++i) {
        if (ZOOM_LEVELS[i] == zoom) {
            m_zoomCombo->setCurrentIndex(i);
            found = true;
            break;
        }
    }
    
    // Если точного значения нет в списке, добавляем его как временный элемент
    if (!found) {
        // Добавляем текущее значение в начало списка
        m_zoomCombo->insertItem(0, QString("%1%").arg(zoom), zoom);
        m_zoomCombo->setCurrentIndex(0);
    }
    
    // Разблокируем сигналы
    m_zoomCombo->blockSignals(false);
    
    // Перерисовываем текущую страницу с новым масштабом
    if (m_currentPage >= 0 && m_currentPage < m_pagePixmaps.size()) {
        renderPage(m_currentPage);
    }
    
    emit zoomChanged(m_currentZoom);
}
