#include "documentprocessor.h"
#include "../model/perechentablemodel.h"
#include "../model/specificationpcbtablemodel.h"
#include "../model/specificationtablemodel.h"
#include "../model/vedomosttablemodel.h"
#include "../model/pcbmaterialmodel.h"
#include "columnsettingsdialog.h"
#include "cellsettingsdialog.h"
#include "../controller/maincontroller.h"
#include <QStandardItemModel>
#include <QHeaderView>

// Регистрируем метатипы для работы с QVariant
// Примечание: SpecificationPCBCellData уже объявлен в specificationpcbtablemodel.h
Q_DECLARE_METATYPE(PerechenCellData)
Q_DECLARE_METATYPE(SpecificationCellData)
Q_DECLARE_METATYPE(VedomostCellData)

#include <QFileDialog>
#include <QMessageBox>
#include <QDebug>
#include <QVector>
#include <QMenu>
#include <QList>
#include <algorithm>
#include <QApplication>
#include <QClipboard>
#include <QMimeData>

// DocumentProcessor
DocumentProcessor::DocumentProcessor(QObject *parent)
    : QObject(parent)
{
}

// PerechenProcessor
PerechenProcessor::PerechenProcessor(QObject *parent)
    : DocumentProcessor(parent)
    , m_controller(new PerechenTableController(this))
{
}

PerechenProcessor::~PerechenProcessor()
{
    // m_controller удалится автоматически, так как он является дочерним объектом
}

void PerechenProcessor::processComponents(const QList<ComponentModel*> &components)
{
    qDebug() << "PerechenProcessor::processComponents: Получено" << components.size() << "компонентов";
    // Передаем компоненты в контроллер
    if (m_controller) {
        m_controller->setComponents(components);
    }
}

void PerechenProcessor::processProjectParams(const QMap<QString, QString> &params)
{
    qDebug() << "PerechenProcessor::processProjectParams: Получено" << params.size() << "параметров";
    // Пока не используем параметры проекта для Perechen
}

QTableView* PerechenProcessor::createTableView()
{
    QTableView *tableView = new QTableView();
    if (m_controller) {
        // НЕ генерируем таблицу автоматически - только отображаем существующую модель
        qDebug() << "PerechenProcessor::createTableView: Отображаем существующую модель без генерации";
        
        tableView->setModel(m_controller->getTableModel());
        
        // Настройка растягивания столбцов для заполнения всего виджета
        QHeaderView *horizontalHeader = tableView->horizontalHeader();
        
        // Отключаем автоматическое изменение размера по содержимому
        horizontalHeader->setStretchLastSection(false);
        
        // Устанавливаем режимы для каждого столбца - все интерактивные (изменяемые по ширине)
        horizontalHeader->setSectionResizeMode(0, QHeaderView::Interactive); // Поз.обозначение
        horizontalHeader->setSectionResizeMode(1, QHeaderView::Interactive); // Наименование
        horizontalHeader->setSectionResizeMode(2, QHeaderView::Interactive); // Кол.
        horizontalHeader->setSectionResizeMode(3, QHeaderView::Interactive); // Примечание
        
        // Устанавливаем начальные размеры для столбцов
        horizontalHeader->resizeSection(0, 100); // Поз.обозначение - 100px
        horizontalHeader->resizeSection(1, 200); // Наименование - 200px
        horizontalHeader->resizeSection(2, 60);  // Кол. - 60px
        horizontalHeader->resizeSection(3, 150); // Примечание - 150px
        
        // Настройка вертикального заголовка
        QHeaderView *verticalHeader = tableView->verticalHeader();
        verticalHeader->setDefaultSectionSize(25); // Устанавливаем высоту строки
        verticalHeader->setSectionResizeMode(QHeaderView::Fixed);
        
        // Принудительно обновляем размеры столбцов
        //horizontalHeader->resizeSections();
        
        qDebug() << "PerechenProcessor::createTableView: Настроено растягивание столбцов";
    } else {
        // Если контроллер не установлен, создаем временную модель для корректной настройки заголовков
        QStandardItemModel *tempModel = new QStandardItemModel(tableView);
        QStringList headers;
        headers << "Поз.обозначение" << "Наименование" << "Кол." << "Примечание";
        tempModel->setHorizontalHeaderLabels(headers);
        
        // Устанавливаем временную модель для корректной настройки заголовков
        tableView->setModel(tempModel);
        
        // Настройка растягивания столбцов для заполнения всего виджета
        QHeaderView *horizontalHeader = tableView->horizontalHeader();
        
        // Отключаем автоматическое изменение размера по содержимому
        horizontalHeader->setStretchLastSection(false);
        
        // Устанавливаем режимы для каждого столбца - все интерактивные (изменяемые по ширине)
        horizontalHeader->setSectionResizeMode(0, QHeaderView::Interactive); // Поз.обозначение
        horizontalHeader->setSectionResizeMode(1, QHeaderView::Interactive); // Наименование
        horizontalHeader->setSectionResizeMode(2, QHeaderView::Interactive); // Кол.
        horizontalHeader->setSectionResizeMode(3, QHeaderView::Interactive); // Примечание
        
        // Устанавливаем начальные размеры для столбцов
        horizontalHeader->resizeSection(0, 100); // Поз.обозначение - 100px
        horizontalHeader->resizeSection(1, 200); // Наименование - 200px
        horizontalHeader->resizeSection(2, 60);  // Кол. - 60px
        horizontalHeader->resizeSection(3, 150); // Примечание - 150px
        
        // Настройка вертикального заголовка
        QHeaderView *verticalHeader = tableView->verticalHeader();
        verticalHeader->setDefaultSectionSize(25); // Устанавливаем высоту строки
        verticalHeader->setSectionResizeMode(QHeaderView::Fixed);
        
        qDebug() << "PerechenProcessor::createTableView: Создана временная модель для настройки заголовков";
    }
    return tableView;
}

void PerechenProcessor::setColumnMappings(const QStringList &mappings)
{
    if (m_controller) {
        m_controller->setColumnMappings(mappings);
    }
}

QStringList PerechenProcessor::getColumnMappings() const
{
    if (m_controller) {
        return m_controller->getColumnMappings();
    }
    return QStringList();
}

QStringList PerechenProcessor::getAvailableProperties() const
{
    if (m_controller) {
        return m_controller->getAvailableProperties();
    }
    return QStringList();
}

void PerechenProcessor::updateTable()
{
    qDebug() << "PerechenProcessor::updateTable: Обновляем таблицу по кнопке";
    if (m_controller) {
        m_controller->updateTableFromComponents();
    }
}

void PerechenProcessor::setController(PerechenTableController *controller)
{
    if (m_controller != controller) {
        qDebug() << "PerechenProcessor::setController: Заменяем контроллер";
        m_controller = controller;
    }
}

void PerechenProcessor::setModel(PerechenTableModel *model)
{
    if (m_controller && model) {
        qDebug() << "PerechenProcessor::setModel: Устанавливаем модель в контроллер";
        m_controller->setModel(model);
    }
}

// SpecificationProcessor
SpecificationProcessor::SpecificationProcessor(QObject *parent)
    : DocumentProcessor(parent)
    , m_controller(new SpecificationController(this))
{
}


void SpecificationProcessor::processComponents(const QList<ComponentModel*> &components)
{
    qDebug() << "SpecificationProcessor::processComponents: Получено" << components.size() << "компонентов";
    // Для спецификации материалов компоненты не используются
}

void SpecificationProcessor::processProjectParams(const QMap<QString, QString> &params)
{
    qDebug() << "SpecificationProcessor::processProjectParams: Получено" << params.size() << "параметров";
    // Пока не используем параметры проекта для Specification
}

QTableView* SpecificationProcessor::createTableView()
{
    QTableView *tableView = new QTableView();
    if (m_controller) {
        // НЕ генерируем таблицу автоматически - только отображаем существующую модель
        qDebug() << "SpecificationProcessor::createTableView: Отображаем существующую модель без генерации";
        
        tableView->setModel(m_controller->getTableModel());
        
        // Настройка растягивания столбцов для заполнения всего виджета
        QHeaderView *horizontalHeader = tableView->horizontalHeader();

        // Отключаем автоматическое изменение размера по содержимому
        horizontalHeader->setStretchLastSection(false);

        // Устанавливаем режимы для каждого столбца - все интерактивные (изменяемые по ширине)
        horizontalHeader->setSectionResizeMode(0, QHeaderView::Interactive); // Формат
        horizontalHeader->setSectionResizeMode(1, QHeaderView::Interactive); // Зона
        horizontalHeader->setSectionResizeMode(2, QHeaderView::Interactive); // Поз.
        horizontalHeader->setSectionResizeMode(3, QHeaderView::Interactive); // Обозначение
        horizontalHeader->setSectionResizeMode(4, QHeaderView::Interactive); // Наименование
        horizontalHeader->setSectionResizeMode(5, QHeaderView::Interactive); // Кол.
        horizontalHeader->setSectionResizeMode(6, QHeaderView::Interactive); // Примечание

        // Устанавливаем начальные размеры для столбцов
        horizontalHeader->resizeSection(0, 60);  // Формат - 60px
        horizontalHeader->resizeSection(1, 50);  // Зона - 50px
        horizontalHeader->resizeSection(2, 80);  // Поз. - 80px
        horizontalHeader->resizeSection(3, 150); // Обозначение - 150px
        horizontalHeader->resizeSection(4, 200); // Наименование - 200px
        horizontalHeader->resizeSection(5, 60);  // Кол. - 60px
        horizontalHeader->resizeSection(6, 150); // Примечание - 150px
        
        // Столбец 4 (Наименование) в режиме Stretch займет оставшееся пространство
        
        // Настройка вертикального заголовка
        QHeaderView *verticalHeader = tableView->verticalHeader();
        verticalHeader->setDefaultSectionSize(25); // Устанавливаем высоту строки
        verticalHeader->setSectionResizeMode(QHeaderView::Fixed);
        
        qDebug() << "SpecificationProcessor::createTableView: Настроено растягивание столбцов";
    } else {
        // Если контроллер не установлен, создаем временную модель для корректной настройки заголовков
        QStandardItemModel *tempModel = new QStandardItemModel(tableView);
        QStringList headers;
        headers << "Формат" << "Зона" << "Позиция" << "Обозначение" << "Наименование" << "Кол." << "Примечание";
        tempModel->setHorizontalHeaderLabels(headers);
        
        // Устанавливаем временную модель для корректной настройки заголовков
        tableView->setModel(tempModel);
        
        // Настройка растягивания столбцов для заполнения всего виджета
        QHeaderView *horizontalHeader = tableView->horizontalHeader();
        
        // Отключаем автоматическое изменение размера по содержимому
        horizontalHeader->setStretchLastSection(false);
        
        // Устанавливаем режимы для каждого столбца - все интерактивные (изменяемые по ширине)
        horizontalHeader->setSectionResizeMode(0, QHeaderView::Interactive); // Формат
        horizontalHeader->setSectionResizeMode(1, QHeaderView::Interactive); // Зона
        horizontalHeader->setSectionResizeMode(2, QHeaderView::Interactive); // Позиция
        horizontalHeader->setSectionResizeMode(3, QHeaderView::Interactive); // Обозначение
        horizontalHeader->setSectionResizeMode(4, QHeaderView::Interactive); // Наименование
        horizontalHeader->setSectionResizeMode(5, QHeaderView::Interactive); // Кол.
        horizontalHeader->setSectionResizeMode(6, QHeaderView::Interactive); // Примечание
        
        // Устанавливаем начальные размеры для столбцов
        horizontalHeader->resizeSection(0, 60);  // Формат - 60px
        horizontalHeader->resizeSection(1, 50);  // Зона - 50px
        horizontalHeader->resizeSection(2, 80);  // Позиция - 80px
        horizontalHeader->resizeSection(3, 120); // Обозначение - 120px
        horizontalHeader->resizeSection(4, 200); // Наименование - 200px
        horizontalHeader->resizeSection(5, 60);  // Кол. - 60px
        horizontalHeader->resizeSection(6, 150); // Примечание - 150px
        
        qDebug() << "SpecificationProcessor::createTableView: Создана временная модель для настройки заголовков";
    }
    
    return tableView;
}

void SpecificationProcessor::setColumnMappings(const QStringList &mappings)
{
    if (m_controller) {
        m_controller->setColumnMappings(mappings);
    }
}

QStringList SpecificationProcessor::getColumnMappings() const
{
    if (m_controller) {
        return m_controller->getColumnMappings();
    }
    return QStringList();
}

QStringList SpecificationProcessor::getAvailableProperties() const
{
    if (m_controller) {
        return m_controller->getAvailableProperties();
    }
    return QStringList();
}

void SpecificationProcessor::updateTable()
{
    if (m_controller) {
        m_controller->updateTableFromMaterials();
    }
}

void SpecificationProcessor::setController(SpecificationController *controller)
{
    if (m_controller != controller) {
        m_controller = controller;
        qDebug() << "SpecificationProcessor::setController: Контроллер заменен";
    }
}

void SpecificationProcessor::setModel(SpecificationTableModel *model)
{
    if (m_controller) {
        m_controller->setModel(model);
    }
}

// SpecificationPCBProcessor
SpecificationPCBProcessor::SpecificationPCBProcessor(QObject *parent)
    : DocumentProcessor(parent)
    , m_controller(nullptr)
{
}

SpecificationPCBProcessor::~SpecificationPCBProcessor()
{
    // m_controller удалится автоматически, так как он является дочерним объектом
}

void SpecificationPCBProcessor::processComponents(const QList<ComponentModel*> &components)
{
    qDebug() << "SpecificationPCBProcessor::processComponents: Получено" << components.size() << "компонентов";
    // Компоненты будут обрабатываться через главный контроллер
}

void SpecificationPCBProcessor::processProjectParams(const QMap<QString, QString> &params)
{
    qDebug() << "SpecificationPCBProcessor::processProjectParams: Получено" << params.size() << "параметров";
    // Пока не используем параметры проекта для SpecificationPCB
}

QTableView* SpecificationPCBProcessor::createTableView()
{
    QTableView *tableView = new QTableView();
    
    qDebug() << "SpecificationPCBProcessor::createTableView: Контроллер доступен:" << (m_controller ? "да" : "нет");
    if (m_controller) {
        qDebug() << "SpecificationPCBProcessor::createTableView: Модель в контроллере доступна:" << (m_controller->getTableModel() ? "да" : "нет");
        if (m_controller->getTableModel()) {
            qDebug() << "SpecificationPCBProcessor::createTableView: Количество строк в модели:" << m_controller->getTableModel()->rowCount();
            qDebug() << "SpecificationPCBProcessor::createTableView: Количество колонок в модели:" << m_controller->getTableModel()->columnCount();
        }
    }
    
    // Если контроллер доступен, используем его модель
    if (m_controller && m_controller->getTableModel()) {
        tableView->setModel(m_controller->getTableModel());
        qDebug() << "SpecificationPCBProcessor::createTableView: Используем модель из контроллера";
    } else {
        // Создаем временную модель с 7 столбцами для корректной настройки заголовков
        QStandardItemModel *tempModel = new QStandardItemModel(tableView);
        QStringList headers;
        headers << "Формат" << "Зона" << "Поз." << "Обозначение" << "Наименование" << "Кол." << "Примечание";
        tempModel->setHorizontalHeaderLabels(headers);
        
        // Устанавливаем временную модель для корректной настройки заголовков
        tableView->setModel(tempModel);
        qDebug() << "SpecificationPCBProcessor::createTableView: Создана временная модель для настройки заголовков";
    }
    
    // Настройка растягивания столбцов для заполнения всего виджета
    QHeaderView *horizontalHeader = tableView->horizontalHeader();
    
    // Отключаем автоматическое изменение размера по содержимому
    horizontalHeader->setStretchLastSection(false);
    
    // Устанавливаем режимы для каждого столбца - все интерактивные (изменяемые по ширине)
    horizontalHeader->setSectionResizeMode(0, QHeaderView::Interactive); // Формат
    horizontalHeader->setSectionResizeMode(1, QHeaderView::Interactive); // Зона
    horizontalHeader->setSectionResizeMode(2, QHeaderView::Interactive); // Поз.
    horizontalHeader->setSectionResizeMode(3, QHeaderView::Interactive); // Обозначение
    horizontalHeader->setSectionResizeMode(4, QHeaderView::Interactive); // Наименование
    horizontalHeader->setSectionResizeMode(5, QHeaderView::Interactive); // Кол.
    horizontalHeader->setSectionResizeMode(6, QHeaderView::Interactive); // Примечание
    
    // Устанавливаем начальные размеры для столбцов
    horizontalHeader->resizeSection(0, 60);  // Формат - 60px
    horizontalHeader->resizeSection(1, 50);  // Зона - 50px
    horizontalHeader->resizeSection(2, 80);  // Поз. - 80px
    horizontalHeader->resizeSection(3, 150); // Обозначение - 150px
    horizontalHeader->resizeSection(4, 200); // Наименование - 200px
    horizontalHeader->resizeSection(5, 60);  // Кол. - 60px
    horizontalHeader->resizeSection(6, 150); // Примечание - 150px
    
    // Настройка вертикального заголовка
    QHeaderView *verticalHeader = tableView->verticalHeader();
    verticalHeader->setDefaultSectionSize(25); // Устанавливаем высоту строки
    verticalHeader->setSectionResizeMode(QHeaderView::Fixed);
    
    qDebug() << "SpecificationPCBProcessor::createTableView: Настроено растягивание столбцов";
    return tableView;
}

void SpecificationPCBProcessor::setColumnMappings(const QStringList &mappings)
{
    qDebug() << "SpecificationPCBProcessor::setColumnMappings: Настройки колонок обновлены:" << mappings;
}

QStringList SpecificationPCBProcessor::getColumnMappings() const
{
    return QStringList();
}

QStringList SpecificationPCBProcessor::getAvailableProperties() const
{
    return QStringList();
}

void SpecificationPCBProcessor::updateTable()
{
    qDebug() << "SpecificationPCBProcessor::updateTable: Обновляем таблицу по кнопке";
}

void SpecificationPCBProcessor::setController(SpecificationPCBController *controller)
{
    qDebug() << "SpecificationPCBProcessor::setController: Устанавливаем контроллер";
    m_controller = controller;
    if (m_controller) {
        qDebug() << "SpecificationPCBProcessor::setController: Контроллер установлен";
    } else {
        qDebug() << "SpecificationPCBProcessor::setController: Контроллер сброшен";
    }
}

void SpecificationPCBProcessor::setModel(SpecificationPCBTableModel *model)
{
    qDebug() << "SpecificationPCBProcessor::setModel: Модель установлена в контроллер";
    if (m_controller) {
        m_controller->setModel(model);
        qDebug() << "SpecificationPCBProcessor::setModel: Модель передана в контроллер";
    } else {
        qDebug() << "SpecificationPCBProcessor::setModel: Контроллер недоступен";
    }
}

// VedomostProcessor
VedomostProcessor::VedomostProcessor(QObject *parent)
    : DocumentProcessor(parent)
    , m_controller(nullptr)
{
}

VedomostProcessor::~VedomostProcessor()
{
    // m_controller удалится автоматически, так как он является дочерним объектом
}

void VedomostProcessor::processComponents(const QList<ComponentModel*> &components)
{
    qDebug() << "VedomostProcessor::processComponents: Получено" << components.size() << "компонентов";
    
    // Только передаем компоненты в контроллер, но не генерируем таблицу
    if (m_controller) {
        m_controller->setComponents(components);
        qDebug() << "VedomostProcessor::processComponents: Компоненты переданы в контроллер";
    } else {
        qDebug() << "VedomostProcessor::processComponents: Контроллер недоступен";
    }
}

void VedomostProcessor::processProjectParams(const QMap<QString, QString> &params)
{
    qDebug() << "VedomostProcessor::processProjectParams: Получено" << params.size() << "параметров";
    // Пока не используем параметры проекта для Vedomost
}

QTableView* VedomostProcessor::createTableView()
{
    QTableView *tableView = new QTableView();
    
    qDebug() << "VedomostProcessor::createTableView: Контроллер доступен:" << (m_controller ? "да" : "нет");
    if (m_controller) {
        qDebug() << "VedomostProcessor::createTableView: Модель в контроллере доступна:" << (m_controller->getTableModel() ? "да" : "нет");
        if (m_controller->getTableModel()) {
            qDebug() << "VedomostProcessor::createTableView: Количество строк в модели:" << m_controller->getTableModel()->rowCount();
            qDebug() << "VedomostProcessor::createTableView: Количество колонок в модели:" << m_controller->getTableModel()->columnCount();
        }
    }
    
    // Если контроллер доступен, используем его модель
    if (m_controller && m_controller->getTableModel()) {
        tableView->setModel(m_controller->getTableModel());
        qDebug() << "VedomostProcessor::createTableView: Используем модель из контроллера";
    } else {
        // Создаем временную модель с 10 столбцами для корректной настройки заголовков
        QStandardItemModel *tempModel = new QStandardItemModel(tableView);
        QStringList headers;
        headers << "Наименование" << "Код продукции" << "Обозначение документа на поставку" 
                << "Поставщик" << "Куда входит (обозначение)" << "Количество на изделие" 
                << "Количество в комплекте" << "Количество на регулир" << "Количество всего" << "Примечание";
        tempModel->setHorizontalHeaderLabels(headers);
        
        // Устанавливаем временную модель для корректной настройки заголовков
        tableView->setModel(tempModel);
        qDebug() << "VedomostProcessor::createTableView: Создана временная модель для настройки заголовков";
    }
    
    // Настройка растягивания столбцов для заполнения всего виджета
    QHeaderView *horizontalHeader = tableView->horizontalHeader();
    
    // Отключаем автоматическое изменение размера по содержимому
    horizontalHeader->setStretchLastSection(false);
    
    // Устанавливаем режимы для каждого столбца - все интерактивные (изменяемые по ширине)
    horizontalHeader->setSectionResizeMode(0, QHeaderView::Interactive); // Наименование
    horizontalHeader->setSectionResizeMode(1, QHeaderView::Interactive); // Код продукции
    horizontalHeader->setSectionResizeMode(2, QHeaderView::Interactive); // Обозначение документа на поставку
    horizontalHeader->setSectionResizeMode(3, QHeaderView::Interactive); // Поставщик
    horizontalHeader->setSectionResizeMode(4, QHeaderView::Interactive); // Куда входит (обозначение)
    horizontalHeader->setSectionResizeMode(5, QHeaderView::Interactive); // Количество на изделие
    horizontalHeader->setSectionResizeMode(6, QHeaderView::Interactive); // Количество в комплекте
    horizontalHeader->setSectionResizeMode(7, QHeaderView::Interactive); // Количество на регулир
    horizontalHeader->setSectionResizeMode(8, QHeaderView::Interactive); // Количество всего
    horizontalHeader->setSectionResizeMode(9, QHeaderView::Interactive); // Примечание
    
    // Устанавливаем начальные размеры для столбцов
    horizontalHeader->resizeSection(0, 200); // Наименование - 200px
    horizontalHeader->resizeSection(1, 120); // Код продукции - 120px
    horizontalHeader->resizeSection(2, 150); // Обозначение документа на поставку - 150px
    horizontalHeader->resizeSection(3, 100); // Поставщик - 100px
    horizontalHeader->resizeSection(4, 120); // Куда входит (обозначение) - 120px
    horizontalHeader->resizeSection(5, 100); // Количество на изделие - 100px
    horizontalHeader->resizeSection(6, 100); // Количество в комплекте - 100px
    horizontalHeader->resizeSection(7, 100); // Количество на регулир - 100px
    horizontalHeader->resizeSection(8, 100); // Количество всего - 100px
    horizontalHeader->resizeSection(9, 150); // Примечание - 150px
    
    // Настройка вертикального заголовка
    QHeaderView *verticalHeader = tableView->verticalHeader();
    verticalHeader->setDefaultSectionSize(25); // Устанавливаем высоту строки
    verticalHeader->setSectionResizeMode(QHeaderView::Fixed);
    
    qDebug() << "VedomostProcessor::createTableView: Настроено растягивание столбцов";
    return tableView;
}

void VedomostProcessor::setColumnMappings(const QStringList &mappings)
{
    qDebug() << "VedomostProcessor::setColumnMappings: Настройки колонок обновлены:" << mappings;
    
    if (m_controller) {
        m_controller->setColumnMappings(mappings);
        qDebug() << "VedomostProcessor::setColumnMappings: Настройки переданы в контроллер";
    } else {
        qDebug() << "VedomostProcessor::setColumnMappings: Контроллер недоступен";
    }
}

QStringList VedomostProcessor::getColumnMappings() const
{
    if (m_controller) {
        return m_controller->getColumnMappings();
    }
    return QStringList();
}

QStringList VedomostProcessor::getAvailableProperties() const
{
    if (m_controller) {
        return m_controller->getAvailableProperties();
    }
    return QStringList();
}

void VedomostProcessor::updateTable()
{
    qDebug() << "VedomostProcessor::updateTable: Обновляем таблицу по кнопке";
    
    if (m_controller) {
        m_controller->updateTableFromComponents();
        qDebug() << "VedomostProcessor::updateTable: Таблица обновлена через контроллер";
    } else {
        qDebug() << "VedomostProcessor::updateTable: Контроллер недоступен";
    }
}

void VedomostProcessor::setController(VedomostController *controller)
{
    qDebug() << "VedomostProcessor::setController: Устанавливаем контроллер";
    m_controller = controller;
    if (m_controller) {
        qDebug() << "VedomostProcessor::setController: Контроллер установлен";
    } else {
        qDebug() << "VedomostProcessor::setController: Контроллер сброшен";
    }
}

void VedomostProcessor::setModel(VedomostTableModel *model)
{
    qDebug() << "VedomostProcessor::setModel: Модель установлена в контроллер";
    if (m_controller) {
        m_controller->setModel(model);
        qDebug() << "VedomostProcessor::setModel: Модель передана в контроллер";
    } else {
        qDebug() << "VedomostProcessor::setModel: Контроллер недоступен";
    }
}

// SimpleListProcessor
SimpleListProcessor::SimpleListProcessor(QObject *parent)
    : DocumentProcessor(parent)
    , m_controller(new SimpleListTableController(this))
{
}

SimpleListProcessor::~SimpleListProcessor()
{
    // m_controller удалится автоматически, так как он является дочерним объектом
}

void SimpleListProcessor::processComponents(const QList<ComponentModel*> &components)
{
    qDebug() << "SimpleListProcessor::processComponents: Получено" << components.size() << "компонентов";
    // Передаем компоненты в контроллер
    if (m_controller) {
        m_controller->setComponents(components);
        qDebug() << "SimpleListProcessor::processComponents: Компоненты переданы в контроллер";
    }
}

void SimpleListProcessor::processProjectParams(const QMap<QString, QString> &params)
{
    qDebug() << "SimpleListProcessor::processProjectParams: Получено" << params.size() << "параметров";
    // Пока не используем параметры проекта
}

QTableView* SimpleListProcessor::createTableView()
{
    QTableView *tableView = new QTableView();
    if (m_controller) {
        tableView->setModel(m_controller->getTableModel());
        
        // Настройка растягивания столбцов
        QHeaderView *horizontalHeader = tableView->horizontalHeader();
        horizontalHeader->setStretchLastSection(false);
        
        // Устанавливаем режимы для каждого столбца
        horizontalHeader->setSectionResizeMode(0, QHeaderView::Interactive); // Поз.обозначение
        horizontalHeader->setSectionResizeMode(1, QHeaderView::Interactive); // Наименование
        horizontalHeader->setSectionResizeMode(2, QHeaderView::Interactive); // Количество
        
        // Устанавливаем начальные размеры для столбцов
        horizontalHeader->resizeSection(0, 150); // Поз.обозначение
        horizontalHeader->resizeSection(1, 300); // Наименование
        horizontalHeader->resizeSection(2, 80);  // Количество
        
        // Настройка вертикального заголовка
        QHeaderView *verticalHeader = tableView->verticalHeader();
        verticalHeader->setDefaultSectionSize(25);
        verticalHeader->setSectionResizeMode(QHeaderView::Fixed);
        
        qDebug() << "SimpleListProcessor::createTableView: Настроено растягивание столбцов";
    } else {
        // Если контроллер не установлен, создаем временную модель
        QStandardItemModel *tempModel = new QStandardItemModel(tableView);
        QStringList headers;
        headers << "Поз.обозначение" << "Наименование" << "Кол.";
        tempModel->setHorizontalHeaderLabels(headers);
        tableView->setModel(tempModel);
        
        // Настройка столбцов
        QHeaderView *horizontalHeader = tableView->horizontalHeader();
        horizontalHeader->setStretchLastSection(false);
        horizontalHeader->setSectionResizeMode(0, QHeaderView::Interactive);
        horizontalHeader->setSectionResizeMode(1, QHeaderView::Interactive);
        horizontalHeader->setSectionResizeMode(2, QHeaderView::Interactive);
        horizontalHeader->resizeSection(0, 150);
        horizontalHeader->resizeSection(1, 300);
        horizontalHeader->resizeSection(2, 80);
        
        QHeaderView *verticalHeader = tableView->verticalHeader();
        verticalHeader->setDefaultSectionSize(25);
        verticalHeader->setSectionResizeMode(QHeaderView::Fixed);
        
        qDebug() << "SimpleListProcessor::createTableView: Создана временная модель";
    }
    return tableView;
}

void SimpleListProcessor::updateTable()
{
    qDebug() << "SimpleListProcessor::updateTable: Обновляем таблицу";
    if (m_controller) {
        m_controller->updateTableFromComponents();
    }
}

void SimpleListProcessor::setController(SimpleListTableController *controller)
{
    qDebug() << "SimpleListProcessor::setController: Устанавливаем контроллер";
    m_controller = controller;
}

void SimpleListProcessor::setModel(SimpleListTableModel *model)
{
    qDebug() << "SimpleListProcessor::setModel: Модель установлена в контроллер";
    if (m_controller) {
        m_controller->setModel(model);
    }
}

// DocumentEditWidget
DocumentEditWidget::DocumentEditWidget(DocumentProcessor *processor, QWidget *parent)
    : QWidget(parent)
    , m_processor(processor)
    , m_componentModel(nullptr)
    , m_projectParamModel(nullptr)
    , m_controller(nullptr)
    , m_titleInscriptionsModel(nullptr)
{
    qDebug() << "DocumentEditWidget: Конструктор без контроллера, processor:" << (processor ? "доступен" : "nullptr");
    setUp();
}

DocumentEditWidget::DocumentEditWidget(DocumentProcessor *processor, MainController *controller, QWidget *parent)
    : QWidget(parent)
    , m_processor(processor)
    , m_componentModel(nullptr)
    , m_projectParamModel(nullptr)
    , m_controller(controller)
    , m_titleInscriptionsModel(nullptr)
{
    qDebug() << "DocumentEditWidget: Конструктор с контроллером, processor:" << (processor ? "доступен" : "nullptr") 
             << "controller:" << (controller ? "доступен" : "nullptr");
    setUp();
}

void DocumentEditWidget::setUp()
{
    qDebug() << "DocumentEditWidget::setUp: Начинаем настройку виджета";
    setWidgets();
    setUpLayout();
    setUpConnections();
    
    // Инициализируем состояние кнопок
    m_insertRowButton->setEnabled(false); // Кнопка вставки неактивна по умолчанию
    m_removeRowButton->setEnabled(false); // Кнопка удаления неактивна по умолчанию
    
    // Применяем настройки растягивания столбцов к пустой таблице
    applyColumnStretching();
    
    qDebug() << "DocumentEditWidget::setUp: Настройка виджета завершена";
}

void DocumentEditWidget::setWidgets()
{
    qDebug() << "DocumentEditWidget::setWidgets: Создаем виджеты";
    m_openSettingsButton = new QPushButton("Настройки документа", this);
    m_generateTableButton = new QPushButton("Генерация таблицы", this);
    m_recalculateTableButton = new QPushButton("Пересчет таблицы", this);
    
    // Новые кнопки для управления строками
    m_addRowButton = new QPushButton("+ Добавить строку", this);
    m_insertRowButton = new QPushButton("+ Вставить строку", this);
    m_removeRowButton = new QPushButton("- Удалить строку", this);
    
    m_tableView = new QTableView(this);
    // Настраиваем таблицу для растягивания на весь виджет
    m_tableView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    m_tableView->horizontalHeader()->setStretchLastSection(false);
    // Включаем контекстное меню
    m_tableView->setContextMenuPolicy(Qt::CustomContextMenu);
    // Устанавливаем режим множественного выбора строк
    m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
    m_tableView->setSelectionMode(QAbstractItemView::ExtendedSelection);
    m_settingsGroupBox = new QGroupBox("Настройки", this);
    qDebug() << "DocumentEditWidget::setWidgets: Виджеты созданы";
}

void DocumentEditWidget::setUpLayout()
{
    qDebug() << "DocumentEditWidget::setUpLayout: Настраиваем компоновку";
    
    // Настраиваем политику размера для всего виджета
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    
    QVBoxLayout* mainLayout = new QVBoxLayout(this);
    
    // Группа настроек
    QHBoxLayout* groupBoxLayout = new QHBoxLayout(m_settingsGroupBox);
    
    // Левая группа кнопок
    groupBoxLayout->addWidget(m_openSettingsButton);
    
    // Растягивающийся элемент для разделения
    groupBoxLayout->addStretch();
    
    // Средняя группа кнопок для управления строками
    groupBoxLayout->addWidget(m_addRowButton);
    groupBoxLayout->addWidget(m_insertRowButton);
    groupBoxLayout->addWidget(m_removeRowButton);
    
    // Растягивающийся элемент для разделения
    groupBoxLayout->addStretch();
    
    // Правая группа кнопок
    groupBoxLayout->addWidget(m_generateTableButton);
    groupBoxLayout->addWidget(m_recalculateTableButton);
    
    mainLayout->addWidget(m_settingsGroupBox);
    mainLayout->addWidget(m_tableView, 1); // Растягиваем таблицу на все доступное пространство
    qDebug() << "DocumentEditWidget::setUpLayout: Компоновка настроена";
}

void DocumentEditWidget::setUpConnections()
{
    qDebug() << "DocumentEditWidget::setUpConnections: Настраиваем соединения сигналов";
    connect(m_generateTableButton, &QPushButton::clicked, this, &DocumentEditWidget::onGenerateTable);
    connect(m_recalculateTableButton, &QPushButton::clicked, this, &DocumentEditWidget::onRecalculateTable);
    connect(m_openSettingsButton, &QPushButton::clicked, this, &DocumentEditWidget::onOpenColumnSettings);
    
    // Соединения для новых кнопок управления строками
    connect(m_addRowButton, &QPushButton::clicked, this, &DocumentEditWidget::onAddRow);
    connect(m_insertRowButton, &QPushButton::clicked, this, &DocumentEditWidget::onInsertRow);
    connect(m_removeRowButton, &QPushButton::clicked, this, &DocumentEditWidget::onRemoveRow);
    
    // Соединение для контекстного меню
    connect(m_tableView, &QTableView::customContextMenuRequested, this, &DocumentEditWidget::onContextMenuRequested);
    
    // Соединение для обновления состояния кнопок при изменении выбора
    // Будем устанавливать это соединение после того, как таблица получит модель
    // connect(m_tableView->selectionModel(), &QItemSelectionModel::selectionChanged, 
    //         this, &DocumentEditWidget::onSelectionChanged);
    
    qDebug() << "DocumentEditWidget::setUpConnections: Соединения сигналов настроены";
}

void DocumentEditWidget::onOpenColumnSettings()
{
    qDebug() << "DocumentEditWidget::onOpenColumnSettings: Нажата кнопка настроек колонок";
    
    // Определяем тип документа
    DocumentType docType = DocumentType::Perechen; // По умолчанию
    
    if (qobject_cast<PerechenProcessor*>(m_processor)) {
        docType = DocumentType::Perechen;
    } else if (qobject_cast<SpecificationPCBProcessor*>(m_processor)) {
        docType = DocumentType::SpecificationPCB;
    } else if (qobject_cast<SpecificationProcessor*>(m_processor)) {
        docType = DocumentType::Specification;
    } else if (qobject_cast<VedomostProcessor*>(m_processor)) {
        docType = DocumentType::Vedomost;
    } else if (qobject_cast<SimpleListProcessor*>(m_processor)) {
        docType = DocumentType::SimpleList;
    } else {
        qDebug() << "DocumentEditWidget::onOpenColumnSettings: Процессор не поддерживает настройки";
        return;
    }
    
    // Создаем универсальный диалог настроек
    DocumentSettingsDialog dialog(docType, m_controller, this);
    
    if (dialog.exec() == QDialog::Accepted) {
        QStringList newTableMappings = dialog.getTableColumnMappings();
        QMap<int, QString> newInscriptionValues = dialog.getTitleInscriptionValues();
        
        qDebug() << "DocumentEditWidget::onOpenColumnSettings: Получены настройки таблицы:" << newTableMappings;
        qDebug() << "DocumentEditWidget::onOpenColumnSettings: Получены настройки надписей:" << newInscriptionValues;
        
        // Настройки таблицы и надписей уже сохранены в диалоге в контроллер
        // Сохраняем настройки в БД
        if (m_controller) {
            m_controller->saveProjectSettingsToDatabase();
            qDebug() << "DocumentEditWidget::onOpenColumnSettings: Настройки сохранены в БД";
        }
        
        qDebug() << "DocumentEditWidget::onOpenColumnSettings: Настройки обновлены, но таблица не генерируется автоматически";
    } else {
        qDebug() << "DocumentEditWidget::onOpenColumnSettings: Диалог настроек отменен";
    }
}



void DocumentEditWidget::onGenerateTable()
{
    qDebug() << "DocumentEditWidget::onGenerateTable: Нажата кнопка генерации таблицы";
    
    // Проверяем, является ли процессор PerechenProcessor
    PerechenProcessor *perechenProcessor = qobject_cast<PerechenProcessor*>(m_processor);
    if (perechenProcessor) {
        if (m_controller && m_controller->perechenTableController()) {
            qDebug() << "DocumentEditWidget::onGenerateTable: Генерируем таблицу через PerechenTableController";
            m_controller->perechenTableController()->generateTableFromComponents();
            
            // Устанавливаем модель из контроллера
            if (m_controller->perechenTableModel()) {
                m_tableView->setModel(m_controller->perechenTableModel());
                applyColumnStretching();
                setupSelectionConnection();
                qDebug() << "DocumentEditWidget::onGenerateTable: Модель PerechenTableModel установлена";
            }
        } else {
            qDebug() << "DocumentEditWidget::onGenerateTable: PerechenTableController недоступен";
        }
    } else {
        // Проверяем, является ли процессор SpecificationPCBProcessor
        SpecificationPCBProcessor *specPCBProcessor = qobject_cast<SpecificationPCBProcessor*>(m_processor);
        if (specPCBProcessor) {
            if (m_controller && m_controller->specificationPCBController()) {
                qDebug() << "DocumentEditWidget::onGenerateTable: Генерируем таблицу через SpecificationPCBController";
                qDebug() << "DocumentEditWidget::onGenerateTable: Компонентов в модели:" << m_componentModel->getComponents().size();
                
                // Передаем компоненты в контроллер
                m_controller->specificationPCBController()->setComponents(m_componentModel->getComponents());
                
                m_controller->specificationPCBController()->generateTableFromComponents();
                
                // Устанавливаем модель из контроллера
                if (m_controller->specificationPCBTableModel()) {
                    m_tableView->setModel(m_controller->specificationPCBTableModel());
                    applyColumnStretching();
                    setupSelectionConnection();
                    qDebug() << "DocumentEditWidget::onGenerateTable: Модель SpecificationPCBTableModel установлена";
                    qDebug() << "DocumentEditWidget::onGenerateTable: Количество строк в модели:" << m_controller->specificationPCBTableModel()->rowCount();
                }
            } else {
                qDebug() << "DocumentEditWidget::onGenerateTable: SpecificationPCBController недоступен";
            }
        } else {
            // Проверяем, является ли процессор SpecificationProcessor
            SpecificationProcessor *specProcessor = qobject_cast<SpecificationProcessor*>(m_processor);
            if (specProcessor) {
                if (m_controller && m_controller->specificationController()) {
                    qDebug() << "DocumentEditWidget::onGenerateTable: Генерируем таблицу через SpecificationController";
                    
                    // Получаем PCB модель материалов
                    PCBMaterialModel* pcbMaterialModel = m_controller->pcbMaterialModel();
                    if (pcbMaterialModel) {
                        qDebug() << "DocumentEditWidget::onGenerateTable: PCB модель материалов доступна, материалов:" << pcbMaterialModel->getMaterialCount();
                        
                        // Передаем PCB модель в контроллер
                        m_controller->specificationController()->setPCBMaterialModel(pcbMaterialModel);
                    } else {
                        qDebug() << "DocumentEditWidget::onGenerateTable: PCB модель материалов недоступна";
                        // Передаем nullptr
                        m_controller->specificationController()->setPCBMaterialModel(nullptr);
                    }
                    
                    m_controller->specificationController()->generateTableFromMaterials();
                    
                    // Устанавливаем модель из контроллера
                    if (m_controller->specificationTableModel()) {
                        m_tableView->setModel(m_controller->specificationTableModel());
                        applyColumnStretching();
                        setupSelectionConnection();
                        qDebug() << "DocumentEditWidget::onGenerateTable: Модель SpecificationTableModel установлена";
                        qDebug() << "DocumentEditWidget::onGenerateTable: Количество строк в модели:" << m_controller->specificationTableModel()->rowCount();
                    }
                } else {
                    qDebug() << "DocumentEditWidget::onGenerateTable: SpecificationController недоступен";
                }
            } else {
                // Проверяем, является ли процессор VedomostProcessor
                VedomostProcessor *vedomostProcessor = qobject_cast<VedomostProcessor*>(m_processor);
                if (vedomostProcessor) {
                    if (m_controller && m_controller->vedomostController()) {
                        qDebug() << "DocumentEditWidget::onGenerateTable: Генерируем таблицу через VedomostController";
                        qDebug() << "DocumentEditWidget::onGenerateTable: Компонентов в модели:" << m_componentModel->getComponents().size();
                        
                        // Передаем компоненты в контроллер
                        m_controller->vedomostController()->setComponents(m_componentModel->getComponents());
                        
                        m_controller->vedomostController()->generateTableFromComponents();
                        
                        // Устанавливаем модель из контроллера
                        if (m_controller->vedomostTableModel()) {
                            m_tableView->setModel(m_controller->vedomostTableModel());
                            applyColumnStretching();
                            setupSelectionConnection();
                            qDebug() << "DocumentEditWidget::onGenerateTable: Модель VedomostTableModel установлена";
                            qDebug() << "DocumentEditWidget::onGenerateTable: Количество строк в модели:" << m_controller->vedomostTableModel()->rowCount();                           

                        }
                    } else {
                        qDebug() << "DocumentEditWidget::onGenerateTable: VedomostController недоступен";
                    }
                } else {
                    // Проверяем, является ли процессор SimpleListProcessor
                    SimpleListProcessor *simpleListProcessor = qobject_cast<SimpleListProcessor*>(m_processor);
                    if (simpleListProcessor) {
                        if (m_controller && m_controller->simpleListTableController()) {
                            qDebug() << "DocumentEditWidget::onGenerateTable: Генерируем таблицу через SimpleListTableController из SpecificationPCB";
                            
                            // Генерируем таблицу бланка заказа на основе SpecificationPCB
                            SpecificationPCBTableModel *specPCBModel = m_controller->specificationPCBTableModel();
                            if (specPCBModel && specPCBModel->rowCount() > 0) {
                                // Если SpecificationPCB уже сгенерирована, используем её
                                m_controller->simpleListTableController()->generateTableFromSpecificationPCB(specPCBModel);
                            } else {
                                // Если SpecificationPCB не сгенерирована, сначала генерируем её
                                qDebug() << "DocumentEditWidget::onGenerateTable: SpecificationPCB не сгенерирована, генерируем её";
                                if (m_controller->specificationPCBController() && m_componentModel) {
                                    m_controller->specificationPCBController()->setComponents(m_componentModel->getComponents());
                                    m_controller->specificationPCBController()->generateTableFromComponents();
                                    
                                    // Теперь используем сгенерированную SpecificationPCB
                                    specPCBModel = m_controller->specificationPCBTableModel();
                                    if (specPCBModel) {
                                        m_controller->simpleListTableController()->generateTableFromSpecificationPCB(specPCBModel);
                                    }
                                }
                            }
                            
                            // Устанавливаем модель из контроллера
                            if (m_controller->simpleListTableModel()) {
                                m_tableView->setModel(m_controller->simpleListTableModel());
                                applyColumnStretching();
                                setupSelectionConnection();
                                qDebug() << "DocumentEditWidget::onGenerateTable: Модель SimpleListTableModel установлена";
                            }
                        } else {
                            qDebug() << "DocumentEditWidget::onGenerateTable: SimpleListTableController недоступен";
                        }
                    } else {
                        qDebug() << "DocumentEditWidget::onGenerateTable: Процессор не является PerechenProcessor, SpecificationPCBProcessor, SpecificationProcessor, VedomostProcessor или SimpleListProcessor";
                    }
                }
            }
        }
    }
}

void DocumentEditWidget::onRecalculateTable()
{
    qDebug() << "DocumentEditWidget::onRecalculateTable: Нажата кнопка пересчета таблицы";
    
    // Проверяем, является ли процессор PerechenProcessor
    PerechenProcessor *perechenProcessor = qobject_cast<PerechenProcessor*>(m_processor);
    if (perechenProcessor) {
        if (m_controller && m_controller->perechenTableModel()) {
            qDebug() << "DocumentEditWidget::onRecalculateTable: Пересчитываем таблицу PerechenTableModel";
            PerechenTableModel *model = m_controller->perechenTableModel();
            model->updateRowNumbers();
            model->updatePageNumbers(); // updatePageNumbers уже уведомляет об изменениях
            qDebug() << "DocumentEditWidget::onRecalculateTable: Пересчет PerechenTableModel завершен";
        } else {
            qDebug() << "DocumentEditWidget::onRecalculateTable: PerechenTableModel недоступна";
        }
        return;
    }
    
    // Проверяем, является ли процессор SpecificationPCBProcessor
    SpecificationPCBProcessor *specPCBProcessor = qobject_cast<SpecificationPCBProcessor*>(m_processor);
    if (specPCBProcessor) {
        if (m_controller && m_controller->specificationPCBTableModel()) {
            qDebug() << "DocumentEditWidget::onRecalculateTable: Пересчитываем таблицу SpecificationPCBTableModel";
            SpecificationPCBTableModel *model = m_controller->specificationPCBTableModel();
            model->updateRowNumbers();
            model->updatePageNumbers(); // updatePageNumbers уже уведомляет об изменениях
            
            // Вызываем optimizePageBreaks через контроллер, который также пересчитывает позиции
            if (m_controller->specificationPCBController()) {
                qDebug() << "DocumentEditWidget::onRecalculateTable: Вызываем optimizePageBreaks для пересчета позиций";
                m_controller->specificationPCBController()->optimizePageBreaks();
            }
            
            qDebug() << "DocumentEditWidget::onRecalculateTable: Пересчет SpecificationPCBTableModel завершен";
        } else {
            qDebug() << "DocumentEditWidget::onRecalculateTable: SpecificationPCBTableModel недоступна";
        }
        return;
    }
    
    // Проверяем, является ли процессор SpecificationProcessor
    SpecificationProcessor *specProcessor = qobject_cast<SpecificationProcessor*>(m_processor);
    if (specProcessor) {
        if (m_controller && m_controller->specificationTableModel()) {
            qDebug() << "DocumentEditWidget::onRecalculateTable: Пересчитываем таблицу SpecificationTableModel";
            SpecificationTableModel *model = m_controller->specificationTableModel();
            model->updateRowNumbers();
            model->updatePageNumbers(); // updatePageNumbers уже уведомляет об изменениях
            qDebug() << "DocumentEditWidget::onRecalculateTable: Пересчет SpecificationTableModel завершен";
        } else {
            qDebug() << "DocumentEditWidget::onRecalculateTable: SpecificationTableModel недоступна";
        }
        return;
    }
    
    // Проверяем, является ли процессор VedomostProcessor
    VedomostProcessor *vedomostProcessor = qobject_cast<VedomostProcessor*>(m_processor);
    if (vedomostProcessor) {
        if (m_controller && m_controller->vedomostTableModel()) {
            qDebug() << "DocumentEditWidget::onRecalculateTable: Пересчитываем таблицу VedomostTableModel";
            VedomostTableModel *model = m_controller->vedomostTableModel();
            model->updateRowNumbers();
            model->updatePageNumbers();
            // Пересчитываем totalQuantity для всех строк
            // updateTotalQuantity уже уведомляет об изменениях через emit dataChanged
            for (int row = 0; row < model->rowCount(); ++row) {
                model->updateTotalQuantity(row);
            }
            qDebug() << "DocumentEditWidget::onRecalculateTable: Пересчет VedomostTableModel завершен";
        } else {
            qDebug() << "DocumentEditWidget::onRecalculateTable: VedomostTableModel недоступна";
        }
        return;
    }
    
    // Проверяем, является ли процессор SimpleListProcessor
    SimpleListProcessor *simpleListProcessor = qobject_cast<SimpleListProcessor*>(m_processor);
    if (simpleListProcessor) {
        if (m_controller && m_controller->simpleListTableController()) {
            qDebug() << "DocumentEditWidget::onRecalculateTable: Пересчитываем таблицу SimpleListTableModel";
            m_controller->simpleListTableController()->updateTableFromComponents();
            qDebug() << "DocumentEditWidget::onRecalculateTable: Пересчет SimpleListTableModel завершен";
        } else {
            qDebug() << "DocumentEditWidget::onRecalculateTable: SimpleListTableController недоступен";
        }
        return;
    }
    
    qDebug() << "DocumentEditWidget::onRecalculateTable: Процессор не является PerechenProcessor, SpecificationPCBProcessor, SpecificationProcessor, VedomostProcessor или SimpleListProcessor";
}

void DocumentEditWidget::setData(ComponentTableModel *componentModel, ProjectParamTableModel *projectParamModel)
{
    qDebug() << "DocumentEditWidget::setData: Устанавливаем данные, componentModel:" << (componentModel ? "доступен" : "nullptr") 
             << "projectParamModel:" << (projectParamModel ? "доступен" : "nullptr");
    
    m_componentModel = componentModel;
    m_projectParamModel = projectParamModel;
    
    // Передаем DesignatorMappingModel в PerechenTableController, если это PerechenProcessor
    PerechenProcessor *perechenProcessor = qobject_cast<PerechenProcessor*>(m_processor);
    if (perechenProcessor && m_controller) {
        // Получаем контроллер из PerechenProcessor
        PerechenTableController *perecheController = perechenProcessor->getController();
        if (perecheController) {
            // Передаем модель маппинга дезигнаторов
            perecheController->setDesignatorMappingModel(m_controller->designatorMappingModel());
            qDebug() << "DocumentEditWidget::setData: DesignatorMappingModel передан в PerechenTableController";
        }
    }
    
    // Передаем DesignatorMappingModel в SpecificationPCBController, если это SpecificationPCBProcessor
    SpecificationPCBProcessor *specPCBProcessor = qobject_cast<SpecificationPCBProcessor*>(m_processor);
    if (specPCBProcessor && m_controller) {
        // Получаем контроллер из SpecificationPCBProcessor
        SpecificationPCBController *specPCBController = specPCBProcessor->getController();
        if (specPCBController) {
            // Передаем модель маппинга дезигнаторов
            specPCBController->setDesignatorMappingModel(m_controller->designatorMappingModel());
            qDebug() << "DocumentEditWidget::setData: DesignatorMappingModel передан в SpecificationPCBController";
        }
    }
    
    // Передаем DesignatorMappingModel в VedomostController, если это VedomostProcessor
    VedomostProcessor *vedomostProcessor = qobject_cast<VedomostProcessor*>(m_processor);
    if (vedomostProcessor && m_controller) {
        // Получаем контроллер из VedomostProcessor
        VedomostController *vedomostController = vedomostProcessor->getController();
        if (vedomostController) {
            // Передаем модель маппинга дезигнаторов
            vedomostController->setDesignatorMappingModel(m_controller->designatorMappingModel());
            qDebug() << "DocumentEditWidget::setData: DesignatorMappingModel передан в VedomostController";
        }
    }
    
    // Не вызываем updateView() автоматически - таблица будет генерироваться только по нажатию кнопки
    qDebug() << "DocumentEditWidget::setData: Данные установлены";
}

void DocumentEditWidget::updateView()
{
    //qDebug() << "DocumentEditWidget::updateView: Начинаем обновление представления для типа документа:" << m_processor->getDocumentType();
    
    if (!m_processor || !m_componentModel || !m_projectParamModel) {
        qDebug() << "DocumentEditWidget::updateView: Один из указателей null - processor:" << (m_processor ? "доступен" : "nullptr") 
                 << "componentModel:" << (m_componentModel ? "доступен" : "nullptr") 
                 << "projectParamModel:" << (m_projectParamModel ? "доступен" : "nullptr");
        return;
    }
    
    qDebug() << "DocumentEditWidget::updateView: Компонентов в модели:" << m_componentModel->getComponents().size();
    
    // Проверяем, является ли процессор VedomostProcessor
    VedomostProcessor *vedomostProcessor = qobject_cast<VedomostProcessor*>(m_processor);
    if (vedomostProcessor) {
        // Для ведомости только передаем компоненты в контроллер, но не генерируем таблицу
        qDebug() << "DocumentEditWidget::updateView: VedomostProcessor - только передаем компоненты в контроллер";
        if (vedomostProcessor->getController()) {
            vedomostProcessor->getController()->setComponents(m_componentModel->getComponents());
        }
    } else {
        // Для других процессоров обрабатываем данные и генерируем таблицу
        m_processor->processComponents(m_componentModel->getComponents());
        m_processor->processProjectParams(m_projectParamModel->getDataAsMap());
    }
    
    // Создаем новую таблицу
    QTableView *newTableView = m_processor->createTableView();
    
    if (!newTableView || !newTableView->model()) {
        qDebug() << "DocumentEditWidget::updateView: Не удалось создать таблицу или модель";
        delete newTableView;
        return;
    }
    
    // Безопасно заменяем модель
    QAbstractItemModel *oldModel = m_tableView->model();
    m_tableView->setModel(newTableView->model());
    
    // Удаляем старую модель только после успешной установки новой
    if (oldModel && oldModel != newTableView->model()) {
        oldModel->deleteLater();
    }
    
    // Удаляем временную таблицу, но не её модель
    delete newTableView;
    
    // Применяем настройки растягивания столбцов к основной таблице
    applyColumnStretching();
    
    // Устанавливаем соединение для сигнала selectionChanged после установки модели
    setupSelectionConnection();
    
    qDebug() << "DocumentEditWidget::updateView: Таблица обновлена успешно";
}

TitleInscriptionsModel* DocumentEditWidget::getTitleInscriptionsModel() const
{
    // Возвращаем модель надписей из MainController
    if (m_controller) {
        TitleInscriptionsModel *titleModel = m_controller->titleInscriptionsModel();
        qDebug() << "DocumentEditWidget::getTitleInscriptionsModel: Возвращаем модель надписей из MainController:" << (titleModel ? "доступна" : "nullptr");
        return titleModel;
    }
    qDebug() << "DocumentEditWidget::getTitleInscriptionsModel: Контроллер недоступен, возвращаем nullptr";
    return nullptr;
}

PerechenTableModel* DocumentEditWidget::getPerechenTableModel() const
{
    qDebug() << "DocumentEditWidget::getPerechenTableModel: Проверяем доступность PerechenProcessor";
    
    // Проверяем, является ли текущий процессор PerechenProcessor
    PerechenProcessor *perechenProcessor = qobject_cast<PerechenProcessor*>(m_processor);
    if (perechenProcessor) {
        if (m_controller && m_controller->perechenTableModel()) {
            qDebug() << "DocumentEditWidget::getPerechenTableModel: Возвращаем модель перечня:" << (m_controller->perechenTableModel() ? "доступна" : "nullptr");
            return m_controller->perechenTableModel();
        }
    }
    
    qDebug() << "DocumentEditWidget::getPerechenTableModel: PerechenProcessor недоступен, возвращаем nullptr";
    return nullptr;
}

SpecificationPCBTableModel* DocumentEditWidget::getSpecificationPCBTableModel() const
{
    qDebug() << "DocumentEditWidget::getSpecificationPCBTableModel: Проверяем доступность SpecificationPCBProcessor";
    
    // Проверяем, является ли текущий процессор SpecificationPCBProcessor
    SpecificationPCBProcessor *specPCBProcessor = qobject_cast<SpecificationPCBProcessor*>(m_processor);
    if (specPCBProcessor) {
        if (m_controller && m_controller->specificationPCBTableModel()) {
            qDebug() << "DocumentEditWidget::getSpecificationPCBTableModel: Возвращаем модель спецификации платы:" << (m_controller->specificationPCBTableModel() ? "доступна" : "nullptr");
            return m_controller->specificationPCBTableModel();
        }
    }
    
    qDebug() << "DocumentEditWidget::getSpecificationPCBTableModel: SpecificationPCBProcessor недоступен, возвращаем nullptr";
    return nullptr;
}

SpecificationTableModel* DocumentEditWidget::getSpecificationTableModel() const
{
    qDebug() << "DocumentEditWidget::getSpecificationTableModel: Проверяем доступность SpecificationProcessor";
    
    // Проверяем, является ли текущий процессор SpecificationProcessor
    SpecificationProcessor *specProcessor = qobject_cast<SpecificationProcessor*>(m_processor);
    if (specProcessor) {
        if (m_controller && m_controller->specificationTableModel()) {
            qDebug() << "DocumentEditWidget::getSpecificationTableModel: Возвращаем модель спецификации:" << (m_controller->specificationTableModel() ? "доступна" : "nullptr");
            return m_controller->specificationTableModel();
        }
    }
    
    qDebug() << "DocumentEditWidget::getSpecificationTableModel: SpecificationProcessor недоступен, возвращаем nullptr";
    return nullptr;
}

VedomostTableModel* DocumentEditWidget::getVedomostTableModel() const
{
    qDebug() << "DocumentEditWidget::getVedomostTableModel: Проверяем доступность VedomostProcessor";
    
    // Проверяем, является ли текущий процессор VedomostProcessor
    VedomostProcessor *vedomostProcessor = qobject_cast<VedomostProcessor*>(m_processor);
    if (vedomostProcessor) {
        if (m_controller && m_controller->vedomostTableModel()) {
            qDebug() << "DocumentEditWidget::getVedomostTableModel: Возвращаем модель ведомости:" << (m_controller->vedomostTableModel() ? "доступна" : "nullptr");
            return m_controller->vedomostTableModel();
        }
    }
    
    qDebug() << "DocumentEditWidget::getVedomostTableModel: VedomostProcessor недоступен, возвращаем nullptr";
    return nullptr;
} 

// Новые слоты для управления строками
void DocumentEditWidget::onAddRow()
{
    qDebug() << "DocumentEditWidget::onAddRow: Нажата кнопка добавления строки";
    
    // Проверяем, является ли процессор PerechenProcessor
    PerechenProcessor *perechenProcessor = qobject_cast<PerechenProcessor*>(m_processor);
    if (perechenProcessor) {
        if (m_controller && m_controller->perechenTableController()) {
            m_controller->perechenTableController()->addEmptyRow();
            qDebug() << "DocumentEditWidget::onAddRow: Пустая строка добавлена через PerechenTableController";
        } else {
            qDebug() << "DocumentEditWidget::onAddRow: PerechenTableController недоступен";
        }
        return;
    }
    
    // Проверяем, является ли процессор SpecificationPCBProcessor
    SpecificationPCBProcessor *specPCBProcessor = qobject_cast<SpecificationPCBProcessor*>(m_processor);
    if (specPCBProcessor) {
        if (m_controller && m_controller->specificationPCBController()) {
            m_controller->specificationPCBController()->addEmptyRow();
            qDebug() << "DocumentEditWidget::onAddRow: Пустая строка добавлена через SpecificationPCBController";
        } else {
            qDebug() << "DocumentEditWidget::onAddRow: SpecificationPCBController недоступен";
        }
        return;
    }
    
    // Проверяем, является ли процессор VedomostProcessor
    VedomostProcessor *vedomostProcessor = qobject_cast<VedomostProcessor*>(m_processor);
    if (vedomostProcessor) {
        if (m_controller && m_controller->vedomostController()) {
            m_controller->vedomostController()->addEmptyRow();
            qDebug() << "DocumentEditWidget::onAddRow: Пустая строка добавлена через VedomostController";
        } else {
            qDebug() << "DocumentEditWidget::onAddRow: VedomostController недоступен";
        }
        return;
    }
    
    qDebug() << "DocumentEditWidget::onAddRow: Процессор не поддерживает добавление строк";
}

void DocumentEditWidget::onInsertRow()
{
    qDebug() << "DocumentEditWidget::onInsertRow: Нажата кнопка вставки строки";
    
    // Получаем текущую выбранную строку
    int selectedRow = getCurrentSelectedRow();
    if (selectedRow == -1) {
        qDebug() << "DocumentEditWidget::onInsertRow: Нет выбранной строки";
        return;
    }
    
    // Проверяем, является ли процессор PerechenProcessor
    PerechenProcessor *perechenProcessor = qobject_cast<PerechenProcessor*>(m_processor);
    if (perechenProcessor) {
        // Проверяем, можно ли вставить строку в эту позицию
        if (m_controller && m_controller->perechenTableModel()) {
            if (!m_controller->perechenTableModel()->canEditRow(selectedRow)) {
                qDebug() << "DocumentEditWidget::onInsertRow: Нельзя вставить строку перед строкой" << selectedRow << "(заголовок или автоматически сгенерированная)";
                return;
            }
        }
        
        qDebug() << "DocumentEditWidget::onInsertRow: Вставляем строку перед строкой" << selectedRow;
        
        // Получаем контроллер и вставляем пустую строку перед текущей
        if (m_controller && m_controller->perechenTableController()) {
            m_controller->perechenTableController()->insertEmptyRowAt(selectedRow);
            qDebug() << "DocumentEditWidget::onInsertRow: Пустая строка вставлена через PerechenTableController";
        } else {
            qDebug() << "DocumentEditWidget::onInsertRow: PerechenTableController недоступен";
        }
        return;
    }
    
    // Проверяем, является ли процессор SpecificationPCBProcessor
    SpecificationPCBProcessor *specPCBProcessor = qobject_cast<SpecificationPCBProcessor*>(m_processor);
    if (specPCBProcessor) {
        // Проверяем, можно ли вставить строку в эту позицию
        if (m_controller && m_controller->specificationPCBTableModel()) {
            if (!m_controller->specificationPCBTableModel()->canEditRow(selectedRow)) {
                qDebug() << "DocumentEditWidget::onInsertRow: Нельзя вставить строку перед строкой" << selectedRow << "(заголовок или автоматически сгенерированная)";
                return;
            }
        }
        
        qDebug() << "DocumentEditWidget::onInsertRow: Вставляем строку перед строкой" << selectedRow;
        
        // Получаем контроллер и вставляем пустую строку перед текущей
        if (m_controller && m_controller->specificationPCBController()) {
            m_controller->specificationPCBController()->insertEmptyRowAt(selectedRow);
            qDebug() << "DocumentEditWidget::onInsertRow: Пустая строка вставлена через SpecificationPCBController";
        } else {
            qDebug() << "DocumentEditWidget::onInsertRow: SpecificationPCBController недоступен";
        }
        return;
    }
    
    // Проверяем, является ли процессор VedomostProcessor
    VedomostProcessor *vedomostProcessor = qobject_cast<VedomostProcessor*>(m_processor);
    if (vedomostProcessor) {
        // Проверяем, можно ли вставить строку в эту позицию
        if (m_controller && m_controller->vedomostTableModel()) {
            if (!m_controller->vedomostTableModel()->canEditRow(selectedRow)) {
                qDebug() << "DocumentEditWidget::onInsertRow: Нельзя вставить строку перед строкой" << selectedRow << "(заголовок или автоматически сгенерированная)";
                return;
            }
        }
        
        qDebug() << "DocumentEditWidget::onInsertRow: Вставляем строку перед строкой" << selectedRow;
        
        // Получаем контроллер и вставляем пустую строку перед текущей
        if (m_controller && m_controller->vedomostController()) {
            m_controller->vedomostController()->insertEmptyRowAt(selectedRow);
            qDebug() << "DocumentEditWidget::onInsertRow: Пустая строка вставлена через VedomostController";
        } else {
            qDebug() << "DocumentEditWidget::onInsertRow: VedomostController недоступен";
        }
        return;
    }
    
    qDebug() << "DocumentEditWidget::onInsertRow: Процессор не поддерживает вставку строк";
}

void DocumentEditWidget::onRemoveRow()
{
    qDebug() << "DocumentEditWidget::onRemoveRow: Нажата кнопка удаления строки";
    
    // Получаем текущую выбранную строку
    int row = getCurrentSelectedRow();
    if (row == -1) {
        qDebug() << "DocumentEditWidget::onRemoveRow: Нет выбранной строки";
        return;
    }
    
    // Проверяем, является ли процессор PerechenProcessor
    PerechenProcessor *perechenProcessor = qobject_cast<PerechenProcessor*>(m_processor);
    if (perechenProcessor) {
        // Проверяем, можно ли удалить эту строку
        if (m_controller && m_controller->perechenTableModel()) {
            if (!m_controller->perechenTableModel()->canEditRow(row)) {
                qDebug() << "DocumentEditWidget::onRemoveRow: Строка" << row << "не может быть удалена (заголовок или автоматически сгенерированная)";
                return;
            }
        }
        
        qDebug() << "DocumentEditWidget::onRemoveRow: Удаляем строку" << row;
        
        // Получаем контроллер и удаляем строку
        if (m_controller && m_controller->perechenTableController()) {
            m_controller->perechenTableController()->removeRow(row);
            qDebug() << "DocumentEditWidget::onRemoveRow: Строка удалена через PerechenTableController";
        } else {
            qDebug() << "DocumentEditWidget::onRemoveRow: PerechenTableController недоступен";
        }
        return;
    }
    
    // Проверяем, является ли процессор SpecificationPCBProcessor
    SpecificationPCBProcessor *specPCBProcessor = qobject_cast<SpecificationPCBProcessor*>(m_processor);
    if (specPCBProcessor) {
        // Проверяем, можно ли удалить эту строку
        if (m_controller && m_controller->specificationPCBTableModel()) {
            if (!m_controller->specificationPCBTableModel()->canEditRow(row)) {
                qDebug() << "DocumentEditWidget::onRemoveRow: Строка" << row << "не может быть удалена (заголовок или автоматически сгенерированная)";
                return;
            }
        }
        
        qDebug() << "DocumentEditWidget::onRemoveRow: Удаляем строку" << row;
        
        // Получаем контроллер и удаляем строку
        if (m_controller && m_controller->specificationPCBController()) {
            m_controller->specificationPCBController()->removeRow(row);
            qDebug() << "DocumentEditWidget::onRemoveRow: Строка удалена через SpecificationPCBController";
        } else {
            qDebug() << "DocumentEditWidget::onRemoveRow: SpecificationPCBController недоступен";
        }
        return;
    }
    
    // Проверяем, является ли процессор SpecificationProcessor
    SpecificationProcessor *specProcessor = qobject_cast<SpecificationProcessor*>(m_processor);
    if (specProcessor) {
        // Проверяем, можно ли удалить эту строку
        if (m_controller && m_controller->specificationTableModel()) {
            if (!m_controller->specificationTableModel()->canEditRow(row)) {
                qDebug() << "DocumentEditWidget::onRemoveRow: Строка" << row << "не может быть удалена (заголовок или автоматически сгенерированная)";
                return;
            }
        }
        
        qDebug() << "DocumentEditWidget::onRemoveRow: Удаляем строку" << row;
        
        // Получаем контроллер и удаляем строку
        if (m_controller && m_controller->specificationController()) {
            m_controller->specificationController()->removeRow(row);
            qDebug() << "DocumentEditWidget::onRemoveRow: Строка удалена через SpecificationController";
        } else {
            qDebug() << "DocumentEditWidget::onRemoveRow: SpecificationController недоступен";
        }
        return;
    }
    
    // Проверяем, является ли процессор VedomostProcessor
    VedomostProcessor *vedomostProcessor = qobject_cast<VedomostProcessor*>(m_processor);
    if (vedomostProcessor) {
        // Проверяем, можно ли удалить эту строку
        if (m_controller && m_controller->vedomostTableModel()) {
            if (!m_controller->vedomostTableModel()->canEditRow(row)) {
                qDebug() << "DocumentEditWidget::onRemoveRow: Строка" << row << "не может быть удалена (заголовок или автоматически сгенерированная)";
                return;
            }
        }
        
        qDebug() << "DocumentEditWidget::onRemoveRow: Удаляем строку" << row;
        
        // Получаем контроллер и удаляем строку
        if (m_controller && m_controller->vedomostController()) {
            m_controller->vedomostController()->removeRow(row);
            qDebug() << "DocumentEditWidget::onRemoveRow: Строка удалена через VedomostController";
        } else {
            qDebug() << "DocumentEditWidget::onRemoveRow: VedomostController недоступен";
        }
        return;
    }
    
    qDebug() << "DocumentEditWidget::onRemoveRow: Процессор не поддерживает удаление строк";
}

// Слот для обновления состояния кнопок
void DocumentEditWidget::onSelectionChanged()
{
    int selectedRow = getCurrentSelectedRow();
    bool hasSelection = selectedRow != -1;
    
    // Кнопки активны только когда есть выбранная строка
    m_insertRowButton->setEnabled(hasSelection);
    m_removeRowButton->setEnabled(hasSelection);
    
    qDebug() << "DocumentEditWidget::onSelectionChanged: Выбрана строка" << selectedRow 
             << "кнопки вставки и удаления" << (hasSelection ? "активны" : "неактивны");
}

// Вспомогательные методы
int DocumentEditWidget::getCurrentSelectedRow() const
{
    QModelIndex currentIndex = m_tableView->currentIndex();
    if (currentIndex.isValid()) {
        return currentIndex.row();
    }
    return -1; // Нет выбранной строки
}

void DocumentEditWidget::setupSelectionConnection()
{
    // Отключаем предыдущее соединение, если оно есть
    disconnect(m_tableView->selectionModel(), &QItemSelectionModel::selectionChanged, 
              this, &DocumentEditWidget::onSelectionChanged);
    
    // Устанавливаем новое соединение
    if (m_tableView->selectionModel()) {
        connect(m_tableView->selectionModel(), &QItemSelectionModel::selectionChanged, 
                this, &DocumentEditWidget::onSelectionChanged);
        qDebug() << "DocumentEditWidget::setupSelectionConnection: Соединение selectionChanged установлено";
        
        // Обновляем состояние кнопок сразу после установки соединения
        onSelectionChanged();
    } else {
        qDebug() << "DocumentEditWidget::setupSelectionConnection: selectionModel недоступен";
    }
}

 


void DocumentEditWidget::applyColumnStretching()
{
    qDebug() << "DocumentEditWidget::applyColumnStretching: Применяем настройки растягивания столбцов";
    
    if (!m_tableView || !m_tableView->model()) {
        qDebug() << "DocumentEditWidget::applyColumnStretching: Таблица или модель недоступны";
        return;
    }
    
    // Проверяем тип процессора и применяем соответствующие настройки
    PerechenProcessor *perechenProcessor = qobject_cast<PerechenProcessor*>(m_processor);
    if (perechenProcessor) {
        // Настройки для Perechen (Перечень элементов)
        QHeaderView *horizontalHeader = m_tableView->horizontalHeader();
        
        // Отключаем автоматическое изменение размера по содержимому
        horizontalHeader->setStretchLastSection(false);
        
        // Устанавливаем режимы для каждого столбца - все интерактивные (изменяемые по ширине)
        horizontalHeader->setSectionResizeMode(0, QHeaderView::Interactive); // Поз.обозначение
        horizontalHeader->setSectionResizeMode(1, QHeaderView::Interactive); // Наименование
        horizontalHeader->setSectionResizeMode(2, QHeaderView::Interactive); // Кол.
        horizontalHeader->setSectionResizeMode(3, QHeaderView::Interactive); // Примечание
        
        // Устанавливаем начальные размеры для столбцов
        horizontalHeader->resizeSection(0, 100); // Поз.обозначение - 100px
        horizontalHeader->resizeSection(1, 200); // Наименование - 200px
        horizontalHeader->resizeSection(2, 60);  // Кол. - 60px
        horizontalHeader->resizeSection(3, 150); // Примечание - 150px
        
        // Принудительно обновляем размеры столбцов
        //horizontalHeader->resizeSections();
        
        qDebug() << "DocumentEditWidget::applyColumnStretching: Настройки для Perechen применены";
        return;
    }
    
    SpecificationProcessor *specProcessor = qobject_cast<SpecificationProcessor*>(m_processor);
    if (specProcessor) {
        // Настройки для Specification (Спецификация)
        QHeaderView *horizontalHeader = m_tableView->horizontalHeader();

        horizontalHeader->setStretchLastSection(false);

        horizontalHeader->setSectionResizeMode(0, QHeaderView::Interactive); // Формат
        horizontalHeader->setSectionResizeMode(1, QHeaderView::Interactive); // Зона
        horizontalHeader->setSectionResizeMode(2, QHeaderView::Interactive); // Поз.
        horizontalHeader->setSectionResizeMode(3, QHeaderView::Interactive); // Обозначение
        horizontalHeader->setSectionResizeMode(4, QHeaderView::Interactive); // Наименование
        horizontalHeader->setSectionResizeMode(5, QHeaderView::Interactive); // Количество
        horizontalHeader->setSectionResizeMode(6, QHeaderView::Interactive); // Примечание

        horizontalHeader->resizeSection(0, 60);  // Формат - 60px
        horizontalHeader->resizeSection(1, 50);  // Зона - 50px
        horizontalHeader->resizeSection(2, 80);  // Поз. - 80px
        horizontalHeader->resizeSection(3, 150); // Обозначение - 150px
        horizontalHeader->resizeSection(4, 200); // Наименование - 200px
        horizontalHeader->resizeSection(5, 60);  // Количество - 60px
        horizontalHeader->resizeSection(6, 150); // Примечание - 150px
        
      //  horizontalHeader->resizeSections();
        
        qDebug() << "DocumentEditWidget::applyColumnStretching: Настройки для Specification применены";
        return;
    }
    
    SpecificationPCBProcessor *specPCBProcessor = qobject_cast<SpecificationPCBProcessor*>(m_processor);
    if (specPCBProcessor) {
        // Настройки для SpecificationPCB (Спецификация ПП)
        QHeaderView *horizontalHeader = m_tableView->horizontalHeader();
        
        horizontalHeader->setStretchLastSection(false);
        
        horizontalHeader->setSectionResizeMode(0, QHeaderView::Interactive); // Формат
        horizontalHeader->setSectionResizeMode(1, QHeaderView::Interactive); // Зона
        horizontalHeader->setSectionResizeMode(2, QHeaderView::Interactive); // Поз.
        horizontalHeader->setSectionResizeMode(3, QHeaderView::Interactive); // Обозначение
        horizontalHeader->setSectionResizeMode(4, QHeaderView::Interactive); // Наименование
        horizontalHeader->setSectionResizeMode(5, QHeaderView::Interactive); // Количество
        horizontalHeader->setSectionResizeMode(6, QHeaderView::Interactive); // Примечание
        
        horizontalHeader->resizeSection(0, 60);  // Формат - 60px
        horizontalHeader->resizeSection(1, 50);  // Зона - 50px
        horizontalHeader->resizeSection(2, 80);  // Поз. - 80px
        horizontalHeader->resizeSection(3, 150); // Обозначение - 150px
        horizontalHeader->resizeSection(4, 200); // Наименование - 200px
        horizontalHeader->resizeSection(5, 60);  // Количество - 60px
        horizontalHeader->resizeSection(6, 150); // Примечание - 150px
        
        //horizontalHeader->resizeSections();
        
        qDebug() << "DocumentEditWidget::applyColumnStretching: Настройки для SpecificationPCB применены";
        return;
    }
    
    VedomostProcessor *vedomostProcessor = qobject_cast<VedomostProcessor*>(m_processor);
    if (vedomostProcessor) {
        // Настройки для Vedomost (Ведомость покупных изделий) - 10 колонок
        QHeaderView *horizontalHeader = m_tableView->horizontalHeader();
        
        horizontalHeader->setStretchLastSection(false);
        
        horizontalHeader->setSectionResizeMode(0, QHeaderView::Interactive); // Наименование
        horizontalHeader->setSectionResizeMode(1, QHeaderView::Interactive); // Код продукции
        horizontalHeader->setSectionResizeMode(2, QHeaderView::Interactive); // Обозначение документа на поставку
        horizontalHeader->setSectionResizeMode(3, QHeaderView::Interactive); // Поставщик
        horizontalHeader->setSectionResizeMode(4, QHeaderView::Interactive); // Куда входит (обозначение)
        horizontalHeader->setSectionResizeMode(5, QHeaderView::Interactive); // Количество на изделие
        horizontalHeader->setSectionResizeMode(6, QHeaderView::Interactive); // Количество в комплекте
        horizontalHeader->setSectionResizeMode(7, QHeaderView::Interactive); // Количество на регулир
        horizontalHeader->setSectionResizeMode(8, QHeaderView::Interactive); // Количество всего
        horizontalHeader->setSectionResizeMode(9, QHeaderView::Interactive); // Примечание
        
        horizontalHeader->resizeSection(0, 200); // Наименование - 200px
        horizontalHeader->resizeSection(1, 120); // Код продукции - 120px
        horizontalHeader->resizeSection(2, 150); // Обозначение документа на поставку - 150px
        horizontalHeader->resizeSection(3, 100); // Поставщик - 100px
        horizontalHeader->resizeSection(4, 120); // Куда входит (обозначение) - 120px
        horizontalHeader->resizeSection(5, 100); // Количество на изделие - 100px
        horizontalHeader->resizeSection(6, 100); // Количество в комплекте - 100px
        horizontalHeader->resizeSection(7, 100); // Количество на регулир - 100px
        horizontalHeader->resizeSection(8, 100); // Количество всего - 100px
        horizontalHeader->resizeSection(9, 150); // Примечание - 150px
        
        qDebug() << "DocumentEditWidget::applyColumnStretching: Настройки для Vedomost применены";
        return;
    }
    
    qDebug() << "DocumentEditWidget::applyColumnStretching: Неизвестный тип процессора";
}

void DocumentEditWidget::onContextMenuRequested(const QPoint &pos)
{
    QModelIndex index = m_tableView->indexAt(pos);
    if (!index.isValid()) {
        return;
    }
    
    int row = index.row();
    
    // Получаем выделенные строки
    QItemSelectionModel *selectionModel = m_tableView->selectionModel();
    QModelIndexList selectedRows = selectionModel->selectedRows();
    int selectedCount = selectedRows.size();
    
    QMenu contextMenu(this);
    
    QAction *addRowAction = contextMenu.addAction("Добавить пустую строку");
    connect(addRowAction, &QAction::triggered, this, &DocumentEditWidget::onContextMenuAddRow);
    
    // Показываем либо "Удалить строку", либо "Удалить n строк" в зависимости от количества выделенных
    QAction *removeRowAction;
    if (selectedCount > 1) {
        removeRowAction = contextMenu.addAction(QString("Удалить %1 строк").arg(selectedCount));
        connect(removeRowAction, &QAction::triggered, this, &DocumentEditWidget::onContextMenuRemoveSelectedRows);
    } else {
        removeRowAction = contextMenu.addAction("Удалить строку");
        connect(removeRowAction, &QAction::triggered, this, &DocumentEditWidget::onContextMenuRemoveRow);
    }
    
    // Добавляем подменю "Объединить" если выбрано несколько строк
    if (selectedCount > 1) {
        contextMenu.addSeparator();
        QMenu *mergeMenu = contextMenu.addMenu(QString("Объединить %1 строк").arg(selectedCount));
        
        QAction *mergeAllAction = mergeMenu->addAction("Объединить все");
        connect(mergeAllAction, &QAction::triggered, this, &DocumentEditWidget::onContextMenuMergeRows);
        
        // Получаем столбец, на котором был клик
        int clickedColumn = index.column();
        QString columnName = m_tableView->model()->headerData(clickedColumn, Qt::Horizontal, Qt::DisplayRole).toString();
        if (columnName.isEmpty()) {
            columnName = QString("Столбец %1").arg(clickedColumn + 1);
        }
        
        QAction *mergeColumnAction = mergeMenu->addAction(QString("Объединить только \"%1\"").arg(columnName));
        // Сохраняем номер столбца в данных действия для использования в слоте
        mergeColumnAction->setData(clickedColumn);
        connect(mergeColumnAction, &QAction::triggered, this, &DocumentEditWidget::onContextMenuMergeColumn);
    }
    
    contextMenu.addSeparator();
    
    // Меню для работы со строками
    QMenu *rowsMenu = contextMenu.addMenu("Строки");
    QAction *copyRowsAction = rowsMenu->addAction("Копировать строки");
    copyRowsAction->setEnabled(selectedCount > 0);
    connect(copyRowsAction, &QAction::triggered, this, &DocumentEditWidget::onContextMenuCopyRows);
    
    QAction *cutRowsAction = rowsMenu->addAction("Вырезать строки");
    cutRowsAction->setEnabled(selectedCount > 0);
    connect(cutRowsAction, &QAction::triggered, this, &DocumentEditWidget::onContextMenuCutRows);
    
    QAction *pasteRowsAction = rowsMenu->addAction("Вставить строки");
    QClipboard *clipboard = QApplication::clipboard();
    const QMimeData *mimeData = clipboard->mimeData();
    pasteRowsAction->setEnabled(mimeData && mimeData->hasText());
    connect(pasteRowsAction, &QAction::triggered, this, &DocumentEditWidget::onContextMenuPasteRows);
    
    // Меню для работы с ячейками
    QMenu *cellsMenu = contextMenu.addMenu("Ячейки");
    QItemSelection cellSelection = selectionModel->selection();
    bool hasCellSelection = !cellSelection.isEmpty();
    
    QAction *copyCellsAction = cellsMenu->addAction("Копировать ячейки");
    copyCellsAction->setEnabled(hasCellSelection);
    connect(copyCellsAction, &QAction::triggered, this, &DocumentEditWidget::onContextMenuCopyCells);
    
    QAction *cutCellsAction = cellsMenu->addAction("Вырезать ячейки");
    cutCellsAction->setEnabled(hasCellSelection);
    connect(cutCellsAction, &QAction::triggered, this, &DocumentEditWidget::onContextMenuCutCells);
    
    QAction *pasteCellsAction = cellsMenu->addAction("Вставить ячейки");
    pasteCellsAction->setEnabled(mimeData && mimeData->hasText());
    connect(pasteCellsAction, &QAction::triggered, this, &DocumentEditWidget::onContextMenuPasteCells);
    
    contextMenu.addSeparator();
    
    QAction *cellSettingsAction = contextMenu.addAction("Настройка ячейки...");
    connect(cellSettingsAction, &QAction::triggered, this, &DocumentEditWidget::onContextMenuCellSettings);
    
    contextMenu.exec(m_tableView->viewport()->mapToGlobal(pos));
}

void DocumentEditWidget::onContextMenuAddRow()
{
    QModelIndex index = m_tableView->currentIndex();
    if (!index.isValid()) {
        return;
    }
    
    int row = index.row();
    
    // Добавляем пустую строку после текущей
    PerechenProcessor *perechenProcessor = qobject_cast<PerechenProcessor*>(m_processor);
    if (perechenProcessor && m_controller && m_controller->perechenTableController()) {
        m_controller->perechenTableController()->addEmptyRowAt(row + 1);
    }
    
    SpecificationPCBProcessor *specPCBProcessor = qobject_cast<SpecificationPCBProcessor*>(m_processor);
    if (specPCBProcessor && m_controller && m_controller->specificationPCBController()) {
        m_controller->specificationPCBController()->addEmptyRowAt(row + 1);
    }
    
    SpecificationProcessor *specProcessor = qobject_cast<SpecificationProcessor*>(m_processor);
    if (specProcessor && m_controller && m_controller->specificationController()) {
        m_controller->specificationController()->addEmptyRowAt(row + 1);
    }
    
    VedomostProcessor *vedomostProcessor = qobject_cast<VedomostProcessor*>(m_processor);
    if (vedomostProcessor && m_controller && m_controller->vedomostController()) {
        m_controller->vedomostController()->addEmptyRowAt(row + 1);
    }
}

void DocumentEditWidget::onContextMenuRemoveRow()
{
    QModelIndex index = m_tableView->currentIndex();
    if (!index.isValid()) {
        return;
    }
    
    int row = index.row();
    onRemoveRow();
}

void DocumentEditWidget::onContextMenuRemoveSelectedRows()
{
    // Получаем выделенные строки
    QItemSelectionModel *selectionModel = m_tableView->selectionModel();
    QModelIndexList selectedRows = selectionModel->selectedRows();
    
    if (selectedRows.isEmpty()) {
        return;
    }
    
    // Собираем номера строк и сортируем в обратном порядке (для корректного удаления)
    QList<int> rowsToDelete;
    for (const QModelIndex &index : selectedRows) {
        if (index.isValid()) {
            rowsToDelete.append(index.row());
        }
    }
    
    // Удаляем дубликаты и сортируем в обратном порядке
    std::sort(rowsToDelete.begin(), rowsToDelete.end());
    rowsToDelete.erase(std::unique(rowsToDelete.begin(), rowsToDelete.end()), rowsToDelete.end());
    std::reverse(rowsToDelete.begin(), rowsToDelete.end());
    
    int count = rowsToDelete.size();
    
    // Запрашиваем подтверждение
    QMessageBox::StandardButton reply = QMessageBox::question(
        this,
        tr("Подтверждение удаления"),
        tr("Вы уверены, что хотите удалить %1 строк?").arg(count),
        QMessageBox::Yes | QMessageBox::No
    );
    
    if (reply != QMessageBox::Yes) {
        return;
    }
    
    // Удаляем строки в обратном порядке (чтобы индексы не сбивались)
    for (int row : rowsToDelete) {
        // Проверяем, можно ли удалить эту строку
        bool canDelete = true;
        
        // Проверяем для каждого типа процессора
        PerechenProcessor *perechenProcessor = qobject_cast<PerechenProcessor*>(m_processor);
        if (perechenProcessor && m_controller && m_controller->perechenTableModel()) {
            canDelete = m_controller->perechenTableModel()->canEditRow(row);
        }
        
        SpecificationPCBProcessor *specPCBProcessor = qobject_cast<SpecificationPCBProcessor*>(m_processor);
        if (specPCBProcessor && m_controller && m_controller->specificationPCBTableModel()) {
            canDelete = m_controller->specificationPCBTableModel()->canEditRow(row);
        }
        
        SpecificationProcessor *specProcessor = qobject_cast<SpecificationProcessor*>(m_processor);
        if (specProcessor && m_controller && m_controller->specificationTableModel()) {
            canDelete = m_controller->specificationTableModel()->canEditRow(row);
        }
        
        VedomostProcessor *vedomostProcessor = qobject_cast<VedomostProcessor*>(m_processor);
        if (vedomostProcessor && m_controller && m_controller->vedomostTableModel()) {
            canDelete = m_controller->vedomostTableModel()->canEditRow(row);
        }
        
        if (!canDelete) {
            qDebug() << "DocumentEditWidget::onContextMenuRemoveSelectedRows: Строка" << row << "не может быть удалена (заголовок или автоматически сгенерированная)";
            continue;
        }
        
        // Удаляем строку через соответствующий контроллер
        if (perechenProcessor && m_controller && m_controller->perechenTableController()) {
            m_controller->perechenTableController()->removeRow(row);
        } else if (specPCBProcessor && m_controller && m_controller->specificationPCBController()) {
            m_controller->specificationPCBController()->removeRow(row);
        } else if (specProcessor && m_controller && m_controller->specificationController()) {
            m_controller->specificationController()->removeRow(row);
        } else if (vedomostProcessor && m_controller && m_controller->vedomostController()) {
            m_controller->vedomostController()->removeRow(row);
        }
    }
    
    qDebug() << "DocumentEditWidget::onContextMenuRemoveSelectedRows: Удалено строк:" << count;
}

void DocumentEditWidget::onContextMenuMergeRows()
{
    // Получаем выделенные строки
    QItemSelectionModel *selectionModel = m_tableView->selectionModel();
    QModelIndexList selectedRows = selectionModel->selectedRows();
    
    if (selectedRows.size() < 2) {
        return; // Нужно минимум 2 строки для объединения
    }
    
    // Собираем номера строк и сортируем
    QList<int> rowsToMerge;
    for (const QModelIndex &index : selectedRows) {
        if (index.isValid()) {
            rowsToMerge.append(index.row());
        }
    }
    
    // Удаляем дубликаты и сортируем
    std::sort(rowsToMerge.begin(), rowsToMerge.end());
    rowsToMerge.erase(std::unique(rowsToMerge.begin(), rowsToMerge.end()), rowsToMerge.end());
    
    if (rowsToMerge.size() < 2) {
        return;
    }
    
    int firstRow = rowsToMerge.first();
    int columnCount = m_tableView->model()->columnCount();
    
    // Объединяем содержимое ячеек для каждой колонки
    for (int col = 0; col < columnCount; ++col) {
        QStringList mergedValues;
        
        // Собираем значения из всех выбранных строк
        for (int row : rowsToMerge) {
            QModelIndex cellIndex = m_tableView->model()->index(row, col);
            if (cellIndex.isValid()) {
                QString cellValue = m_tableView->model()->data(cellIndex, Qt::DisplayRole).toString().trimmed();
                if (!cellValue.isEmpty()) {
                    mergedValues.append(cellValue);
                }
            }
        }
        
        // Объединяем значения через пробел
        QString mergedValue = mergedValues.join(" ");
        
        // Записываем объединенное значение в первую строку
        QModelIndex firstCellIndex = m_tableView->model()->index(firstRow, col);
        if (firstCellIndex.isValid()) {
            // Сохраняем CellData из первой строки (если есть)
            QVariant originalCellData = m_tableView->model()->data(firstCellIndex, Qt::UserRole);
            
            // Устанавливаем новое значение
            m_tableView->model()->setData(firstCellIndex, mergedValue, Qt::EditRole);
            
            // Если была структура CellData, обновляем значение в ней
            if (originalCellData.isValid()) {
                if (originalCellData.canConvert<PerechenCellData>()) {
                    PerechenCellData cell = originalCellData.value<PerechenCellData>();
                    cell.value = mergedValue;
                    m_tableView->model()->setData(firstCellIndex, QVariant::fromValue(cell), Qt::UserRole);
                } else if (originalCellData.canConvert<SpecificationPCBCellData>()) {
                    SpecificationPCBCellData cell = originalCellData.value<SpecificationPCBCellData>();
                    cell.value = mergedValue;
                    m_tableView->model()->setData(firstCellIndex, QVariant::fromValue(cell), Qt::UserRole);
                } else if (originalCellData.canConvert<SpecificationCellData>()) {
                    SpecificationCellData cell = originalCellData.value<SpecificationCellData>();
                    cell.value = mergedValue;
                    m_tableView->model()->setData(firstCellIndex, QVariant::fromValue(cell), Qt::UserRole);
                } else if (originalCellData.canConvert<VedomostCellData>()) {
                    VedomostCellData cell = originalCellData.value<VedomostCellData>();
                    cell.value = mergedValue;
                    m_tableView->model()->setData(firstCellIndex, QVariant::fromValue(cell), Qt::UserRole);
                }
            }
        }
    }
    
    // Удаляем остальные строки в обратном порядке (чтобы индексы не сбивались)
    QList<int> rowsToDelete = rowsToMerge;
    rowsToDelete.removeFirst(); // Не удаляем первую строку
    std::reverse(rowsToDelete.begin(), rowsToDelete.end());
    
    // Удаляем строки через соответствующий контроллер
    for (int row : rowsToDelete) {
        // Проверяем, можно ли удалить эту строку
        bool canDelete = true;
        
        PerechenProcessor *perechenProcessor = qobject_cast<PerechenProcessor*>(m_processor);
        if (perechenProcessor && m_controller && m_controller->perechenTableModel()) {
            canDelete = m_controller->perechenTableModel()->canEditRow(row);
        }
        
        SpecificationPCBProcessor *specPCBProcessor = qobject_cast<SpecificationPCBProcessor*>(m_processor);
        if (specPCBProcessor && m_controller && m_controller->specificationPCBTableModel()) {
            canDelete = m_controller->specificationPCBTableModel()->canEditRow(row);
        }
        
        SpecificationProcessor *specProcessor = qobject_cast<SpecificationProcessor*>(m_processor);
        if (specProcessor && m_controller && m_controller->specificationTableModel()) {
            canDelete = m_controller->specificationTableModel()->canEditRow(row);
        }
        
        VedomostProcessor *vedomostProcessor = qobject_cast<VedomostProcessor*>(m_processor);
        if (vedomostProcessor && m_controller && m_controller->vedomostTableModel()) {
            canDelete = m_controller->vedomostTableModel()->canEditRow(row);
        }
        
        if (!canDelete) {
            qDebug() << "DocumentEditWidget::onContextMenuMergeRows: Строка" << row << "не может быть удалена (заголовок или автоматически сгенерированная)";
            continue;
        }
        
        // Удаляем строку через соответствующий контроллер
        if (perechenProcessor && m_controller && m_controller->perechenTableController()) {
            m_controller->perechenTableController()->removeRow(row);
        } else if (specPCBProcessor && m_controller && m_controller->specificationPCBController()) {
            m_controller->specificationPCBController()->removeRow(row);
        } else if (specProcessor && m_controller && m_controller->specificationController()) {
            m_controller->specificationController()->removeRow(row);
        } else if (vedomostProcessor && m_controller && m_controller->vedomostController()) {
            m_controller->vedomostController()->removeRow(row);
        }
    }
    
    qDebug() << "DocumentEditWidget::onContextMenuMergeRows: Объединено строк:" << rowsToMerge.size() << "в строку" << firstRow;
}

void DocumentEditWidget::onContextMenuMergeColumn()
{
    // Получаем выделенные строки
    QItemSelectionModel *selectionModel = m_tableView->selectionModel();
    QModelIndexList selectedRows = selectionModel->selectedRows();
    
    if (selectedRows.size() < 2) {
        return; // Нужно минимум 2 строки для объединения
    }
    
    // Получаем столбец из действия, которое вызвало слот
    QAction *action = qobject_cast<QAction*>(sender());
    if (!action) {
        return;
    }
    
    int targetColumn = action->data().toInt();
    if (targetColumn < 0) {
        return;
    }
    
    // Собираем номера строк и сортируем
    QList<int> rowsToMerge;
    for (const QModelIndex &index : selectedRows) {
        if (index.isValid()) {
            rowsToMerge.append(index.row());
        }
    }
    
    // Удаляем дубликаты и сортируем
    std::sort(rowsToMerge.begin(), rowsToMerge.end());
    rowsToMerge.erase(std::unique(rowsToMerge.begin(), rowsToMerge.end()), rowsToMerge.end());
    
    if (rowsToMerge.size() < 2) {
        return;
    }
    
    int firstRow = rowsToMerge.first();
    
    // Объединяем содержимое ячеек только для выбранного столбца
    QStringList mergedValues;
    
    // Собираем значения из всех выбранных строк для выбранного столбца
    for (int row : rowsToMerge) {
        QModelIndex cellIndex = m_tableView->model()->index(row, targetColumn);
        if (cellIndex.isValid()) {
            QString cellValue = m_tableView->model()->data(cellIndex, Qt::DisplayRole).toString().trimmed();
            if (!cellValue.isEmpty()) {
                mergedValues.append(cellValue);
            }
        }
    }
    
    // Объединяем значения через пробел
    QString mergedValue = mergedValues.join(" ");
    
    // Записываем объединенное значение в первую строку
    QModelIndex firstCellIndex = m_tableView->model()->index(firstRow, targetColumn);
    if (firstCellIndex.isValid()) {
        // Сохраняем CellData из первой строки (если есть)
        QVariant originalCellData = m_tableView->model()->data(firstCellIndex, Qt::UserRole);
        
        // Устанавливаем новое значение
        m_tableView->model()->setData(firstCellIndex, mergedValue, Qt::EditRole);
        
        // Если была структура CellData, обновляем значение в ней
        if (originalCellData.isValid()) {
            if (originalCellData.canConvert<PerechenCellData>()) {
                PerechenCellData cell = originalCellData.value<PerechenCellData>();
                cell.value = mergedValue;
                m_tableView->model()->setData(firstCellIndex, QVariant::fromValue(cell), Qt::UserRole);
            } else if (originalCellData.canConvert<SpecificationPCBCellData>()) {
                SpecificationPCBCellData cell = originalCellData.value<SpecificationPCBCellData>();
                cell.value = mergedValue;
                m_tableView->model()->setData(firstCellIndex, QVariant::fromValue(cell), Qt::UserRole);
            } else if (originalCellData.canConvert<SpecificationCellData>()) {
                SpecificationCellData cell = originalCellData.value<SpecificationCellData>();
                cell.value = mergedValue;
                m_tableView->model()->setData(firstCellIndex, QVariant::fromValue(cell), Qt::UserRole);
            } else if (originalCellData.canConvert<VedomostCellData>()) {
                VedomostCellData cell = originalCellData.value<VedomostCellData>();
                cell.value = mergedValue;
                m_tableView->model()->setData(firstCellIndex, QVariant::fromValue(cell), Qt::UserRole);
            }
        }
    }
    
    // Очищаем значения в остальных строках для выбранного столбца
    QList<int> rowsToClear = rowsToMerge;
    rowsToClear.removeFirst(); // Не очищаем первую строку
    
    for (int row : rowsToClear) {
        QModelIndex cellIndex = m_tableView->model()->index(row, targetColumn);
        if (cellIndex.isValid()) {
            // Очищаем значение, но сохраняем структуру CellData
            QVariant originalCellData = m_tableView->model()->data(cellIndex, Qt::UserRole);
            
            m_tableView->model()->setData(cellIndex, "", Qt::EditRole);
            
            // Обновляем значение в CellData, если оно есть
            if (originalCellData.isValid()) {
                if (originalCellData.canConvert<PerechenCellData>()) {
                    PerechenCellData cell = originalCellData.value<PerechenCellData>();
                    cell.value = "";
                    m_tableView->model()->setData(cellIndex, QVariant::fromValue(cell), Qt::UserRole);
                } else if (originalCellData.canConvert<SpecificationPCBCellData>()) {
                    SpecificationPCBCellData cell = originalCellData.value<SpecificationPCBCellData>();
                    cell.value = "";
                    m_tableView->model()->setData(cellIndex, QVariant::fromValue(cell), Qt::UserRole);
                } else if (originalCellData.canConvert<SpecificationCellData>()) {
                    SpecificationCellData cell = originalCellData.value<SpecificationCellData>();
                    cell.value = "";
                    m_tableView->model()->setData(cellIndex, QVariant::fromValue(cell), Qt::UserRole);
                } else if (originalCellData.canConvert<VedomostCellData>()) {
                    VedomostCellData cell = originalCellData.value<VedomostCellData>();
                    cell.value = "";
                    m_tableView->model()->setData(cellIndex, QVariant::fromValue(cell), Qt::UserRole);
                }
            }
        }
    }
    
    qDebug() << "DocumentEditWidget::onContextMenuMergeColumn: Объединен столбец" << targetColumn 
             << "для строк:" << rowsToMerge.size() << "в строку" << firstRow;
}

void DocumentEditWidget::onContextMenuCellSettings()
{
    QModelIndex index = m_tableView->currentIndex();
    if (!index.isValid()) {
        return;
    }
    
    int row = index.row();
    int column = index.column();
    
    // Получаем название ячейки из заголовка
    QString cellName = m_tableView->model()->headerData(column, Qt::Horizontal, Qt::DisplayRole).toString();
    if (cellName.isEmpty()) {
        cellName = QString("Колонка %1").arg(column + 1);
    }
    
    // Получаем текущие значения из модели
    int currentStretch = 100;
    bool currentIsHeader = false;
    bool currentIsUnderline = true;
    QVariant cellData = m_tableView->model()->data(index, Qt::UserRole);
    if (cellData.isValid()) {
        // Извлекаем значения из CellData
        if (cellData.canConvert<PerechenCellData>()) {
            PerechenCellData cell = cellData.value<PerechenCellData>();
            currentStretch = cell.stretch;
            currentIsHeader = cell.isHeader;
            currentIsUnderline = cell.isUnderline;
        } else if (cellData.canConvert<SpecificationPCBCellData>()) {
            SpecificationPCBCellData cell = cellData.value<SpecificationPCBCellData>();
            currentStretch = cell.stretch;
            currentIsHeader = cell.isHeader;
            currentIsUnderline = cell.isUnderline;
        } else if (cellData.canConvert<SpecificationCellData>()) {
            SpecificationCellData cell = cellData.value<SpecificationCellData>();
            currentStretch = cell.stretch;
            currentIsHeader = cell.isHeader;
            currentIsUnderline = cell.isUnderline;
        } else if (cellData.canConvert<VedomostCellData>()) {
            VedomostCellData cell = cellData.value<VedomostCellData>();
            currentStretch = cell.stretch;
            currentIsHeader = cell.isHeader;
            currentIsUnderline = cell.isUnderline;
        }
    }
    
    // Создаем диалог настройки ячейки
    CellSettingsDialog dialog(row, column, cellName, currentStretch, currentIsHeader, currentIsUnderline, this);
    
    if (dialog.exec() == QDialog::Accepted) {
        int newStretch = dialog.getStretch();
        bool newIsHeader = dialog.isHeader();
        bool newIsUnderline = dialog.isUnderline();
        qDebug() << "DocumentEditWidget::onContextMenuCellSettings: Установлены настройки для ячейки row=" << row << "column=" << column
                 << "stretch=" << newStretch << "isHeader=" << newIsHeader << "isUnderline=" << newIsUnderline;
        
        // Обновляем настройки в соответствующей модели
        bool success = false;
        PerechenTableModel *perechenModel = getPerechenTableModel();
        if (perechenModel) {
            // Вызываем все три метода независимо - они вернут true, если значение изменилось
            perechenModel->setCellStretch(row, column, newStretch);
            perechenModel->setCellHeader(row, column, newIsHeader);
            perechenModel->setCellUnderline(row, column, newIsUnderline);
            success = true; // Всегда успех, если модель доступна
        } else {
            SpecificationPCBTableModel *specPCBModel = getSpecificationPCBTableModel();
            if (specPCBModel) {
                // Вызываем все три метода независимо - они вернут true, если значение изменилось
                specPCBModel->setCellStretch(row, column, newStretch);
                specPCBModel->setCellHeader(row, column, newIsHeader);
                specPCBModel->setCellUnderline(row, column, newIsUnderline);
                success = true; // Всегда успех, если модель доступна
            } else {
                SpecificationTableModel *specModel = getSpecificationTableModel();
                if (specModel) {
                    // Вызываем все три метода независимо - они вернут true, если значение изменилось
                    specModel->setCellStretch(row, column, newStretch);
                    specModel->setCellHeader(row, column, newIsHeader);
                    specModel->setCellUnderline(row, column, newIsUnderline);
                    success = true; // Всегда успех, если модель доступна
                } else {
                    VedomostTableModel *vedomostModel = getVedomostTableModel();
                    if (vedomostModel) {
                        // Вызываем все три метода независимо - они вернут true, если значение изменилось
                        vedomostModel->setCellStretch(row, column, newStretch);
                        vedomostModel->setCellHeader(row, column, newIsHeader);
                        vedomostModel->setCellUnderline(row, column, newIsUnderline);
                        success = true; // Всегда успех, если модель доступна
                    }
                }
            }
        }
        
        if (success) {
            qDebug() << "DocumentEditWidget::onContextMenuCellSettings: Настройки успешно сохранены в модель";
        } else {
            qDebug() << "DocumentEditWidget::onContextMenuCellSettings: Ошибка при сохранении настроек в модель - модель не найдена";
        }
    }
}

// Методы для копирования/вставки/вырезания строк
void DocumentEditWidget::onContextMenuCopyRows()
{
    QItemSelectionModel *selectionModel = m_tableView->selectionModel();
    QModelIndexList selectedRows = selectionModel->selectedRows();
    
    if (selectedRows.isEmpty()) {
        return;
    }
    
    copyRowsToClipboard(selectedRows);
}

void DocumentEditWidget::onContextMenuCutRows()
{
    QItemSelectionModel *selectionModel = m_tableView->selectionModel();
    QModelIndexList selectedRows = selectionModel->selectedRows();
    
    if (selectedRows.isEmpty()) {
        return;
    }
    
    QModelIndex currentIndex = m_tableView->currentIndex();
    int insertPosition = currentIndex.isValid() ? currentIndex.row() : -1;
    
    cutRows(insertPosition);
}

void DocumentEditWidget::onContextMenuPasteRows()
{
    QModelIndex currentIndex = m_tableView->currentIndex();
    int insertPosition = currentIndex.isValid() ? currentIndex.row() + 1 : -1;
    
    if (insertPosition < 0) {
        // Если нет текущей позиции, вставляем в конец
        QAbstractItemModel *model = m_tableView->model();
        if (model) {
            insertPosition = model->rowCount();
        } else {
            return;
        }
    }
    
    pasteRowsFromClipboard(insertPosition);
}

// Методы для копирования/вставки/вырезания ячеек
void DocumentEditWidget::onContextMenuCopyCells()
{
    QItemSelectionModel *selectionModel = m_tableView->selectionModel();
    QItemSelection selection = selectionModel->selection();
    
    if (selection.isEmpty()) {
        return;
    }
    
    copyCellsToClipboard(selection);
}

void DocumentEditWidget::onContextMenuCutCells()
{
    QModelIndex currentIndex = m_tableView->currentIndex();
    
    if (!currentIndex.isValid()) {
        return;
    }
    
    cutCells(currentIndex);
}

void DocumentEditWidget::onContextMenuPasteCells()
{
    QModelIndex currentIndex = m_tableView->currentIndex();
    
    if (!currentIndex.isValid()) {
        return;
    }
    
    pasteCellsFromClipboard(currentIndex);
}

// Вспомогательные методы для копирования/вставки строк
void DocumentEditWidget::copyRowsToClipboard(const QModelIndexList &rows)
{
    if (rows.isEmpty() || !m_tableView->model()) {
        return;
    }
    
    QAbstractItemModel *model = m_tableView->model();
    int columnCount = model->columnCount();
    
    // Собираем номера строк и сортируем их
    QList<int> rowNumbers;
    for (const QModelIndex &index : rows) {
        if (index.isValid()) {
            rowNumbers.append(index.row());
        }
    }
    std::sort(rowNumbers.begin(), rowNumbers.end());
    rowNumbers.erase(std::unique(rowNumbers.begin(), rowNumbers.end()), rowNumbers.end());
    
    // Формируем текст в формате CSV (табуляция для разделения столбцов, перенос строки для строк)
    QStringList rowTexts;
    for (int row : rowNumbers) {
        QStringList cellTexts;
        for (int col = 0; col < columnCount; ++col) {
            QModelIndex cellIndex = model->index(row, col);
            QString cellText = model->data(cellIndex, Qt::DisplayRole).toString();
            // Заменяем переносы строк и табуляции на пробелы для совместимости
            cellText.replace('\n', ' ').replace('\r', ' ').replace('\t', ' ');
            cellTexts.append(cellText);
        }
        rowTexts.append(cellTexts.join("\t"));
    }
    
    QString clipboardText = rowTexts.join("\n");
    
    // Копируем в буфер обмена
    QClipboard *clipboard = QApplication::clipboard();
    clipboard->setText(clipboardText);
    
    qDebug() << "DocumentEditWidget::copyRowsToClipboard: Скопировано строк:" << rowNumbers.size();
}

void DocumentEditWidget::pasteRowsFromClipboard(int insertPosition)
{
    QClipboard *clipboard = QApplication::clipboard();
    QString clipboardText = clipboard->text();
    
    if (clipboardText.isEmpty()) {
        return;
    }
    
    QAbstractItemModel *model = m_tableView->model();
    if (!model) {
        return;
    }
    
    // Парсим текст из буфера обмена
    QStringList rows = clipboardText.split('\n', Qt::SkipEmptyParts);
    if (rows.isEmpty()) {
        return;
    }
    
    int columnCount = model->columnCount();
    
    // Определяем, какой контроллер использовать для добавления строк
    PerechenProcessor *perechenProcessor = qobject_cast<PerechenProcessor*>(m_processor);
    SpecificationPCBProcessor *specPCBProcessor = qobject_cast<SpecificationPCBProcessor*>(m_processor);
    SpecificationProcessor *specProcessor = qobject_cast<SpecificationProcessor*>(m_processor);
    VedomostProcessor *vedomostProcessor = qobject_cast<VedomostProcessor*>(m_processor);
    
    // Вставляем строки в обратном порядке, чтобы позиция вставки не смещалась
    // и порядок строк сохранялся правильно
    for (int i = rows.size() - 1; i >= 0; --i) {
        QStringList cells = rows[i].split('\t');
        
        // Добавляем пустую строку через соответствующий контроллер
        if (perechenProcessor && m_controller && m_controller->perechenTableController()) {
            m_controller->perechenTableController()->addEmptyRowAt(insertPosition);
            // Заполняем ячейки вставленной строки
            for (int col = 0; col < qMin(columnCount, cells.size()); ++col) {
                QModelIndex cellIndex = model->index(insertPosition, col);
                if (cellIndex.isValid()) {
                    model->setData(cellIndex, cells[col].trimmed(), Qt::EditRole);
                }
            }
        } else if (specPCBProcessor && m_controller && m_controller->specificationPCBController()) {
            m_controller->specificationPCBController()->addEmptyRowAt(insertPosition);
            for (int col = 0; col < qMin(columnCount, cells.size()); ++col) {
                QModelIndex cellIndex = model->index(insertPosition, col);
                if (cellIndex.isValid()) {
                    model->setData(cellIndex, cells[col].trimmed(), Qt::EditRole);
                }
            }
        } else if (specProcessor && m_controller && m_controller->specificationController()) {
            m_controller->specificationController()->addEmptyRowAt(insertPosition);
            for (int col = 0; col < qMin(columnCount, cells.size()); ++col) {
                QModelIndex cellIndex = model->index(insertPosition, col);
                if (cellIndex.isValid()) {
                    model->setData(cellIndex, cells[col].trimmed(), Qt::EditRole);
                }
            }
        } else if (vedomostProcessor && m_controller && m_controller->vedomostController()) {
            m_controller->vedomostController()->addEmptyRowAt(insertPosition);
            for (int col = 0; col < qMin(columnCount, cells.size()); ++col) {
                QModelIndex cellIndex = model->index(insertPosition, col);
                if (cellIndex.isValid()) {
                    model->setData(cellIndex, cells[col].trimmed(), Qt::EditRole);
                }
            }
        }
    }
    
    qDebug() << "DocumentEditWidget::pasteRowsFromClipboard: Вставлено строк:" << rows.size() << "в позицию:" << insertPosition;
}

void DocumentEditWidget::cutRows(int insertPosition)
{
    QItemSelectionModel *selectionModel = m_tableView->selectionModel();
    QModelIndexList selectedRows = selectionModel->selectedRows();
    
    if (selectedRows.isEmpty()) {
        return;
    }
    
    // Копируем строки
    copyRowsToClipboard(selectedRows);
    
    // Удаляем строки (в обратном порядке)
    QList<int> rowNumbers;
    for (const QModelIndex &index : selectedRows) {
        if (index.isValid()) {
            rowNumbers.append(index.row());
        }
    }
    std::sort(rowNumbers.begin(), rowNumbers.end());
    rowNumbers.erase(std::unique(rowNumbers.begin(), rowNumbers.end()), rowNumbers.end());
    std::reverse(rowNumbers.begin(), rowNumbers.end());
    
    // Удаляем строки через соответствующий контроллер
    PerechenProcessor *perechenProcessor = qobject_cast<PerechenProcessor*>(m_processor);
    SpecificationPCBProcessor *specPCBProcessor = qobject_cast<SpecificationPCBProcessor*>(m_processor);
    SpecificationProcessor *specProcessor = qobject_cast<SpecificationProcessor*>(m_processor);
    VedomostProcessor *vedomostProcessor = qobject_cast<VedomostProcessor*>(m_processor);
    
    for (int row : rowNumbers) {
        if (perechenProcessor && m_controller && m_controller->perechenTableController()) {
            m_controller->perechenTableController()->removeRow(row);
        } else if (specPCBProcessor && m_controller && m_controller->specificationPCBController()) {
            m_controller->specificationPCBController()->removeRow(row);
        } else if (specProcessor && m_controller && m_controller->specificationController()) {
            m_controller->specificationController()->removeRow(row);
        } else if (vedomostProcessor && m_controller && m_controller->vedomostController()) {
            m_controller->vedomostController()->removeRow(row);
        }
    }
    
    qDebug() << "DocumentEditWidget::cutRows: Вырезано строк:" << rowNumbers.size();
}

// Вспомогательные методы для копирования/вставки ячеек
void DocumentEditWidget::copyCellsToClipboard(const QItemSelection &selection)
{
    if (selection.isEmpty() || !m_tableView->model()) {
        return;
    }
    
    QAbstractItemModel *model = m_tableView->model();
    QModelIndexList indexes = selection.indexes();
    
    if (indexes.isEmpty()) {
        return;
    }
    
    // Определяем границы выбранной области
    int minRow = indexes.first().row();
    int maxRow = indexes.first().row();
    int minCol = indexes.first().column();
    int maxCol = indexes.first().column();
    
    for (const QModelIndex &index : indexes) {
        minRow = qMin(minRow, index.row());
        maxRow = qMax(maxRow, index.row());
        minCol = qMin(minCol, index.column());
        maxCol = qMax(maxCol, index.column());
    }
    
    // Формируем текст в формате таблицы (табуляция для столбцов, перенос строки для строк)
    QStringList rowTexts;
    for (int row = minRow; row <= maxRow; ++row) {
        QStringList cellTexts;
        for (int col = minCol; col <= maxCol; ++col) {
            QModelIndex cellIndex = model->index(row, col);
            QString cellText;
            // Проверяем, есть ли эта ячейка в выделении
            if (indexes.contains(cellIndex)) {
                cellText = model->data(cellIndex, Qt::DisplayRole).toString();
            }
            // Заменяем переносы строк и табуляции на пробелы для совместимости
            cellText.replace('\n', ' ').replace('\r', ' ').replace('\t', ' ');
            cellTexts.append(cellText);
        }
        rowTexts.append(cellTexts.join("\t"));
    }
    
    QString clipboardText = rowTexts.join("\n");
    
    // Копируем в буфер обмена
    QClipboard *clipboard = QApplication::clipboard();
    clipboard->setText(clipboardText);
    
    qDebug() << "DocumentEditWidget::copyCellsToClipboard: Скопировано ячеек:" << indexes.size();
}

void DocumentEditWidget::pasteCellsFromClipboard(const QModelIndex &topLeft)
{
    if (!topLeft.isValid() || !m_tableView->model()) {
        return;
    }
    
    QClipboard *clipboard = QApplication::clipboard();
    QString clipboardText = clipboard->text();
    
    if (clipboardText.isEmpty()) {
        return;
    }
    
    QAbstractItemModel *model = m_tableView->model();
    
    // Парсим текст из буфера обмена
    QStringList rows = clipboardText.split('\n', Qt::SkipEmptyParts);
    if (rows.isEmpty()) {
        return;
    }
    
    int startRow = topLeft.row();
    int startCol = topLeft.column();
    int maxRow = model->rowCount() - 1;
    int maxCol = model->columnCount() - 1;
    
    // Вставляем данные, начиная с topLeft
    for (int i = 0; i < rows.size(); ++i) {
        int currentRow = startRow + i;
        if (currentRow > maxRow) {
            break; // Достигли конца таблицы
        }
        
        QStringList cells = rows[i].split('\t');
        for (int j = 0; j < cells.size(); ++j) {
            int currentCol = startCol + j;
            if (currentCol > maxCol) {
                break; // Достигли конца строки
            }
            
            QModelIndex cellIndex = model->index(currentRow, currentCol);
            if (cellIndex.isValid()) {
                model->setData(cellIndex, cells[j].trimmed(), Qt::EditRole);
            }
        }
    }
    
    qDebug() << "DocumentEditWidget::pasteCellsFromClipboard: Вставлено ячеек из буфера обмена, начиная с row:" << startRow << "col:" << startCol;
}

void DocumentEditWidget::cutCells(const QModelIndex &topLeft)
{
    if (!topLeft.isValid()) {
        return;
    }
    
    QItemSelectionModel *selectionModel = m_tableView->selectionModel();
    QItemSelection selection = selectionModel->selection();
    
    if (selection.isEmpty()) {
        return;
    }
    
    // Копируем ячейки
    copyCellsToClipboard(selection);
    
    // Очищаем выбранные ячейки
    QModelIndexList indexes = selection.indexes();
    QAbstractItemModel *model = m_tableView->model();
    
    for (const QModelIndex &index : indexes) {
        if (index.isValid()) {
            model->setData(index, "", Qt::EditRole);
        }
    }
    
    qDebug() << "DocumentEditWidget::cutCells: Вырезано ячеек:" << indexes.size();
}