#include "vedomostcontroller.h"
#include "../model/componentmodel.h"
#include "../model/projectparamtablemodel.h"
#include "../model/titleinscriptionsmodel.h"
#include "../controller/maincontroller.h"
#include <QDebug>
#include <QCollator>

VedomostController::VedomostController(QObject *parent)
    : QObject(parent)
    , m_tableModel(new VedomostTableModel(this))
    , m_designatorMappingModel(nullptr)
    , m_projectSettingsModel(nullptr)
    , m_mainController(nullptr)
{
    // Устанавливаем маппинг по умолчанию для ведомости покупных изделий
    // Только поля, которые можно маппить на свойства компонентов
    m_columnMappings << "Name" << "ProductCode" << "DocumentCode" << "Supplier" 
                     << "WhereUsed" << "Note";
    
    // Автоматический пересчет отключен - пересчет выполняется по кнопке "Пересчет таблицы"
    // connect(m_tableModel, &VedomostTableModel::dataChanged, 
    //         this, &VedomostController::onRowDataChanged);
}

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

void VedomostController::setDesignatorMappingModel(DesignatorMappingModel *mappingModel)
{
    m_designatorMappingModel = mappingModel;
}

void VedomostController::setModel(VedomostTableModel *model)
{
    if (m_tableModel != model) {
        qDebug() << "VedomostController::setModel: Заменяем модель таблицы";
        m_tableModel = model;
        
        // Если модель не пуста, загружаем из неё настройки колонок
        if (m_tableModel) {
            QStringList columnMappings = m_tableModel->columnMappings();
            if (!columnMappings.isEmpty()) {
                qDebug() << "VedomostController::setModel: Загружаем настройки колонок из модели:" << columnMappings;
                m_columnMappings = columnMappings;
            }
        }
    }
}

void VedomostController::setProjectSettingsModel(ProjectSettingsModel *model)
{
    m_projectSettingsModel = model;
    qDebug() << "VedomostController::setProjectSettingsModel: Установлена модель настроек проекта";
}

void VedomostController::setMainController(MainController *controller)
{
    m_mainController = controller;
    qDebug() << "VedomostController::setMainController: Установлен главный контроллер";
}

void VedomostController::setComponents(const QList<ComponentModel*> &components)
{
    qDebug() << "VedomostController::setComponents: Устанавливаем" << components.size() << "компонентов";
    m_components = components;

    // Собираем доступные свойства из компонентов
    m_propertyNames = collectPropertyNames();
    qDebug() << "VedomostController::setComponents: Собрано свойств:" << m_propertyNames.size();
    qDebug() << "VedomostController::setComponents: Свойства:" << m_propertyNames;
}

void VedomostController::generateTableFromComponents()
{
    if (!m_tableModel) {
        return;
    }

    qDebug() << "VedomostController::generateTableFromComponents: Начинаем генерацию таблицы";
    qDebug() << "VedomostController::generateTableFromComponents: Текущие настройки колонок:" << m_columnMappings;
    qDebug() << "VedomostController::generateTableFromComponents: Количество компонентов:" << m_components.size();

    // Очищаем таблицу
    m_tableModel->clear();

    // Добавляем заголовок таблицы
    // VedomostRowData headerRow;
    // headerRow.isHeader = true;
    // headerRow.name = VedomostCellData("Наименование", 0, 1, true);
    // headerRow.productCode = VedomostCellData("Код продукции", 0, 1, true);
    // headerRow.documentCode = VedomostCellData("Обозначение документа на поставку", 0, 1, true);
    // headerRow.supplier = VedomostCellData("Поставщик", 0, 1, true);
    // headerRow.whereUsed = VedomostCellData("Куда входит (обозначение)", 0, 1, true);
    // headerRow.quantityPerItem = VedomostCellData("Количество на изделие", 0, 1, true);
    // headerRow.quantityInSet = VedomostCellData("Количество в комплекте", 0, 1, true);
    // headerRow.quantityForReg = VedomostCellData("Количество на регулир", 0, 1, true);
    // headerRow.totalQuantity = VedomostCellData("Количество всего", 0, 1, true);
    // headerRow.note = VedomostCellData("Примечание", 0, 1, true);
    // m_tableModel->addRow(headerRow);

    // // Добавляем пустую строку после заголовка
    // m_tableModel->addEmptyRow();

    if (m_components.isEmpty()) {
        qDebug() << "VedomostController::generateTableFromComponents: Нет компонентов для генерации";
        return;
    }

    try {
        // Сортируем компоненты по десигнатору
        std::sort(m_components.begin(), m_components.end(),
                  [this](ComponentModel* a, ComponentModel* b) {
                      if (!a || !b) return false;
                      return a->designator() < b->designator();
                  });

        // Группируем компоненты по буквенной части десигнатора
        QMap<QString, QList<ComponentModel*>> groupedByLetter;
        for (ComponentModel *component : m_components) {
            QPair<QString, QString> designatorParts = splitDesignator(component->designator());
            QString desLetter = designatorParts.first;
            groupedByLetter[desLetter].append(component);
        }

        // Обрабатываем каждую группу
        for (auto it = groupedByLetter.begin(); it != groupedByLetter.end(); ++it) {
            QString desLetter = it.key();
            QList<ComponentModel*> componentsInGroup = it.value();
            
            if (componentsInGroup.size() > 1) {
                // Если компонентов больше одного, группируем компоненты по наименованию
                QList<QPair<QString, QList<ComponentModel*>>> groupedByName;
                for (ComponentModel *component : componentsInGroup) {
                    QString componentName = getMappedValue(component, "Name");
                    
                    // Ищем существующую группу
                    bool found = false;
                    for (auto &group : groupedByName) {
                        if (group.first == componentName) {
                            group.second.append(component);
                            found = true;
                            break;
                        }
                    }
                    
                    // Если группа не найдена, создаем новую
                    if (!found) {
                        QList<ComponentModel*> newGroup;
                        newGroup.append(component);
                        groupedByName.append(qMakePair(componentName, newGroup));
                    }
                }
                
                // Если несколько разных названий в группе - добавляем заголовок типа
                if (groupedByName.size() > 1) {
                    // Добавляем заголовок типа (множественное число)
                    QString componentTypeHeader = getComponentType(componentsInGroup.first());
                    if (!componentTypeHeader.isEmpty()) {
                        VedomostRowData headerRow;
                        // Заголовок должен иметь isHeader=true и isUnderline=true для центрирования и подчеркивания в PDF
                        headerRow.name = VedomostCellData(componentTypeHeader, 0, 1, true, true, false, 100, true);
                        headerRow.productCode = VedomostCellData("", 0, 1, false, true, false, 100, false);
                        headerRow.documentCode = VedomostCellData("", 0, 1, false, true, false, 100, false);
                        headerRow.supplier = VedomostCellData("", 0, 1, false, true, false, 100, false);
                        headerRow.whereUsed = VedomostCellData("", 0, 1, false, true, false, 100, false);
                        headerRow.quantityPerItem = VedomostCellData("", 0, 1, false, true, false, 100, false);
                        headerRow.quantityInSet = VedomostCellData("", 0, 1, false, true, false, 100, false);
                        headerRow.quantityForReg = VedomostCellData("", 0, 1, false, true, false, 100, false);
                        headerRow.totalQuantity = VedomostCellData("", 0, 1, false, true, false, 100, false);
                        headerRow.note = VedomostCellData("", 0, 1, false, true, false, 100, false);
                        headerRow.isHeader = true; // Помечаем всю строку как заголовок
                        m_tableModel->addRow(headerRow);
                    }
                    
                    // Добавляем пустую строку
                    m_tableModel->addEmptyRow();
                }
                
                // Теперь создаем строки для каждой группы по наименованию
                for (const auto &nameGroup : groupedByName) {
                    QString componentName = nameGroup.first;
                    QList<ComponentModel*> componentsWithSameName = nameGroup.second;
                    
                    // Подсчитываем общее количество компонентов
                    int totalQuantity = componentsWithSameName.size();
                    
                    // Создаем строку для этой группы компонентов
                    ComponentModel *firstComponent = componentsWithSameName.first();
                    
                    // Получаем оригинальные строки для правильной обработки выражений
                    QStringList mappings = getColumnMappings();
                    QString nameProperty = mappings.size() > 0 ? mappings[0] : "Name";
                    QString productCodeProperty = mappings.size() > 1 ? mappings[1] : "ProductCode";
                    QString documentCodeProperty = mappings.size() > 2 ? mappings[2] : "DocumentCode";
                    QString supplierProperty = mappings.size() > 3 ? mappings[3] : "Supplier";
                    
                    // Получаем СЫРЫЕ значения свойств БЕЗ вычисления выражений для правильного разделения
                    QString nameOriginalString = getComponentRawValue(firstComponent, nameProperty);
                    QString productCodeOriginalString = getComponentRawValue(firstComponent, productCodeProperty);
                    QString documentCodeOriginalString = getComponentRawValue(firstComponent, documentCodeProperty);
                    QString supplierOriginalString = getComponentRawValue(firstComponent, supplierProperty);
                    
                    // Получаем данные с разделением длинных строк
                    QString nameValue = getMappedValue(firstComponent, "Name");
                    
                    // Определяем, нужно ли добавлять название элемента
                    // Если несколько разных названий в группе - только название без типа
                    // Если несколько одинаковых элементов - множественное число + название
                    // Если один элемент - единственное число + название
                    bool addComponentType = false;
                    QString componentTypeName;
                    
                    if (groupedByName.size() > 1) {
                        // Несколько разных названий - только название без типа
                        addComponentType = false;
                    } else if (totalQuantity > 1) {
                        // Несколько одинаковых элементов - множественное число
                        componentTypeName = getComponentType(firstComponent);
                        addComponentType = true;
                    } else {
                        // Один элемент - единственное число
                        componentTypeName = getComponentTypeName(firstComponent);
                        addComponentType = true;
                    }
                    
                    QString productCodeValue = getMappedValue(firstComponent, "ProductCode");
                    QString documentCodeValue = getMappedValue(firstComponent, "DocumentCode");
                    QString supplierValue = getMappedValue(firstComponent, "Supplier");
                    QString whereUsedValue = getWhereUsed(); // Получаем из titleInscriptionsModel или ProjectParamTable
                    QString noteValue = getMappedValue(firstComponent, "Note");
                    
                    qDebug() << "[SPLIT_CALL] ========== ВЫЗОВ splitLongDesignation для Name ==========";
                    qDebug() << "[SPLIT_CALL] nameValue:" << nameValue;
                    qDebug() << "[SPLIT_CALL] nameOriginalString:" << nameOriginalString;
                    qDebug() << "[SPLIT_CALL] component:" << (firstComponent ? "не nullptr" : "nullptr");
                    qDebug() << "[SPLIT_CALL] maxLength: 32";
                    
                    // Разделяем длинные строки (используем оригинальные строки для обработки выражений)
                    // ВАЖНО: сначала разделяем, потом добавляем название элемента к первой части
                    QList<QString> nameParts = splitLongDesignation(nameValue, nameOriginalString, firstComponent, 32);
                    
                    qDebug() << "[SPLIT_CALL] Результат nameParts:" << nameParts;
                    
                    // Добавляем название элемента к первой части, если нужно
                    if (addComponentType && !componentTypeName.isEmpty() && !nameParts.isEmpty()) {
                        if (!nameParts.first().isEmpty()) {
                            nameParts.first() = componentTypeName + " " + nameParts.first();
                        } else {
                            nameParts.first() = componentTypeName;
                        }
                    }
                    QList<QString> productCodeParts = splitLongDesignation(productCodeValue, productCodeOriginalString, firstComponent, 25);
                    QList<QString> documentCodeParts = splitLongDesignation(documentCodeValue, documentCodeOriginalString, firstComponent, 35);
                    QList<QString> supplierParts = splitLongDesignation(supplierValue, supplierOriginalString, firstComponent, 25);
                    QList<QString> whereUsedParts = splitLongDesignation(whereUsedValue, whereUsedValue, firstComponent, 35);
                    QList<QString> noteParts = splitLongDesignation(noteValue, noteValue, firstComponent, 16);
                    
                    // Группируем десигнаторы только для компонентов с этим наименованием
                    // Сначала сортируем компоненты по десигнатору (численно)
                    std::sort(componentsWithSameName.begin(), componentsWithSameName.end(),
                              [this](ComponentModel* a, ComponentModel* b) {
                                  if (!a || !b) return false;
                                  
                                  QString designatorA = a->designator();
                                  QString designatorB = b->designator();
                                  
                                  // Разделяем десигнаторы на буквенную и числовую части
                                  QPair<QString, QString> partsA = splitDesignator(designatorA);
                                  QPair<QString, QString> partsB = splitDesignator(designatorB);
                                  
                                  QString letterA = partsA.first;
                                  QString letterB = partsB.first;
                                  QString numberA = partsA.second;
                                  QString numberB = partsB.second;
                                  
                                  // Сначала сравниваем буквенные части
                                  if (letterA != letterB) {
                                      return letterA < letterB;
                                  }
                                  
                                  // Если буквенные части одинаковые, сравниваем числовые части
                                  bool okA, okB;
                                  int numA = numberA.toInt(&okA);
                                  int numB = numberB.toInt(&okB);
                                  
                                  if (okA && okB) {
                                      return numA < numB;
                                  }
                                  
                                  // Fallback: если не удалось преобразовать в числа, используем строковое сравнение
                                  return numberA < numberB;
                              });
                    
                    QList<QString> designatorGroupsForThisName;
                    QString currentGroup = componentsWithSameName.first()->designator();
                    QString lastDesignator = currentGroup;
                    
                    for (int i = 1; i < componentsWithSameName.size(); ++i) {
                        QString currentDesignator = componentsWithSameName[i]->designator();
                        QPair<QString, QString> currentParts = splitDesignator(currentDesignator);
                        QPair<QString, QString> lastParts = splitDesignator(lastDesignator);
                        
                        // Проверяем, является ли текущий десигнатор следующим по порядку
                        if (currentParts.first == lastParts.first) {
                            bool ok1, ok2;
                            int currentNum = currentParts.second.toInt(&ok1);
                            int lastNum = lastParts.second.toInt(&ok2);
                            
                            if (ok1 && ok2 && currentNum == lastNum + 1) {
                                // Продолжаем группу
                                lastDesignator = currentDesignator;
                            } else {
                                // Завершаем текущую группу и начинаем новую
                                if (currentGroup == lastDesignator) {
                                    designatorGroupsForThisName.append(currentGroup);
                                } else {
                                    designatorGroupsForThisName.append(currentGroup + "-" + lastDesignator);
                                }
                                currentGroup = currentDesignator;
                                lastDesignator = currentDesignator;
                            }
                        } else {
                            // Завершаем текущую группу и начинаем новую
                            if (currentGroup == lastDesignator) {
                                designatorGroupsForThisName.append(currentGroup);
                            } else {
                                designatorGroupsForThisName.append(currentGroup + "-" + lastDesignator);
                            }
                            currentGroup = currentDesignator;
                            lastDesignator = currentDesignator;
                        }
                    }
                    
                    // Добавляем последнюю группу
                    if (currentGroup == lastDesignator) {
                        designatorGroupsForThisName.append(currentGroup);
                    } else {
                        designatorGroupsForThisName.append(currentGroup + "-" + lastDesignator);
                    }
                    
                    // Разбиваем длинные группы десигнаторов (35 символов на строку для whereUsed)
                    QStringList designatorsSplit = splitDesignatorGroups(designatorGroupsForThisName, 35);
                    
                    // Если несколько одинаковых элементов или один элемент - добавляем пустую строку перед
                    if (groupedByName.size() == 1) {
                        m_tableModel->addEmptyRow();
                    }
                    
                    // Определяем максимальное количество строк для всех полей
                    int maxRows = qMax(qMax(qMax(nameParts.size(), productCodeParts.size()), 
                                          qMax(documentCodeParts.size(), supplierParts.size())),
                                     qMax(qMax(whereUsedParts.size(), noteParts.size()), designatorsSplit.size()));
                    
                    // Создаем строки для каждой части
                    for (int i = 0; i < maxRows; ++i) {
                        VedomostRowData row;
                        
                        // Заполняем данные с учетом разделения
                        row.name = VedomostCellData(i < nameParts.size() ? nameParts[i] : "", 0, 1, false, true, false, 100, false);
                        row.productCode = VedomostCellData(i < productCodeParts.size() ? productCodeParts[i] : "", 0, 1, false, true, false, 100, false);
                        row.documentCode = VedomostCellData(i < documentCodeParts.size() ? documentCodeParts[i] : "", 0, 1, false, true, false, 100, false);
                        row.supplier = VedomostCellData(i < supplierParts.size() ? supplierParts[i] : "", 0, 1, false, true, false, 100, false);
                        
                        // В whereUsed показываем значение из titleInscriptionsModel или ProjectParamTable
                        if (i < whereUsedParts.size()) {
                            row.whereUsed = VedomostCellData(whereUsedParts[i], 0, 1, false, true, false, 100, false);
                        } else {
                            row.whereUsed = VedomostCellData("", 0, 1, false, true, false, 100, false);
                        }
                        
                        // Количества только в первой строке
                        if (i == 0) {
                            row.quantityPerItem = VedomostCellData(QString::number(totalQuantity), 0, 1, false, true, false, 100, false);
                            row.quantityInSet = VedomostCellData("", 0, 1, false, true, false, 100, false);
                            row.quantityForReg = VedomostCellData("", 0, 1, false, true, false, 100, false);
                            // totalQuantity должен быть автоматически сгенерирован для автоматического пересчета
                            row.totalQuantity = VedomostCellData(QString::number(totalQuantity), 0, 1, false, true, true, 100, false);
                        } else {
                            row.quantityPerItem = VedomostCellData("", 0, 1, false, true, false, 100, false);
                            row.quantityInSet = VedomostCellData("", 0, 1, false, true, false, 100, false);
                            row.quantityForReg = VedomostCellData("", 0, 1, false, true, false, 100, false);
                            row.totalQuantity = VedomostCellData("", 0, 1, false, true, false, 100, false);
                        }
                        
                        row.note = VedomostCellData(i < noteParts.size() ? noteParts[i] : "", 0, 1, false, true, false, 100, false);
                        
                        m_tableModel->addRow(row);
                    }
                    
                    // Если несколько одинаковых элементов или один элемент - добавляем пустую строку после
                    if (groupedByName.size() == 1) {
                        m_tableModel->addEmptyRow();
                    }
                }
            } else {
                // Если компонент один, добавляем его как отдельную строку
                ComponentModel *component = componentsInGroup.first();
                
                // Получаем оригинальные строки для правильной обработки выражений
                QStringList mappings = getColumnMappings();
                QString nameProperty = mappings.size() > 0 ? mappings[0] : "Name";
                QString productCodeProperty = mappings.size() > 1 ? mappings[1] : "ProductCode";
                QString documentCodeProperty = mappings.size() > 2 ? mappings[2] : "DocumentCode";
                QString supplierProperty = mappings.size() > 3 ? mappings[3] : "Supplier";
                
                // Получаем СЫРЫЕ значения свойств БЕЗ вычисления выражений для правильного разделения
                QString nameOriginalString = getComponentRawValue(component, nameProperty);
                QString productCodeOriginalString = getComponentRawValue(component, productCodeProperty);
                QString documentCodeOriginalString = getComponentRawValue(component, documentCodeProperty);
                QString supplierOriginalString = getComponentRawValue(component, supplierProperty);
                
                // Получаем данные с разделением длинных строк
                QString nameValue = getMappedValue(component, "Name");
                
                // Для одного элемента: единственное число + название
                QString componentTypeName = getComponentTypeName(component);
                
                // Добавляем пустую строку перед
                m_tableModel->addEmptyRow();
                
                QString productCodeValue = getMappedValue(component, "ProductCode");
                QString documentCodeValue = getMappedValue(component, "DocumentCode");
                QString supplierValue = getMappedValue(component, "Supplier");
                QString whereUsedValue = getWhereUsed(); // Получаем из titleInscriptionsModel или ProjectParamTable
                QString noteValue = getMappedValue(component, "Note");
                
                qDebug() << "[SPLIT_CALL] ========== ВЫЗОВ splitLongDesignation для Name (один элемент) ==========";
                qDebug() << "[SPLIT_CALL] nameValue:" << nameValue;
                qDebug() << "[SPLIT_CALL] nameOriginalString:" << nameOriginalString;
                qDebug() << "[SPLIT_CALL] component:" << (component ? "не nullptr" : "nullptr");
                qDebug() << "[SPLIT_CALL] maxLength: 32";
                
                // Разделяем длинные строки (используем оригинальные строки для обработки выражений)
                // ВАЖНО: сначала разделяем, потом добавляем название элемента к первой части
                QList<QString> nameParts = splitLongDesignation(nameValue, nameOriginalString, component, 32);
                
                qDebug() << "[SPLIT_CALL] Результат nameParts:" << nameParts;
                
                // Добавляем название элемента к первой части, если нужно
                if (!componentTypeName.isEmpty() && !nameParts.isEmpty()) {
                    if (!nameParts.first().isEmpty()) {
                        nameParts.first() = componentTypeName + " " + nameParts.first();
                    } else {
                        nameParts.first() = componentTypeName;
                    }
                }
                QList<QString> productCodeParts = splitLongDesignation(productCodeValue, productCodeOriginalString, component, 25);
                QList<QString> documentCodeParts = splitLongDesignation(documentCodeValue, documentCodeOriginalString, component, 35);
                QList<QString> supplierParts = splitLongDesignation(supplierValue, supplierOriginalString, component, 25);
                QList<QString> whereUsedParts = splitLongDesignation(whereUsedValue, whereUsedValue, component, 35);
                QList<QString> noteParts = splitLongDesignation(noteValue, noteValue, component, 16);
                
                // Определяем максимальное количество строк
                int maxRows = qMax(qMax(qMax(nameParts.size(), productCodeParts.size()), 
                                      qMax(documentCodeParts.size(), supplierParts.size())),
                                 qMax(whereUsedParts.size(), noteParts.size()));
                
                // Создаем строки для каждой части
                for (int i = 0; i < maxRows; ++i) {
                    VedomostRowData row;
                    
                    // Заполняем данные с учетом разделения
                    row.name = VedomostCellData(i < nameParts.size() ? nameParts[i] : "", 0, 1, false, true, false, 100, false);
                    row.productCode = VedomostCellData(i < productCodeParts.size() ? productCodeParts[i] : "", 0, 1, false, true, false, 100, false);
                    row.documentCode = VedomostCellData(i < documentCodeParts.size() ? documentCodeParts[i] : "", 0, 1, false, true, false, 100, false);
                    row.supplier = VedomostCellData(i < supplierParts.size() ? supplierParts[i] : "", 0, 1, false, true, false, 100, false);
                    
                    // В whereUsed показываем значение из titleInscriptionsModel или ProjectParamTable
                    if (i < whereUsedParts.size()) {
                        row.whereUsed = VedomostCellData(whereUsedParts[i], 0, 1, false, true, false, 100, false);
                    } else {
                        row.whereUsed = VedomostCellData("", 0, 1, false, true, false, 100, false);
                    }
                    
                    // Количества только в первой строке
                    if (i == 0) {
                        row.quantityPerItem = VedomostCellData("1", 0, 1, false, true, false, 100, false);
                        row.quantityInSet = VedomostCellData("", 0, 1, false, true, false, 100, false);
                        row.quantityForReg = VedomostCellData("", 0, 1, false, true, false, 100, false);
                        // totalQuantity должен быть автоматически сгенерирован для автоматического пересчета
                        row.totalQuantity = VedomostCellData("1", 0, 1, false, true, true, 100, false);
                    } else {
                        row.quantityPerItem = VedomostCellData("", 0, 1, false, true, false, 100, false);
                        row.quantityInSet = VedomostCellData("", 0, 1, false, true, false, 100, false);
                        row.quantityForReg = VedomostCellData("", 0, 1, false, true, false, 100, false);
                        row.totalQuantity = VedomostCellData("", 0, 1, false, true, false, 100, false);
                    }
                    
                    row.note = VedomostCellData(i < noteParts.size() ? noteParts[i] : "", 0, 1, false, true, false, 100, false);
                    
                    m_tableModel->addRow(row);
                }
                
                // Добавляем пустую строку после
                m_tableModel->addEmptyRow();
            }
        }

        qDebug() << "VedomostController::generateTableFromComponents: Таблица сгенерирована, строк:" << m_tableModel->rowCount();
        
        // Оптимизируем разрывы страниц после генерации таблицы
        m_tableModel->optimizePageBreaks();
        
    } catch (const std::exception &e) {
        qDebug() << "VedomostController::generateTableFromComponents: Ошибка при генерации:" << e.what();
    } catch (...) {
        qDebug() << "VedomostController::generateTableFromComponents: Неизвестная ошибка при генерации";
    }
}

void VedomostController::updateTableFromComponents()
{
    if (!m_tableModel) {
        qDebug() << "VedomostController::updateTableFromComponents: m_tableModel is null";
        return;
    }

    qDebug() << "VedomostController::updateTableFromComponents: Обновляем таблицу из" << m_components.size() << "компонентов";

    if (m_components.isEmpty()) {
        qDebug() << "VedomostController::updateTableFromComponents: Нет компонентов для обновления";
        return;
    }

    try {
        // Метод updateTableFromComponents больше не используется в новой логике
        qDebug() << "VedomostController::updateTableFromComponents: Метод устарел";
    } catch (const std::exception &e) {
        qDebug() << "VedomostController::updateTableFromComponents: Ошибка при обновлении:" << e.what();
    } catch (...) {
        qDebug() << "VedomostController::updateTableFromComponents: Неизвестная ошибка при обновлении";
    }
}

QString VedomostController::getComponentValue(ComponentModel *component, const QString &propertyName)
{
    if (!component) {
        return "";
    }

    qDebug() << "VedomostController::getComponentValue: propertyName =" << propertyName;

    // Получаем значение свойства компонента
    QString value;
    if (propertyName == "Designator") {
        value = component->designator();
        qDebug() << "VedomostController::getComponentValue: Designator =" << value;
    } else {
        QMap<QString, QString> props = component->properties();
        value = props.value(propertyName, "");
        qDebug() << "VedomostController::getComponentValue: Свойство" << propertyName << "=" << value;
    }

    // Проверяем, является ли значение свойства выражением
    if (value.startsWith("=")) {
        qDebug() << "VedomostController::getComponentValue: Значение свойства является выражением:" << value;
        return parseExpression(component, value);
    }

    return value;
}

QString VedomostController::getComponentRawValue(ComponentModel *component, const QString &propertyName)
{
    if (!component) {
        return "";
    }

    qDebug() << "[RAW_VALUE] VedomostController::getComponentRawValue: propertyName =" << propertyName;

    // Получаем сырое значение свойства компонента БЕЗ вычисления выражений
    QString value;
    if (propertyName == "Designator") {
        value = component->designator();
        qDebug() << "[RAW_VALUE] Designator =" << value;
    } else {
        QMap<QString, QString> props = component->properties();
        value = props.value(propertyName, "");
        qDebug() << "[RAW_VALUE] Свойство" << propertyName << "=" << value;
    }

    // Возвращаем сырое значение без вычисления
    return value;
}

QString VedomostController::getMappedValue(ComponentModel *component, const QString &columnName)
{
    if (!component) {
        return "";
    }

    qDebug() << "VedomostController::getMappedValue: columnName =" << columnName;

    // Определяем индекс колонки в маппинге
    int columnIndex = -1;
    if (columnName == "Name") columnIndex = 0;
    else if (columnName == "ProductCode") columnIndex = 1;
    else if (columnName == "DocumentCode") columnIndex = 2;
    else if (columnName == "Supplier") columnIndex = 3;
    else if (columnName == "WhereUsed") columnIndex = 4;
    else if (columnName == "Note") columnIndex = 5;

    if (columnIndex < 0 || columnIndex >= m_columnMappings.size()) {
        qDebug() << "VedomostController::getMappedValue: Неизвестная колонка или индекс вне диапазона:" << columnName;
        return "";
    }

    // Получаем маппинг для этой колонки
    QString mappedProperty = m_columnMappings[columnIndex];
    
    // Если маппинг пустой или "Не выбрано", возвращаем пустую строку
    if (mappedProperty.isEmpty() || mappedProperty == "-- Не выбрано --") {
        qDebug() << "VedomostController::getMappedValue: Маппинг пустой для колонки" << columnName;
        return "";
    }

    qDebug() << "VedomostController::getMappedValue: Маппинг" << columnName << "->" << mappedProperty;

    // Для колонки "WhereUsed" значение получается из ProjectParamTable, а не из компонента
    if (columnName == "WhereUsed") {
        return getWhereUsed();
    }
    
    // Получаем значение из компонента
    QString value = getComponentValue(component, mappedProperty);

    return value;
}

QString VedomostController::parseExpression(ComponentModel *component, const QString &expression)
{
    if (!component) {
        return "";
    }

    qDebug() << "VedomostController::parseExpression: Обрабатываем выражение:" << expression;

    QString result;
    QString expr;

    // Определяем, как обрабатывать выражение
    if (expression.startsWith("=")) {
        expr = expression.mid(1); // Убираем начальный "="
    } else if (expression.startsWith("\"") && expression.endsWith("\"")) {
        // Если это просто значение в кавычках, возвращаем его без кавычек
        return expression.mid(1, expression.length() - 2);
    } else {
        // Если это не выражение, возвращаем как есть
        return expression;
    }

    // Разбиваем выражение по операторам "+" с учетом кавычек
    QStringList parts;
    QString currentPart;
    bool inDoubleQuotes = false;
    bool inSingleQuotes = false;

    for (int i = 0; i < expr.length(); ++i) {
        QChar ch = expr[i];

        if (ch == '"' && !inSingleQuotes) {
            inDoubleQuotes = !inDoubleQuotes;
            currentPart += ch;
        } else if (ch == '\'' && !inDoubleQuotes) {
            inSingleQuotes = !inSingleQuotes;
            currentPart += ch;
        } else if (ch == '+' && !inDoubleQuotes && !inSingleQuotes) {
            // Это разделитель "+" вне кавычек
            if (!currentPart.trimmed().isEmpty()) {
                parts.append(currentPart.trimmed());
            }
            currentPart.clear();
        } else {
            currentPart += ch;
        }
    }

    // Добавляем последнюю часть
    if (!currentPart.trimmed().isEmpty()) {
        parts.append(currentPart.trimmed());
    }

    qDebug() << "VedomostController::parseExpression: Части выражения:" << parts;

    for (const QString &part : parts) {
        QString trimmedPart = part.trimmed();
        qDebug() << "VedomostController::parseExpression: Обрабатываем часть:" << trimmedPart;

        // Если это не пустая строка, добавляем к результату
        if (!trimmedPart.isEmpty()) {
            QString value;

            // Проверяем, является ли это литералом в одинарных кавычках
            if (trimmedPart.startsWith("'") && trimmedPart.endsWith("'")) {
                // Это литерал - убираем кавычки и используем как есть
                value = trimmedPart.mid(1, trimmedPart.length() - 2);
                qDebug() << "VedomostController::parseExpression: Найден литерал в одинарных кавычках:" << value;
            }
            // Проверяем, является ли это именем свойства компонента в двойных кавычках
            else if (trimmedPart.startsWith("\"") && trimmedPart.endsWith("\"")) {
                // Это свойство компонента - убираем кавычки и ищем в свойствах
                QString propertyName = trimmedPart.mid(1, trimmedPart.length() - 2);
                qDebug() << "VedomostController::parseExpression: Ищем свойство компонента:" << propertyName;

                if (propertyName == "Designator") {
                    value = component->designator();
                    qDebug() << "VedomostController::parseExpression: Найдено свойство Designator =" << value;
                } else {
                    // Ищем в свойствах компонента
                    QMap<QString, QString> props = component->properties();
                    value = props.value(propertyName, "");
                    qDebug() << "VedomostController::parseExpression: Ищем свойство" << propertyName << "в компоненте, результат:" << value;
                    // Рекурсивно обрабатываем вложенные выражения
                    if (value.startsWith("=")) {
                        qDebug() << "VedomostController::parseExpression: Значение свойства является вложенным выражением, рекурсивно обрабатываем";
                        value = parseExpression(component, value);
                    }
                }
            }
            // Проверяем, является ли это именем свойства компонента без кавычек
            else if (trimmedPart == "Designator") {
                value = component->designator();
                qDebug() << "VedomostController::parseExpression: Найдено свойство Designator =" << value;
            } else {
                // Ищем в свойствах компонента
                QMap<QString, QString> props = component->properties();
                value = props.value(trimmedPart, "");
                qDebug() << "VedomostController::parseExpression: Ищем свойство" << trimmedPart << "в компоненте, результат:" << value;
                // Рекурсивно обрабатываем вложенные выражения
                if (value.startsWith("=")) {
                    qDebug() << "VedomostController::parseExpression: Значение свойства является вложенным выражением, рекурсивно обрабатываем";
                    value = parseExpression(component, value);
                }
            }

            // Добавляем значение к результату
            if (!value.isEmpty()) {
                if (!result.isEmpty()) {
                    result += value;
                } else {
                    result = value;
                }
                qDebug() << "VedomostController::parseExpression: Добавили к результату, текущий результат:" << result;
            }
        }
    }

    qDebug() << "VedomostController::parseExpression: Финальный результат:" << result;
    return result;
}

QList<QString> VedomostController::splitByConnectors(const QString &text, int maxLength)
{
    QList<QString> result;
    
    if (text.length() <= maxLength) {
        result.append(text);
        return result;
    }
    
    // Ищем соединения (тире, дефисы, точки)
    QStringList connectors = {" - ", "–", "—", " — ", " — ", " / ", " \\ ", " + ", " = "};
    
    // Ищем ближайший к середине строки разделитель
    int targetLength = maxLength;
    int bestSplitPos = -1;
    int minDifference = text.length();
    
    for (const QString &connector : connectors) {
        int pos = text.indexOf(connector);
        while (pos != -1) {
            int leftLength = pos;
            int rightLength = text.length() - pos - connector.length();
            
            // Вычисляем разницу с целевой длиной
            int leftDiff = abs(leftLength - targetLength);
            int rightDiff = abs(rightLength - targetLength);
            int totalDiff = leftDiff + rightDiff;
            
            // Если эта позиция лучше предыдущей, запоминаем её
            if (totalDiff < minDifference) {
                minDifference = totalDiff;
                bestSplitPos = pos;
            }
            
            pos = text.indexOf(connector, pos + 1);
        }
    }
    
    // Если нашли подходящий разделитель, разделяем по нему
    if (bestSplitPos != -1) {
        // Определяем длину разделителя
        int connectorLength = 0;
        for (const QString &connector : connectors) {
            if (text.mid(bestSplitPos, connector.length()) == connector) {
                connectorLength = connector.length();
                break;
            }
        }
        
        QString leftPart = text.left(bestSplitPos).trimmed();
        QString rightPart = text.mid(bestSplitPos + connectorLength).trimmed();
        
        // Рекурсивно обрабатываем обе части
        if (!leftPart.isEmpty()) {
            QList<QString> leftParts = splitByConnectors(leftPart, maxLength);
            result.append(leftParts);
        }
        
        if (!rightPart.isEmpty()) {
            QList<QString> rightParts = splitByConnectors(rightPart, maxLength);
            result.append(rightParts);
        }
    }
    
    // Если разделители не найдены или не подходят, возвращаем исходный текст
    if (result.isEmpty()) {
        result.append(text);
    }
    
    return result;
}

QList<QString> VedomostController::splitComplexStringByMiddle(const QString &text, int maxLength)
{
    QList<QString> result;
    
    if (text.length() <= maxLength) {
        result.append(text);
        return result;
    }
    
    qDebug() << "[SPLIT_DEBUG] splitComplexStringByMiddle: Разделяем комплексную строку:" << text;
    
    // Ищем запятые в тексте
    QList<int> commaPositions;
    for (int i = 0; i < text.length(); ++i) {
        if (text[i] == ',') {
            commaPositions.append(i);
        }
    }
    
    if (commaPositions.isEmpty()) {
        // Если запятых нет, используем обычное разделение по пробелам
        qDebug() << "[SPLIT_DEBUG] splitComplexStringByMiddle: Запятых не найдено, используем splitBySpaces";
        return splitBySpaces(text, maxLength);
    }
    
    // Ищем запятую, ближайшую к середине строки
    int targetLength = maxLength;
    int bestSplitPos = -1;
    int minDifference = text.length();
    
    for (int pos : commaPositions) {
        int leftLength = pos + 1; // Включаем запятую в левую часть
        int rightLength = text.length() - pos - 1;
        
        // Вычисляем разницу с целевой длиной
        int leftDiff = abs(leftLength - targetLength);
        int rightDiff = abs(rightLength - targetLength);
        int totalDiff = leftDiff + rightDiff;
        
        // Если эта позиция лучше предыдущей, запоминаем её
        if (totalDiff < minDifference) {
            minDifference = totalDiff;
            bestSplitPos = pos;
        }
    }
    
    // Если нашли подходящую запятую, разделяем по ней
    if (bestSplitPos != -1) {
        QString leftPart = text.left(bestSplitPos + 1).trimmed(); // Включаем запятую
        QString rightPart = text.mid(bestSplitPos + 1).trimmed();
        
        qDebug() << "[SPLIT_DEBUG] splitComplexStringByMiddle: Найдена запятая на позиции" << bestSplitPos;
        qDebug() << "[SPLIT_DEBUG] splitComplexStringByMiddle: Левая часть:" << leftPart;
        qDebug() << "[SPLIT_DEBUG] splitComplexStringByMiddle: Правая часть:" << rightPart;
        
        // Рекурсивно обрабатываем обе части
        if (!leftPart.isEmpty()) {
            QList<QString> leftParts = splitComplexStringByMiddle(leftPart, maxLength);
            result.append(leftParts);
        }
        
        if (!rightPart.isEmpty()) {
            QList<QString> rightParts = splitComplexStringByMiddle(rightPart, maxLength);
            result.append(rightParts);
        }
    } else {
        // Если не удалось найти подходящую запятую, используем обычное разделение
        qDebug() << "[SPLIT_DEBUG] splitComplexStringByMiddle: Не удалось найти подходящую запятую, используем splitBySpaces";
        result = splitBySpaces(text, maxLength);
    }
    
    qDebug() << "[SPLIT_DEBUG] splitComplexStringByMiddle: Результат:" << result;
    return result;
}

QStringList VedomostController::collectPropertyNames()
{
    QStringList propertyNames;

    // Добавляем основные свойства компонента
    propertyNames << "Designator" << "Name" << "ProductCode" << "DocumentCode" << "Supplier";

    // Собираем дополнительные свойства из компонентов
    for (ComponentModel *component : m_components) {
        QMap<QString, QString> props = component->properties();
        for (auto it = props.begin(); it != props.end(); ++it) {
            if (!propertyNames.contains(it.key())) {
                propertyNames.append(it.key());
            }
        }
    }

    // Если дополнительные свойства не найдены в компонентах, добавляем стандартные
    if (propertyNames.size() <= 5) { // Только базовые свойства
        propertyNames << "Type" << "Value" << "Footprint" << "Description" << "ManufacturerPartNumber";
        qDebug() << "VedomostController: Дополнительные свойства не найдены, используем стандартные:" << propertyNames;
    }

    // Добавляем специальные свойства для ведомости
    propertyNames << "WhereUsed" << "QuantityPerItem" << "QuantityInSet" << "QuantityForReg" << "TotalQuantity" << "Note";

    return propertyNames;
}

void VedomostController::setColumnMappings(const QStringList &mappings)
{
    qDebug() << "VedomostController::setColumnMappings: Устанавливаем новые настройки колонок:" << mappings;
    m_columnMappings = mappings;
    
    // Сохраняем настройки в ProjectSettingsModel
    if (m_projectSettingsModel) {
        for (int i = 0; i < mappings.size(); ++i) {
            m_projectSettingsModel->setColumnMapping("Vedomost", i, mappings[i]);
        }
        qDebug() << "VedomostController::setColumnMappings: Настройки сохранены в ProjectSettingsModel";
    }
    
    // Обновляем настройки в модели
    if (m_tableModel) {
        m_tableModel->setColumnMappings(mappings);
        qDebug() << "VedomostController::setColumnMappings: Настройки обновлены в модели";
    }
    
    qDebug() << "VedomostController::setColumnMappings: Настройки колонок обновлены:" << m_columnMappings;
}

QStringList VedomostController::getColumnMappings() const
{
    // Если есть ProjectSettingsModel, читаем настройки из него
    if (m_projectSettingsModel) {
        QStringList settings = m_projectSettingsModel->getColumnMappings("Vedomost");
        if (!settings.isEmpty()) {
            qDebug() << "VedomostController::getColumnMappings: Получены настройки из ProjectSettingsModel:" << settings;
            return settings;
        }
    }
    
    // Fallback: возвращаем локальные настройки
    qDebug() << "VedomostController::getColumnMappings: Возвращаем локальные настройки:" << m_columnMappings;
    return m_columnMappings;
}

QStringList VedomostController::getAvailableProperties() const
{
    QStringList properties = m_propertyNames;
    // Убираем специальные значения, оставляем только реальные свойства компонентов
    return properties;
}

QString VedomostController::getComponentType(ComponentModel *component)
{
    if (!component) return "";

    // Получаем тип компонента из маппинга дезигнаторов
    if (m_designatorMappingModel) {
        QString componentType = m_designatorMappingModel->getComponentType(component->designator(), true); // true для множественного числа
        if (!componentType.isEmpty()) {
            return componentType;
        }
    }

    // Если маппинг не найден, используем тип из свойств компонента
    QMap<QString, QString> props = component->properties();
    QString type = props.value("Type", "");
    if (!type.isEmpty()) {
        return type;
    }

    // Если и тип не найден, используем designator как fallback
    return component->designator();
}

QString VedomostController::getComponentTypeName(ComponentModel *component)
{
    if (!component) return "";

    // Получаем название элемента по десигнатору в единственном числе
    if (m_designatorMappingModel) {
        QString componentType = m_designatorMappingModel->getComponentType(component->designator(), false); // false для единственного числа
        if (!componentType.isEmpty()) {
            return componentType;
        }
    }

    // Если маппинг не найден, используем тип из свойств компонента
    QMap<QString, QString> props = component->properties();
    QString type = props.value("Type", "");
    if (!type.isEmpty()) {
        return type;
    }

    // Если и тип не найден, возвращаем пустую строку
    return QString();
}

QPair<QString, QString> VedomostController::splitDesignator(const QString &designator)
{
    if (designator.isEmpty()) {
        return QPair<QString, QString>("", "");
    }

    // Используем регулярное выражение для разделения буквенной и цифровой части
    QRegExp regex("([A-Za-z]+)(\\d*)");
    if (regex.indexIn(designator) != -1) {
        QString letterPart = regex.cap(1);
        QString numberPart = regex.cap(2);
        return QPair<QString, QString>(letterPart, numberPart);
    }

    // Fallback: если регулярное выражение не сработало,
    // ищем первую цифру и разделяем по ней
    for (int i = 0; i < designator.length(); ++i) {
        if (designator[i].isDigit()) {
            QString letterPart = designator.left(i);
            QString numberPart = designator.mid(i);
            return QPair<QString, QString>(letterPart, numberPart);
        }
    }

    // Если цифр нет, возвращаем весь десигнатор как буквенную часть
    return QPair<QString, QString>(designator, "");
}

// Новые методы для управления строками
void VedomostController::addEmptyRow()
{
    if (m_tableModel) {
        m_tableModel->addEmptyRow();
        qDebug() << "VedomostController::addEmptyRow: Добавлена пустая строка";
        
        // Автоматический пересчет отключен - пересчет выполняется по кнопке "Пересчет таблицы"
        // m_tableModel->optimizePageBreaks();
    }
}

void VedomostController::addEmptyRowAt(int position)
{
    if (m_tableModel) {
        m_tableModel->addEmptyRowAt(position);
        qDebug() << "VedomostController::addEmptyRowAt: Добавлена пустая строка в позицию" << position;
        
        // Автоматический пересчет отключен - пересчет выполняется по кнопке "Пересчет таблицы"
        // m_tableModel->optimizePageBreaks();
    }
}

void VedomostController::insertEmptyRowAt(int position)
{
    if (m_tableModel) {
        m_tableModel->addEmptyRowAt(position);
        qDebug() << "VedomostController::insertEmptyRowAt: Вставлена пустая строка в позицию" << position;
        
        // Автоматический пересчет отключен - пересчет выполняется по кнопке "Пересчет таблицы"
        // m_tableModel->optimizePageBreaks();
    }
}

void VedomostController::removeRow(int row)
{
    if (m_tableModel) {
        m_tableModel->removeRow(row);
        qDebug() << "VedomostController::removeRow: Удалена строка" << row;
        
        // Автоматический пересчет отключен - пересчет выполняется по кнопке "Пересчет таблицы"
        // m_tableModel->optimizePageBreaks();
    }
}

void VedomostController::clearTable()
{
    if (m_tableModel) {
        m_tableModel->clear();
        qDebug() << "VedomostController::clearTable: Таблица очищена";
    }
}

void VedomostController::optimizePageBreaks()
{
    if (m_tableModel) {
        qDebug() << "VedomostController::optimizePageBreaks: Оптимизируем разрывы страниц";
        m_tableModel->optimizePageBreaks();
    }
}

int VedomostController::getFontSize() const
{
    if (m_projectSettingsModel) {
        return m_projectSettingsModel->getFontSize("Vedomost");
    }
    return 12; // По умолчанию
}

void VedomostController::setFontSize(int fontSize)
{
    if (m_projectSettingsModel) {
        m_projectSettingsModel->setFontSize("Vedomost", fontSize);
    }
}

int VedomostController::getFontStretch() const
{
    if (m_projectSettingsModel) {
        return m_projectSettingsModel->getFontStretch("Vedomost");
    }
    return 100; // По умолчанию (нормальный)
}

void VedomostController::setFontStretch(int stretch)
{
    if (m_projectSettingsModel) {
        m_projectSettingsModel->setFontStretch("Vedomost", stretch);
    }
}

QString VedomostController::getWhereUsed() const
{
    // Сначала пытаемся получить значение из titleInscriptionsModel (поля 101 или 1001)
    if (m_mainController) {
        TitleInscriptionsModel *titleModel = m_mainController->titleInscriptionsModel();
        ProjectParamTableModel *paramModel = m_mainController->projectParamTableModel();
        
        if (titleModel) {
            // Пробуем сначала поле 101, затем 1001
            QString inscriptionValue;
            int fieldNumber = -1;
            
            if (!titleModel->getInscriptionValue(101).isEmpty()) {
                inscriptionValue = titleModel->getInscriptionValue(101);
                fieldNumber = 101;
            } else if (!titleModel->getInscriptionValue(1001).isEmpty()) {
                inscriptionValue = titleModel->getInscriptionValue(1001);
                fieldNumber = 1001;
            }
            
            if (!inscriptionValue.isEmpty() && inscriptionValue != "-- Не выбрано --") {
                // Если значение - это название поля из ProjectParamTable, получаем реальное значение
                if (paramModel) {
                    QMap<QString, QString> params = paramModel->getDataAsMap();
                    if (params.contains(inscriptionValue)) {
                        QString projectParamValue = params[inscriptionValue];
                        if (!projectParamValue.isEmpty()) {
                            return projectParamValue;
                        }
                    }
                }
                // Если сопоставления нет или значение параметра пустое, возвращаем значение надписи
                return inscriptionValue;
            }
        }
    }
    
    // Fallback: используем старую логику из columnMappings
    QStringList mappings = getColumnMappings();
    // Поле "WhereUsed" находится в позиции 4 в columnMappings
    if (mappings.size() > 4) {
        QString fieldName = mappings[4];
        if (!fieldName.isEmpty()) {
            // Получаем значение из projectparamtable
            if (m_mainController) {
                ProjectParamTableModel *paramModel = m_mainController->projectParamTableModel();
                if (paramModel) {
                    QMap<QString, QString> params = paramModel->getDataAsMap();
                    if (params.contains(fieldName)) {
                        return params[fieldName]; // Возвращаем значение, а не название поля
                    }
                }
            }
            // Если не удалось получить значение из модели, возвращаем название поля
            return fieldName;
        }
    }
    return QString();
}

QList<QString> VedomostController::splitLongDesignation(const QString &designation, const QString originalString, ComponentModel *component, int maxLength)
{
    QList<QString> result;
    
    qDebug() << "[SPLIT_DEBUG] ========== splitLongDesignation START ==========";
    qDebug() << "[SPLIT_DEBUG] designation:" << designation;
    qDebug() << "[SPLIT_DEBUG] designation.length():" << designation.length();
    qDebug() << "[SPLIT_DEBUG] originalString:" << originalString;
    qDebug() << "[SPLIT_DEBUG] originalString.startsWith('='):" << originalString.startsWith("=");
    qDebug() << "[SPLIT_DEBUG] component:" << (component ? "не nullptr" : "nullptr");
    qDebug() << "[SPLIT_DEBUG] maxLength:" << maxLength;
    
    if (designation.length() <= maxLength) {
        qDebug() << "[SPLIT_DEBUG] Строка короткая, возвращаем как есть";
        result.append(designation);
        qDebug() << "[SPLIT_DEBUG] ========== splitLongDesignation END (короткая строка) ==========";
        return result;
    }
    
    // Проверяем, является ли наименование выражением с частями
    if (originalString.startsWith("=") && component) {
        qDebug() << "[SPLIT_DEBUG] >>> ВЕТКА: Это выражение, разделяем по плюсам";
        // Это выражение - разделяем по частям
        QString expr = originalString.mid(1); // Убираем начальный "="
        qDebug() << "[SPLIT_DEBUG] Выражение без '=':" << expr;
        QStringList parts;
        QString currentPart;
        bool inDoubleQuotes = false;
        bool inSingleQuotes = false;
        
        for (int i = 0; i < expr.length(); ++i) {
            QChar ch = expr[i];
            
            if (ch == '"' && !inSingleQuotes) {
                inDoubleQuotes = !inDoubleQuotes;
                currentPart += ch;
            } else if (ch == '\'' && !inDoubleQuotes) {
                inSingleQuotes = !inSingleQuotes;
                currentPart += ch;
            } else if (ch == '+' && !inDoubleQuotes && !inSingleQuotes) {
                // Это разделитель "+" вне кавычек
                qDebug() << "[SPLIT_DEBUG] Найден разделитель '+' на позиции" << i << ", текущая часть:" << currentPart;
                if (!currentPart.trimmed().isEmpty()) {
                    parts.append(currentPart.trimmed());
                    qDebug() << "[SPLIT_DEBUG] Добавлена часть в список:" << currentPart.trimmed();
                }
                currentPart.clear();
            } else {
                currentPart += ch;
            }
        }
        
        // Добавляем последнюю часть
        if (!currentPart.trimmed().isEmpty()) {
            parts.append(currentPart.trimmed());
            qDebug() << "[SPLIT_DEBUG] Добавлена последняя часть:" << currentPart.trimmed();
        }
        
        qDebug() << "[SPLIT_DEBUG] Всего частей выражения:" << parts.size();
        qDebug() << "[SPLIT_DEBUG] Части выражения:" << parts;
        
        // Сначала собираем все части в одну строку для комплексных строк
        QString fullString;
        
        for (int i = 0; i < parts.size(); ++i) {
            QString trimmedPart = parts[i].trimmed();
            if (!trimmedPart.isEmpty()) {
                QString displayPart;
                
                // Проверяем, является ли это литералом в одинарных кавычках
                if (trimmedPart.startsWith("'") && trimmedPart.endsWith("'")) {
                    // Это литерал (запятая, пробел и т.д.)
                    displayPart = trimmedPart.mid(1, trimmedPart.length() - 2);
                } else {
                    // Это имя свойства - получаем значение из компонента
                    QMap<QString, QString> props = component->properties();
                    qDebug() << "[SPLIT_DEBUG] Обрабатываем свойство:" << trimmedPart;
                    
                    if (trimmedPart == "Designator") {
                        displayPart = component->designator();
                        qDebug() << "[SPLIT_DEBUG] Свойство Designator, значение:" << displayPart;
                    } else if (trimmedPart.startsWith("\"") && trimmedPart.endsWith("\"")) {
                        QString propertyName = trimmedPart.mid(1, trimmedPart.length() - 2);
                        displayPart = props.value(propertyName, "");
                        qDebug() << "[SPLIT_DEBUG] Свойство в кавычках:" << propertyName << ", значение:" << displayPart;
                        // Рекурсивно обрабатываем вложенные выражения
                        if (displayPart.startsWith("=")) {
                            qDebug() << "[SPLIT_DEBUG] Значение свойства является вложенным выражением, рекурсивно обрабатываем";
                            displayPart = parseExpression(component, displayPart);
                        }
                    } else {
                        displayPart = props.value(trimmedPart, "");
                        qDebug() << "[SPLIT_DEBUG] Свойство без кавычек:" << trimmedPart << ", значение:" << displayPart;
                        // Рекурсивно обрабатываем вложенные выражения
                        if (displayPart.startsWith("=")) {
                            qDebug() << "[SPLIT_DEBUG] Значение свойства является вложенным выражением, рекурсивно обрабатываем";
                            displayPart = parseExpression(component, displayPart);
                        }
                    }
                }
                
                fullString += displayPart;
            }
        }
        
        qDebug() << "[SPLIT_DEBUG] Собранная полная строка:" << fullString << ", длина:" << fullString.length();
        
        // Проверяем, содержит ли строка запятые (комплексная строка)
        bool isComplexString = fullString.contains(',');
        
        if (isComplexString && fullString.length() > maxLength) {
            qDebug() << "[SPLIT_DEBUG] Комплексная строка с запятыми, делим по середине";
            // Для комплексной строки делим по середине, а не по началу
            result = splitComplexStringByMiddle(fullString, maxLength);
        } else if (fullString.length() > maxLength) {
            qDebug() << "[SPLIT_DEBUG] Строка длинная, разделяем по пробелам";
            // Обычная длинная строка - разделяем по пробелам
            result = splitBySpaces(fullString, maxLength);
        } else {
            qDebug() << "[SPLIT_DEBUG] Строка короткая, возвращаем как есть";
            result.append(fullString);
        }
    } else {
        qDebug() << "[SPLIT_DEBUG] >>> ВЕТКА: Обычный текст (не выражение)";
        qDebug() << "[SPLIT_DEBUG] Причина: originalString.startsWith('=') =" << originalString.startsWith("=") << ", component =" << (component ? "не nullptr" : "nullptr");
        // Обычный текст - сначала пытаемся разделить по соединениям (тире, дефисы)
        qDebug() << "[SPLIT_DEBUG] Пытаемся разделить по соединениям (тире, дефисы)";
        result = splitByConnectors(designation, maxLength);
        qDebug() << "[SPLIT_DEBUG] Результат разделения по соединениям:" << result << ", размер:" << result.size();
        
        // Если разделение по соединениям не дало результата, разделяем по пробелам
        if (result.size() <= 1) {
            qDebug() << "[SPLIT_DEBUG] Разделение по соединениям не дало результата, разделяем по пробелам";
            result = splitBySpaces(designation, maxLength);
            qDebug() << "[SPLIT_DEBUG] Результат разделения по пробелам:" << result;
        }
    }
    
    qDebug() << "[SPLIT_DEBUG] ФИНАЛЬНЫЙ результат разделения:" << result;
    qDebug() << "[SPLIT_DEBUG] ========== splitLongDesignation END ==========";
    return result;
}

QList<QString> VedomostController::splitBySpaces(const QString &text, int maxLength)
{
    QList<QString> result;
    
    if (text.length() <= maxLength) {
        result.append(text);
        return result;
    }
    
    // Ищем пробел, ближайший к середине строки
    int targetLength = maxLength;
    int bestSplitPos = -1;
    int minDifference = text.length(); // Минимальная разница с целевой длиной
    
    // Ищем пробелы в тексте
    for (int i = 0; i < text.length(); ++i) {
        if (text[i] == ' ') {
            int leftLength = i;
            int rightLength = text.length() - i - 1;
            
            // Вычисляем разницу с целевой длиной
            int leftDiff = abs(leftLength - targetLength);
            int rightDiff = abs(rightLength - targetLength);
            int totalDiff = leftDiff + rightDiff;
            
            // Если эта позиция лучше предыдущей, запоминаем её
            if (totalDiff < minDifference) {
                minDifference = totalDiff;
                bestSplitPos = i;
            }
        }
    }
    
    // Если нашли подходящий пробел, разделяем по нему
    if (bestSplitPos != -1) {
        QString leftPart = text.left(bestSplitPos).trimmed();
        QString rightPart = text.mid(bestSplitPos + 1).trimmed();
        
        // Рекурсивно обрабатываем обе части
        if (!leftPart.isEmpty()) {
            QList<QString> leftParts = splitBySpaces(leftPart, maxLength);
            result.append(leftParts);
        }
        
        if (!rightPart.isEmpty()) {
            QList<QString> rightParts = splitBySpaces(rightPart, maxLength);
            result.append(rightParts);
        }
    } else {
        // Если пробелов нет или не удалось найти подходящий, разбиваем посимвольно
        // for (int i = 0; i < text.length(); i += maxLength) {
        //     result.append(text.mid(i, maxLength));
        // }
        result.append(text);
    }
    
    return result;
}

QStringList VedomostController::splitDesignatorGroups(const QStringList &designatorGroups, int maxLength)
{
    QStringList result;
    QString currentLine;
    
    for (const QString &group : designatorGroups) {
        QString testLine = currentLine.isEmpty() ? group : currentLine + ", " + group;
        
        if (testLine.length() <= maxLength) {
            currentLine = testLine;
        } else {
            if (!currentLine.isEmpty()) {
                result.append(currentLine + ",");
            }
            currentLine = group;
        }
    }
    
    if (!currentLine.isEmpty()) {
        result.append(currentLine);
    }
    
    // Теперь разбиваем каждую строку, если она длиннее maxLength
    QStringList finalResult;
    for (const QString &line : result) {
        if (line.length() <= maxLength) {
            finalResult.append(line);
        } else {
            // Разбиваем длинную строку посимвольно, но стараемся разбивать по запятым
            QStringList parts = line.split(", ");
            QString currentPart = "";
            
            for (const QString &part : parts) {
                QString testPart = currentPart.isEmpty() ? part : currentPart + ", " + part;
                
                if (testPart.length() <= maxLength) {
                    currentPart = testPart;
                } else {
                    if (!currentPart.isEmpty()) {
                        finalResult.append(currentPart);
                    }
                    currentPart = part;
                }
            }
            
            if (!currentPart.isEmpty()) {
                finalResult.append(currentPart);
            }
        }
    }
    
    return finalResult;
}

void VedomostController::onRowDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
{
    Q_UNUSED(roles);
    
    if (!m_tableModel) {
        return;
    }
    
    // Обрабатываем каждую измененную строку
    for (int row = topLeft.row(); row <= bottomRight.row(); ++row) {
        // Проверяем, изменились ли колонки с количествами (5, 6, 7)
        int startCol = topLeft.column();
        int endCol = bottomRight.column();
        
        bool quantityChanged = false;
        for (int col = startCol; col <= endCol; ++col) {
            if (col == 5 || col == 6 || col == 7) { // quantityPerItem, quantityInSet, quantityForReg
                quantityChanged = true;
                break;
            }
        }
        
        if (quantityChanged) {
            // Проверяем, что totalQuantity автоматически сгенерировано (не редактировалось вручную)
            // Используем прямой вызов метода модели для проверки и обновления
            m_tableModel->updateTotalQuantity(row);
        }
    }
} 
