#include "specificationpcbcontroller.h"
#include "../model/specificationpcbtablemodel.h"
#include "../model/designatormappingmodel.h"
#include "../model/projectsettingsmodel.h"
#include "../model/projectparamtablemodel.h"
#include "../model/componenttablemodel.h"
#include "../controller/maincontroller.h"
#include <QDebug>
#include <QCollator>

SpecificationPCBController::SpecificationPCBController(QObject *parent)
    : QObject(parent)
    , m_tableModel(new SpecificationPCBTableModel(this))
    , m_designatorMappingModel(nullptr)
    , m_projectSettingsModel(nullptr)
    , m_mainController(nullptr)
    , m_pcbDocFileName("")
{
    // Устанавливаем маппинг по умолчанию для спецификации платы
    m_columnMappings << "Format" << "Zone" << "Position" << "Designator" << "Name" << "Quantity" << "Value";
}

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

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

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

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

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

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

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

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

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

    // Очищаем таблицу
    m_tableModel->clear();
    SpecificationPCBRowData emptyRow;
    emptyRow.isEmpty = true;
    m_tableModel->addRow(emptyRow);
    SpecificationPCBRowData headerRow;
    headerRow.isHeader = true;
    headerRow.format = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
    headerRow.zone = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
    headerRow.position = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
    headerRow.designation = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
    headerRow.name = SpecificationPCBCellData("Документация", 0, 1, true, false, false, 100, true);
    headerRow.quantity = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
    headerRow.note = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
    
    
    m_tableModel->addRow(headerRow);

    m_tableModel->addRow(emptyRow);
    
    SpecificationPCBRowData defaultRow1;
    defaultRow1.isHeader = false;
    defaultRow1.format = SpecificationPCBCellData("A1", 0, 1, false, false, false, 100, false);
    defaultRow1.zone = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
    defaultRow1.position = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
    defaultRow1.designation = SpecificationPCBCellData(getDecimalNumberBoard()+" СБ", 0, 1, false, false, false, 100, false);
    defaultRow1.name = SpecificationPCBCellData("Сборочный чертеж", 0, 1, false, false, false, 100, false);
    defaultRow1.quantity = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
    defaultRow1.note = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
    m_tableModel->addRow(defaultRow1);

    SpecificationPCBRowData defaultRow2;
    defaultRow2.isHeader = false;
    defaultRow2.format = SpecificationPCBCellData("A3", 0, 1, false, false, false, 100, false);
    defaultRow2.zone = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
    defaultRow2.position = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
    defaultRow2.designation = SpecificationPCBCellData(getDecimalNumberBoard()+" Э3", 0, 1, false, false, false, 100, false);
    defaultRow2.name = SpecificationPCBCellData("Схема электрическая принципиальная", 0, 1, false, false, false, 100, false);
    m_tableModel->addRow(defaultRow2);

    SpecificationPCBRowData defaultRow3;
    defaultRow3.isHeader = false;
    defaultRow3.format = SpecificationPCBCellData("A4", 0, 1, false, false, false, 100, false);
    defaultRow3.zone = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
    defaultRow3.position = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
    defaultRow3.designation = SpecificationPCBCellData(getDecimalNumberBoard()+" ПЭ3", 0, 1, false, false, false, 100, false);
    defaultRow3.name = SpecificationPCBCellData("Перечень элементов", 0, 1, false, false, false, 100, false);
    defaultRow3.quantity = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
    defaultRow3.note = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
    m_tableModel->addRow(defaultRow3);

    SpecificationPCBRowData defaultRow4;
    defaultRow4.isHeader = false;
    defaultRow4.format = SpecificationPCBCellData("A3", 0, 1, false, false, false, 100, false);
    defaultRow4.zone = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
    defaultRow4.position = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
    defaultRow4.designation = SpecificationPCBCellData(getDecimalNumberBoard()+" ВП", 0, 1, false, false, false, 100, false);
    defaultRow4.name = SpecificationPCBCellData("Ведомость покупных изделий", 0, 1, false, false, false, 100, false);
    defaultRow4.quantity = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
    defaultRow4.note = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
    m_tableModel->addRow(defaultRow4);

    SpecificationPCBRowData defaultRow5;
    defaultRow5.isHeader = false;
    defaultRow5.format = SpecificationPCBCellData("*)", 0, 1, false);
    defaultRow5.zone = SpecificationPCBCellData("", 0, 1, false);
    defaultRow5.position = SpecificationPCBCellData("", 0, 1, false);
    defaultRow5.designation = SpecificationPCBCellData(getDecimalNumberBoard()+" Д33", 0, 1, false);
    defaultRow5.name = SpecificationPCBCellData("Данные результатов проектирования", 0, 1, false);
    defaultRow5.quantity = SpecificationPCBCellData("", 0, 1, false);
    defaultRow5.note = SpecificationPCBCellData("DVD диск", 0, 1, false);
    m_tableModel->addRow(defaultRow5);

    m_tableModel->addRow(emptyRow);

    SpecificationPCBRowData defaultRow5_1;
    defaultRow5_1.isHeader = false;
    defaultRow5_1.format = SpecificationPCBCellData("А4", 0, 1, false);
    defaultRow5_1.zone = SpecificationPCBCellData("", 0, 1, false);
    defaultRow5_1.position = SpecificationPCBCellData("", 0, 1, false);
    defaultRow5_1.designation = SpecificationPCBCellData(getDecimalNumberBoard()+" Д10-УЛ", 0, 1, false);
    defaultRow5_1.name = SpecificationPCBCellData("Удостоверяющий лист", 0, 1, false);
    defaultRow5_1.quantity = SpecificationPCBCellData("", 0, 1, false);
    defaultRow5_1.note = SpecificationPCBCellData("Размножать", 0, 1, false);
    m_tableModel->addRow(defaultRow5_1);
    SpecificationPCBRowData defaultRow5_2;
    defaultRow5_2.isHeader = false;
    defaultRow5_2.format = SpecificationPCBCellData("", 0, 1, false);
    defaultRow5_2.zone = SpecificationPCBCellData("", 0, 1, false);
    defaultRow5_2.position = SpecificationPCBCellData("", 0, 1, false);
    defaultRow5_2.designation = SpecificationPCBCellData("", 0, 1, false);
    defaultRow5_2.name = SpecificationPCBCellData("Данные результатов проектирования", 0, 1, false);
    defaultRow5_2.quantity = SpecificationPCBCellData("", 0, 1, false);
    defaultRow5_2.note = SpecificationPCBCellData("по указанию", 0, 1, false);
    m_tableModel->addRow(defaultRow5_2);
    m_tableModel->addRow(emptyRow);
    SpecificationPCBRowData headerRow2_4;
    headerRow2_4.isHeader = true;
    headerRow2_4.format = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
    headerRow2_4.zone = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
    headerRow2_4.position = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
    headerRow2_4.designation = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
    headerRow2_4.name = SpecificationPCBCellData("Сборочные единицы", 0, 1, true, false, false, 100, true);
    headerRow2_4.quantity = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
    headerRow2_4.note = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
    m_tableModel->addRow(headerRow2_4);



    m_tableModel->addRow(emptyRow);

    SpecificationPCBRowData pcbInfo;
    pcbInfo.isHeader = false;
    pcbInfo.format = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
    pcbInfo.zone = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
    pcbInfo.position = SpecificationPCBCellData("1", 0, 1, false, false, false, 100, false);
    pcbInfo.designation = SpecificationPCBCellData(getDecimalNumberBoard()+" платы", 0, 1, false, false, false, 100, false);
    pcbInfo.name = SpecificationPCBCellData(getBoardName(), 0, 1, false, false, false, 100, false);
    pcbInfo.quantity = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
    pcbInfo.note = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
    m_tableModel->addRow(pcbInfo);

    m_tableModel->addRow(emptyRow);
    SpecificationPCBRowData headerRow2;
    headerRow2.isHeader = true;
    headerRow2.format = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
    headerRow2.zone = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
    headerRow2.position = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
    headerRow2.designation = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
    headerRow2.name = SpecificationPCBCellData("Детали", 0, 1, true, false, false, 100, true);
    headerRow2.quantity = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
    headerRow2.note = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
    m_tableModel->addRow(headerRow2);
    m_tableModel->addRow(emptyRow);
    SpecificationPCBRowData headerRow2_1;
    headerRow2_1.isHeader = true;
    headerRow2_1.format = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
    headerRow2_1.zone = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
    headerRow2_1.position = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
    headerRow2_1.designation = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
    headerRow2_1.name = SpecificationPCBCellData("Стандартные изделия", 0, 1, true, false, false, 100, true);
    headerRow2_1.quantity = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
    headerRow2_1.note = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
    m_tableModel->addRow(headerRow2_1);
    m_tableModel->addRow(emptyRow);


    SpecificationPCBRowData headerRow3;
    headerRow3.isHeader = true;
    headerRow3.format = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
    headerRow3.zone = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
    headerRow3.position = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
    headerRow3.designation = SpecificationPCBCellData("", 0, 1, true, false, false, 100, true);
    headerRow3.name = SpecificationPCBCellData("Прочие изделия", 0, 1, true, false, false, 100, true);

    int pos1 = 2;

    m_tableModel->addRow(headerRow3);

    m_tableModel->addRow(emptyRow);

  

    if (m_components.isEmpty()) {
        return;
    }

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

                      QString designatorA = a->designator();
                      QString designatorB = b->designator();

                      // Разделяем десигнаторы на буквенную и числовую части
                      QPair<QString, QString> partsA = SpecificationPCBController::splitDesignator(designatorA);
                      QPair<QString, QString> partsB = SpecificationPCBController::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;
                  });

        // Группируем компоненты по буквенной части десигнатора
        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 = getComponentValue(component, "ManufacturerPartNumber");
                    
                    // Ищем существующую группу
                    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));
                    }
                }
                
                // Теперь создаем строки для каждой группы по наименованию
                for (const auto &nameGroup : groupedByName) {
                    QString componentName = nameGroup.first;
                    QList<ComponentModel*> componentsWithSameName = nameGroup.second;
                    
                    // Подсчитываем общее количество компонентов
                    int totalQuantity = componentsWithSameName.size();
                    
                    // Создаем строку для этой группы компонентов
                    ComponentModel *firstComponent = componentsWithSameName.first();
                    QMap<QString, QString> props = firstComponent->properties();
                    QString originalString = props.value("ManufacturerPartNumber", "");
                    QList<QString> designationParts = splitLongDesignation(componentName, originalString, firstComponent);
                    
                    // Группируем десигнаторы только для компонентов с этим наименованием
                                         // Сначала сортируем компоненты по десигнатору (численно)
                     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;
                    int groupCount = 1; // Счетчик элементов в текущей группе
                    
                    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;
                                groupCount++;
                            } else {
                                // Завершаем текущую группу и начинаем новую
                                if (currentGroup == lastDesignator) {
                                    designatorGroupsForThisName.append(currentGroup);
                                } else {
                                    // Если в группе 2 элемента - через запятую, иначе через дефис
                                    if (groupCount == 2) {
                                        designatorGroupsForThisName.append(currentGroup + ", " + lastDesignator);
                                    } else {
                                        designatorGroupsForThisName.append(currentGroup + "-" + lastDesignator);
                                    }
                                }
                                currentGroup = currentDesignator;
                                lastDesignator = currentDesignator;
                                groupCount = 1;
                            }
                        } else {
                            // Завершаем текущую группу и начинаем новую
                            if (currentGroup == lastDesignator) {
                                designatorGroupsForThisName.append(currentGroup);
                            } else {
                                // Если в группе 2 элемента - через запятую, иначе через дефис
                                if (groupCount == 2) {
                                    designatorGroupsForThisName.append(currentGroup + ", " + lastDesignator);
                                } else {
                                    designatorGroupsForThisName.append(currentGroup + "-" + lastDesignator);
                                }
                            }
                            currentGroup = currentDesignator;
                            lastDesignator = currentDesignator;
                            groupCount = 1;
                        }
                    }
                    
                    // Добавляем последнюю группу
                    if (currentGroup == lastDesignator) {
                        designatorGroupsForThisName.append(currentGroup);
                    } else {
                        // Если в группе 2 элемента - через запятую, иначе через дефис
                        if (groupCount == 2) {
                            designatorGroupsForThisName.append(currentGroup + ", " + lastDesignator);
                        } else {
                            designatorGroupsForThisName.append(currentGroup + "-" + lastDesignator);
                        }
                    }
                    
                    // Объединяем все группы дезигнаторов в одну строку через запятые
                    QString allDesignators = designatorGroupsForThisName.join(", ");
                    
                    // Разбиваем длинные группы десигнаторов используя логику комплексных строк (11 символов на строку)
                    QList<QString> designatorsSplitList = splitComplexStringByMiddle(allDesignators, 11);
                    QStringList designatorsSplit;
                    for (const QString &str : designatorsSplitList) {
                        designatorsSplit.append(str);
                    }
                    
                    // Получаем тип компонента: если количество > 1, используем множественное число, иначе единственное
                    QString componentType;
                    if (totalQuantity > 1) {
                        componentType = getComponentType(firstComponent);
                    } else {
                        componentType = getComponentTypeSingular(firstComponent);
                    }
                    
                    // Формируем список строк названия с учетом типа компонента
                    QList<QString> nameParts;
                    if (!componentType.isEmpty() && !designationParts.isEmpty()) {
                        // Проверяем, помещается ли тип компонента + первая часть названия
                        QString firstPartWithType = componentType + " " + designationParts[0];
                        if (firstPartWithType.length() <= 34) {
                            // Помещается - добавляем тип в первую строку
                            nameParts.append(firstPartWithType);
                            // Добавляем остальные части
                            for (int i = 1; i < designationParts.size(); ++i) {
                                nameParts.append(designationParts[i]);
                            }
                        } else {
                            // Не помещается - выносим тип в отдельную строку
                            nameParts.append(componentType);
                            // Добавляем все части названия
                            for (const QString &part : designationParts) {
                                nameParts.append(part);
                            }
                        }
                    } else {
                        // Типа нет или нет частей названия - используем как есть
                        nameParts = designationParts;
                    }
                    
                    // Определяем максимальное количество строк для названия и дезигнаторов
                    int maxRows = qMax(nameParts.size(), designatorsSplit.size());
                    
                    for (int rowIndex = 0; rowIndex < maxRows; ++rowIndex) {
                        SpecificationPCBRowData row;
                        
                        // Только в первой строке показываем позицию и количество
                        if (rowIndex == 0) {
                            row.position = SpecificationPCBCellData(QString::number(pos1++), 0, 1, false, false, false, 100, false);
                            row.quantity = SpecificationPCBCellData(QString::number(totalQuantity), 0, 1, false, false, false, 100, false);
                        } else {
                            // В последующих строках оставляем пустыми позицию и количество
                            row.position = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
                            row.quantity = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
                        }
                        
                        // Заполняем название
                        if (rowIndex < nameParts.size()) {
                            row.name = SpecificationPCBCellData(nameParts[rowIndex], 0, 1, false, false, false, 100, false);
                        } else {
                            row.name = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
                        }
                        
                        // Заполняем десигнаторы (если есть)
                        if (rowIndex < designatorsSplit.size()) {
                            row.note = SpecificationPCBCellData(designatorsSplit[rowIndex], 0, 1, false, false, false, 100, false);
                        } else {
                            row.note = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
                        }
                        
                        // Заполняем остальные поля согласно требованиям
                        row.format = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
                        row.zone = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
                        row.designation = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
                        
                        m_tableModel->addRow(row);
                    }
                }
            } else {
                // Если компонент один, добавляем его как отдельную строку
                ComponentModel *component = componentsInGroup.first();
                QString currentDesignation = getComponentValue(component, "ManufacturerPartNumber");
                
                // Получаем тип компонента в единственном числе (количество = 1)
                QString componentType = getComponentTypeSingular(component);
                
                // Разделяем длинное наименование на несколько строк
                QMap<QString, QString> props = component->properties();
                QString originalString = props.value("ManufacturerPartNumber", "");
                QList<QString> designationParts = splitLongDesignation(currentDesignation, originalString, component);
                
                // Формируем список строк названия с учетом типа компонента
                QList<QString> nameParts;
                if (!componentType.isEmpty() && !designationParts.isEmpty()) {
                    // Проверяем, помещается ли тип компонента + первая часть названия
                    QString firstPartWithType = componentType + " " + designationParts[0];
                    if (firstPartWithType.length() <= 34) {
                        // Помещается - добавляем тип в первую строку
                        nameParts.append(firstPartWithType);
                        // Добавляем остальные части
                        for (int i = 1; i < designationParts.size(); ++i) {
                            nameParts.append(designationParts[i]);
                        }
                    } else {
                        // Не помещается - выносим тип в отдельную строку
                        nameParts.append(componentType);
                        // Добавляем все части названия
                        for (const QString &part : designationParts) {
                            nameParts.append(part);
                        }
                    }
                } else {
                    // Типа нет или нет частей названия - используем как есть
                    nameParts = designationParts;
                }
                
                // Обрабатываем дезигнатор: если он длинный, разбиваем используя логику комплексных строк
                QString designatorStr = component->designator();
                QList<QString> designatorParts = splitComplexStringByMiddle(designatorStr, 11);
                
                // Определяем максимальное количество строк для названия и дезигнатора
                int maxParts = qMax(nameParts.size(), designatorParts.size());
                
                for (int partIndex = 0; partIndex < maxParts; ++partIndex) {
                    SpecificationPCBRowData row;
                    
                    // Только в первой строке показываем позицию и количество
                    if (partIndex == 0) {
                        row.position = SpecificationPCBCellData(QString::number(pos1++), 0, 1, false, false, false, 100, false);
                        row.quantity = SpecificationPCBCellData("1", 0, 1, false, false, false, 100, false);
                    } else {
                        // В последующих строках оставляем пустыми позицию и количество
                        row.position = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
                        row.quantity = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
                    }
                    
                    // Заполняем дезигнатор (если есть)
                    if (partIndex < designatorParts.size()) {
                        row.note = SpecificationPCBCellData(designatorParts[partIndex], 0, 1, false, false, false, 100, false);
                    } else {
                        row.note = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
                    }
                    
                    // Заполняем остальные поля согласно требованиям
                    row.format = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
                    row.zone = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
                    row.designation = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
                    
                    // Заполняем название
                    if (partIndex < nameParts.size()) {
                        row.name = SpecificationPCBCellData(nameParts[partIndex], 0, 1, false, false, false, 100, false);
                    } else {
                        row.name = SpecificationPCBCellData("", 0, 1, false, false, false, 100, false);
                    }
                    
                    m_tableModel->addRow(row);
                }
            }
        }

        qDebug() << "SpecificationPCBController::generateTableFromComponents: Таблица сгенерирована, строк:" << m_tableModel->rowCount();
    qDebug() << "SpecificationPCBController::generateTableFromComponents: Модель доступна:" << (m_tableModel ? "да" : "нет");
    qDebug() << "SpecificationPCBController::generateTableFromComponents: Количество строк в модели:" << m_tableModel->rowCount();
    qDebug() << "SpecificationPCBController::generateTableFromComponents: Количество колонок в модели:" << m_tableModel->columnCount();
        
        // Оптимизируем разрывы страниц после генерации таблицы
        m_tableModel->optimizePageBreaks();
        
    } catch (const std::exception &e) {
        qDebug() << "SpecificationPCBController::generateTableFromComponents: Ошибка при генерации:" << e.what();
    } catch (...) {
        qDebug() << "SpecificationPCBController::generateTableFromComponents: Неизвестная ошибка при генерации";
    }
    m_tableModel->addRow(emptyRow);
    SpecificationPCBRowData defaultRow6;
    defaultRow6.isHeader = false;
    defaultRow6.format = SpecificationPCBCellData("", 0, 1, false);
    defaultRow6.zone = SpecificationPCBCellData("", 0, 1, false);
    defaultRow6.position = SpecificationPCBCellData("", 0, 1, false);
    defaultRow6.designation = SpecificationPCBCellData("", 0, 1, false);
    defaultRow6.name = SpecificationPCBCellData("Примечание", 0, 1, false);
    defaultRow6.quantity = SpecificationPCBCellData("", 0, 1, false);
    defaultRow6.note = SpecificationPCBCellData("", 0, 1, false);
    m_tableModel->addRow(defaultRow6);
    SpecificationPCBRowData defaultRow6_1;
    defaultRow6_1.isHeader = false;
    defaultRow6_1.format = SpecificationPCBCellData("", 0, 1, false);
    defaultRow6_1.zone = SpecificationPCBCellData("", 0, 1, false);
    defaultRow6_1.position = SpecificationPCBCellData("", 0, 1, false);
    defaultRow6_1.designation = SpecificationPCBCellData("", 0, 1, false);
    defaultRow6_1.name = SpecificationPCBCellData("Изготовить плату печатную", 0, 1, false);
    defaultRow6_1.quantity = SpecificationPCBCellData("", 0, 1, false);
    defaultRow6_1.note = SpecificationPCBCellData("", 0, 1, false);
    m_tableModel->addRow(defaultRow6_1);
    SpecificationPCBRowData defaultRow6_2;
    defaultRow6_2.isHeader = false;
    defaultRow6_2.format = SpecificationPCBCellData("", 0, 1, false);
    defaultRow6_2.zone = SpecificationPCBCellData("", 0, 1, false);
    defaultRow6_2.position = SpecificationPCBCellData("", 0, 1, false);
    defaultRow6_2.designation = SpecificationPCBCellData("", 0, 1, false);
    // Формируем строку "По файлу" с именем PcbDoc файла, если оно есть
    QString fileText = "По файлу";
    if (!m_pcbDocFileName.isEmpty()) {
        QFileInfo fileInfo(m_pcbDocFileName);
        fileText = "По файлу " + fileInfo.fileName();
    }
    defaultRow6_2.name = SpecificationPCBCellData(fileText, 0, 1, false);
    defaultRow6_2.quantity = SpecificationPCBCellData("", 0, 1, false);
    defaultRow6_2.note = SpecificationPCBCellData("", 0, 1, false);
    m_tableModel->addRow(defaultRow6_2);
    SpecificationPCBRowData defaultRow6_3;
    defaultRow6_3.isHeader = false;
    defaultRow6_3.format = SpecificationPCBCellData("", 0, 1, false);
    defaultRow6_3.zone = SpecificationPCBCellData("", 0, 1, false);
    defaultRow6_3.position = SpecificationPCBCellData("", 0, 1, false);
    defaultRow6_3.designation = SpecificationPCBCellData("", 0, 1, false);
    defaultRow6_3.name = SpecificationPCBCellData("из состава"+getDecimalNumberBoard()+" Д10", 0, 1, false);
    defaultRow6_3.quantity = SpecificationPCBCellData("", 0, 1, false);
    defaultRow6_3.note = SpecificationPCBCellData("", 0, 1, false);
    m_tableModel->addRow(defaultRow6_3);
}

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

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

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

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

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

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

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

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

    return value;
}

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

    qDebug() << "SpecificationPCBController::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() << "SpecificationPCBController::parseExpression: Части выражения:" << parts;

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

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

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

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

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

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

QStringList SpecificationPCBController::collectPropertyNames()
{
    QStringList propertyNames;

    // Добавляем основные свойства компонента
    propertyNames << "Designator" << "Format" << "Zone" << "Position";

    // Собираем дополнительные свойства из компонентов
    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() <= 4) { // Только базовые свойства
        propertyNames << "Name" << "Type" << "Value" << "Footprint" << "Description";
        qDebug() << "SpecificationPCBController: Дополнительные свойства не найдены, используем стандартные:" << propertyNames;
    }

    // Добавляем специальное свойство для количества компонентов в группе
    propertyNames << "Quantity" << "Кол.";

    return propertyNames;
}

// Методы для работы с децимальными номерами
QString SpecificationPCBController::getDecimalNumberBoard() const
{
    QStringList mappings = getColumnMappings();
    if (mappings.size() > 7) {
        QString fieldName = mappings[7];
        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();
}

void SpecificationPCBController::setDecimalNumberBoard(const QString &value)
{
    QStringList mappings = getColumnMappings();
    while (mappings.size() <= 7) {
        mappings.append("");
    }
    mappings[7] = value;
    setColumnMappings(mappings);
}

QString SpecificationPCBController::getDecimalNumberDocument() const
{
    QStringList mappings = getColumnMappings();
    if (mappings.size() > 8) {
        QString fieldName = mappings[8];
        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();
}

void SpecificationPCBController::setDecimalNumberDocument(const QString &value)
{
    QStringList mappings = getColumnMappings();
    while (mappings.size() <= 8) {
        mappings.append("");
    }
    mappings[8] = value;
    setColumnMappings(mappings);
}

// Методы для работы с названием платы
QString SpecificationPCBController::getBoardName() const
{
    QStringList mappings = getColumnMappings();
    if (mappings.size() > 6) {
        QString fieldName = mappings[6];
        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();
}

void SpecificationPCBController::setBoardName(const QString &value)
{
    QStringList mappings = getColumnMappings();
    while (mappings.size() <= 6) {
        mappings.append("");
    }
    mappings[6] = value;
    setColumnMappings(mappings);
}

void SpecificationPCBController::setPcbDocFileName(const QString &fileName)
{
    m_pcbDocFileName = fileName;
    qDebug() << "SpecificationPCBController::setPcbDocFileName: Установлено имя файла:" << fileName;
}

QString SpecificationPCBController::getPcbDocFileName() const
{
    return m_pcbDocFileName;
}

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

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

QStringList SpecificationPCBController::getAvailableProperties() const
{
    QStringList properties = m_propertyNames;
    properties.prepend("<Пусто>");
    properties.prepend("<Авто>");
    return properties;
}

QString SpecificationPCBController::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 SpecificationPCBController::getComponentTypeSingular(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();
}

QString SpecificationPCBController::getComponentFormat(ComponentModel *component)
{
    if (!component) return "";
    
    // Получаем формат из свойств компонента
    QMap<QString, QString> props = component->properties();
    QString format = props.value("Format", "");
    if (!format.isEmpty()) {
        return format;
    }
    
    // Если формат не найден, используем значение по умолчанию
    return "A4";
}

QString SpecificationPCBController::getComponentZone(ComponentModel *component)
{
    if (!component) return "";
    
    // Получаем зону из свойств компонента
    QMap<QString, QString> props = component->properties();
    QString zone = props.value("Zone", "");
    if (!zone.isEmpty()) {
        return zone;
    }
    
    // Если зона не найдена, используем значение по умолчанию
    return "1";
}

QString SpecificationPCBController::getComponentPosition(ComponentModel *component)
{
    if (!component) return "";
    
    // Для спецификации платы позиция обычно совпадает с дезигнатором
    return component->designator();
}

QPair<QString, QString> SpecificationPCBController::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 SpecificationPCBController::addEmptyRow()
{
    if (m_tableModel) {
        m_tableModel->addEmptyRow();
        qDebug() << "SpecificationPCBController::addEmptyRow: Добавлена пустая строка";
        
        // Автоматический пересчет отключен - пересчет выполняется по кнопке "Пересчет таблицы"
        // m_tableModel->optimizePageBreaks();
    }
}

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

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

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

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

void SpecificationPCBController::optimizePageBreaks()
{
    if (m_tableModel) {
        qDebug() << "SpecificationPCBController::optimizePageBreaks: Оптимизируем разрывы страниц";
        m_tableModel->optimizePageBreaks();
        // После оптимизации разрывов пересчитываем позиции
        recalculatePositions();
    }
}

void SpecificationPCBController::recalculatePositions()
{
    if (!m_tableModel) {
        qDebug() << "SpecificationPCBController::recalculatePositions: m_tableModel is null, выходим";
        return;
    }
    
    qDebug() << "SpecificationPCBController::recalculatePositions: Начинаем перерасчет позиций, строк в таблице:" << m_tableModel->rowCount();
    
    const int POSITION_COLUMN = 2; // Индекс колонки "Поз."
    int rowCount = m_tableModel->rowCount();
    int currentPosition = 0;
    int updatedCount = 0;
    
    // Сначала собираем список строк, где позиция не пустая (пользователь ввел значение)
    QList<int> rowsWithPosition;
    
    for (int row = 0; row < rowCount; ++row) {
        QModelIndex index = m_tableModel->index(row, POSITION_COLUMN);
        if (!index.isValid()) {
            qDebug() << "SpecificationPCBController::recalculatePositions: Строка" << row << "- невалидный индекс";
            continue;
        }
        
        // Получаем значение позиции СНАЧАЛА, чтобы проверить, есть ли оно
        QString positionValueRaw = m_tableModel->data(index, Qt::DisplayRole).toString();
        QString positionValue = positionValueRaw.trimmed();
        
        // Детальное логирование для диагностики
        qDebug() << "SpecificationPCBController::recalculatePositions: Строка" << row 
                 << "- позиция (raw): '" << positionValueRaw << "'"
                 << ", позиция (trimmed): '" << positionValue << "'"
                 << ", isEmpty:" << positionValue.isEmpty();
        
        // Если позиция пустая, пропускаем строку
        if (positionValue.isEmpty()) {
            qDebug() << "SpecificationPCBController::recalculatePositions: Строка" << row << "- позиция пустая, пропускаем";
            continue;
        }
        
        // Проверяем, не является ли строка заголовком
        QModelIndex firstColumnIndex = m_tableModel->index(row, 0);
        QVariant headerVariant = m_tableModel->data(firstColumnIndex, Qt::UserRole);
        bool isHeader = false;
        
        if (headerVariant.isValid()) {
            SpecificationPCBCellData cellData = headerVariant.value<SpecificationPCBCellData>();
            isHeader = cellData.isHeader;
        }
        
        // Также проверяем через метод модели, если доступен
        if (m_tableModel->isRowHeader(row)) {
            isHeader = true;
        }
        
        // Пропускаем только заголовки (но не пустые строки, так как пользователь мог ввести позицию в пустую строку)
        if (isHeader) {
            qDebug() << "SpecificationPCBController::recalculatePositions: Строка" << row << "- заголовок, пропускаем (позиция:" << positionValue << ")";
            continue;
        }
        
        // Если позиция не пустая и строка не заголовок, добавляем в список для пересчета
        rowsWithPosition.append(row);
        qDebug() << "SpecificationPCBController::recalculatePositions: Найдена строка" << row << "с позицией:" << positionValue << "(isHeader:" << isHeader << ")";
    }
    
    qDebug() << "SpecificationPCBController::recalculatePositions: Найдено строк с позициями:" << rowsWithPosition.size();
    
    // Теперь пересчитываем позиции сквозно от 1 до n только для строк, где позиция была не пустая
    // Всегда обновляем позиции, даже если они уже правильные, чтобы гарантировать последовательность
    for (int row : rowsWithPosition) {
        QModelIndex index = m_tableModel->index(row, POSITION_COLUMN);
        if (!index.isValid()) {
            continue;
        }
        
        // Получаем текущее значение позиции
        QString positionValue = m_tableModel->data(index, Qt::DisplayRole).toString().trimmed();
        
        // Увеличиваем счетчик позиции и устанавливаем новое значение
        currentPosition++;
        QString newPosition = QString::number(currentPosition);
        
        // Всегда обновляем позицию, чтобы гарантировать последовательность
        qDebug() << "SpecificationPCBController::recalculatePositions: Обновляем позицию в строке" << row 
                 << "с '" << positionValue << "' на '" << newPosition << "'";
        bool success = m_tableModel->setData(index, newPosition, Qt::EditRole);
        if (success) {
            updatedCount++;
            // Проверяем, что значение действительно обновилось
            QString updatedValue = m_tableModel->data(index, Qt::DisplayRole).toString().trimmed();
            if (updatedValue != newPosition) {
                qDebug() << "SpecificationPCBController::recalculatePositions: ВНИМАНИЕ! Позиция в строке" << row 
                         << "не обновилась! Ожидалось:" << newPosition << ", получено:" << updatedValue;
            } else {
                qDebug() << "SpecificationPCBController::recalculatePositions: Позиция в строке" << row 
                         << "успешно обновлена на" << newPosition;
            }
        } else {
            qDebug() << "SpecificationPCBController::recalculatePositions: Ошибка при обновлении позиции в строке" << row 
                     << "- setData вернул false";
        }
    }
    
    qDebug() << "SpecificationPCBController::recalculatePositions: Перерасчет позиций завершен, обновлено строк:" << updatedCount << "из" << currentPosition;
}

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

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

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

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

QList<QString> SpecificationPCBController::splitLongDesignation(const QString &designation, const QString originalString, ComponentModel *component, int maxLength)
{
    QList<QString> result;
    
    if (designation.length() <= maxLength) {
        result.append(designation);
        return result;
    }
    
    qDebug() << "SpecificationPCBController::splitLongDesignation: Разделяем длинное наименование:" << designation;
    
    // Проверяем, является ли наименование выражением с частями
    if (originalString.startsWith("=") && component) {
        // Это выражение - разделяем по частям
        QString expr = originalString.mid(1); // Убираем начальный "="
        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() << "SpecificationPCBController::splitLongDesignation: Части выражения:" << 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() << "Обрабатываем свойство:" << trimmedPart;
                    
                    if (trimmedPart == "Designator") {
                        displayPart = component->designator();
                    } else {
                        QString propertyName = trimmedPart.startsWith("\"") && trimmedPart.endsWith("\"") 
                            ? trimmedPart.mid(1, trimmedPart.length() - 2) 
                            : trimmedPart;
                        displayPart = props.value(propertyName, "");
                        // Рекурсивно обрабатываем вложенные выражения
                        if (displayPart.startsWith("=")) {
                            qDebug() << "SpecificationPCBController::splitLongDesignation: Значение свойства является вложенным выражением, рекурсивно обрабатываем";
                            displayPart = parseExpression(component, displayPart);
                        }
                    }
                }
                
                fullString += displayPart;
            }
        }
        
        qDebug() << "SpecificationPCBController::splitLongDesignation: Собранная полная строка:" << fullString << ", длина:" << fullString.length();
        
        // Проверяем, содержит ли строка запятые (комплексная строка)
        bool isComplexString = fullString.contains(',');
        
        if (isComplexString && fullString.length() > maxLength) {
            qDebug() << "SpecificationPCBController::splitLongDesignation: Комплексная строка с запятыми, делим по середине";
            // Для комплексной строки делим по середине, а не по началу
            result = splitComplexStringByMiddle(fullString, maxLength);
        } else if (fullString.length() > maxLength) {
            qDebug() << "SpecificationPCBController::splitLongDesignation: Строка длинная, разделяем по пробелам";
            // Обычная длинная строка - разделяем по пробелам
            result = splitBySpaces(fullString, maxLength);
        } else {
            qDebug() << "SpecificationPCBController::splitLongDesignation: Строка короткая, возвращаем как есть";
            result.append(fullString);
        }
    } else {
        // Обычный текст - разделяем по пробелам
        result = splitBySpaces(designation, maxLength);
    }
    
    qDebug() << "SpecificationPCBController::splitLongDesignation: Результат разделения:" << result;
    return result;
}

QList<QString> SpecificationPCBController::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;
}

QList<QString> SpecificationPCBController::splitComplexStringByMiddle(const QString &text, int maxLength)
{
    QList<QString> result;
    
    if (text.length() <= maxLength) {
        result.append(text);
        return result;
    }
    
    qDebug() << "SpecificationPCBController::splitComplexStringByMiddle: Разделяем комплексную строку:" << text;
    
    // Ищем запятые в тексте
    QList<int> commaPositions;
    for (int i = 0; i < text.length(); ++i) {
        if (text[i] == ',') {
            commaPositions.append(i);
        }
    }
    
    if (commaPositions.isEmpty()) {
        // Если запятых нет, используем обычное разделение по пробелам
        qDebug() << "SpecificationPCBController::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() << "SpecificationPCBController::splitComplexStringByMiddle: Найдена запятая на позиции" << bestSplitPos;
        qDebug() << "SpecificationPCBController::splitComplexStringByMiddle: Левая часть:" << leftPart;
        qDebug() << "SpecificationPCBController::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() << "SpecificationPCBController::splitComplexStringByMiddle: Не удалось найти подходящую запятую, используем splitBySpaces";
        result = splitBySpaces(text, maxLength);
    }
    
    qDebug() << "SpecificationPCBController::splitComplexStringByMiddle: Результат:" << result;
    return result;
}

QStringList SpecificationPCBController::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;
}
