#include "perechentablecontroller.h"
#include "../model/componentmodel.h"
#include "../model/designatormappingmodel.h"
#include <QDebug>
#include <QCollator>

PerechenTableController::PerechenTableController(QObject *parent)
    : QObject(parent)
    , m_tableModel(new PerechenTableModel(this))
    , m_designatorMappingModel(nullptr)
    , m_projectSettingsModel(nullptr)
{
    // Устанавливаем маппинг по умолчанию для группировки
    // Эти настройки будут переопределены в MainController
    m_columnMappings << "Designator" << "Name" << "Quantity" << "Note";
}

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

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

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

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

void PerechenTableController::setComponents(const QList<ComponentModel*> &components)
{
    m_components = components;

    // Собираем доступные свойства из компонентов
    m_propertyNames = collectPropertyNames();
}

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

    qDebug() << "PerechenTableController::generateTableFromComponents: Начинаем генерацию таблицы";
    qDebug() << "PerechenTableController::generateTableFromComponents: Текущие настройки колонок:" << m_columnMappings;
    
    // Дополнительная проверка настроек колонок
    if (m_tableModel) {
        QStringList modelMappings = m_tableModel->columnMappings();
        qDebug() << "PerechenTableController::generateTableFromComponents: Настройки колонок в модели:" << modelMappings;
        
        // Если настройки в модели отличаются от локальных, синхронизируем их
        if (modelMappings != m_columnMappings) {
            qDebug() << "PerechenTableController::generateTableFromComponents: Синхронизируем настройки колонок";
            m_columnMappings = modelMappings;
        }
    }
    
    qDebug() << "PerechenTableController::generateTableFromComponents: Количество компонентов:" << m_components.size();

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

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

    try {
        // Группируем компоненты по типу
       // QList<ComponentGroup> groups = groupComponentsByType(m_components);

        // Добавляем заголовок таблицы

        PerechenRowData emptyRow;
        emptyRow.isEmpty = true;
    
        
        // Добавляем группы компонентов с группировкой по типу
        int rowNumber = 1;
        QString currentType;
        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 = PerechenTableController::splitDesignator(designatorA);
                      QPair<QString, QString> partsB = PerechenTableController::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;
                  });

        QString complesDesignatorFront = "";
        QString complesDesignatorBack = "";
        // Группируем компоненты по буквенной части десигнатора
        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) {
                // Если компонентов больше одного, добавляем заголовок типа
                PerechenRowData headerRow;
               
            
                m_tableModel->addRow(emptyRow);
                headerRow.isHeader = true;
                headerRow.designation = PerechenCellData(getComponentType(componentsInGroup.first()), 0, 1, true, false, false, 100, true);
                
                m_tableModel->addRow(headerRow);
                m_tableModel->addRow(emptyRow);
                
                // Обрабатываем компоненты последовательно, группируя по currentDesignation
                QString prevDesignation = "";
                QString prevOriginalString = "";
                ComponentModel *prevComponent = nullptr;
                QString groupStartDesignator = "";
                QString groupLastDesignator = "";
                int groupCount = 0;
                
                for (int i = 0; i < componentsInGroup.size(); ++i) {
                    ComponentModel *component = componentsInGroup[i];
                    QString currentDesignation = getComponentValue(component, m_columnMappings.value(0, "<Пусто>"));
                    
                    if (i == 0 || currentDesignation != prevDesignation) {
                        // Добавляем предыдущую группу, если она есть
                        if (i > 0 && groupCount > 0) {
                            // Разделяем длинное наименование на несколько строк
                            // Используем исходное значение для правильного разделения по частям
                            QList<QString> designationParts = splitLongDesignation(prevDesignation, prevOriginalString, prevComponent);
                            
                            for (int partIndex = 0; partIndex < designationParts.size(); ++partIndex) {
                                PerechenRowData row;
                                
                                // Только в первой строке показываем позицию и количество
                                if (partIndex == 0) {
                                    QString positionText;
                                    if (groupCount == 1) {
                                        positionText = groupStartDesignator;
                                    } else if (groupCount == 2) {
                                        // Если в группе 2 элемента - через запятую
                                        positionText = groupStartDesignator + ", " + groupLastDesignator;
                                    } else {
                                        // Если в группе 3 и более элементов - через дефис
                                        positionText = groupStartDesignator + "-" + groupLastDesignator;
                                    }
                                    row.position = PerechenCellData(positionText, 0, 1, false, false, false, 100, false);
                                    row.quantity = PerechenCellData(QString::number(groupCount), 0, 1, false, false, false, 100, false);
                                } else {
                                    // В последующих строках оставляем пустыми позицию и количество
                                    row.position = PerechenCellData("", 0, 1, false, false, false, 100, false);
                                    row.quantity = PerechenCellData("", 0, 1, false, false, false, 100, false);
                                }
                                
                                row.designation = PerechenCellData(designationParts[partIndex], 0, 1, false, false, false, 100, false);
                                row.note = PerechenCellData("", 0, 1, false, false, false, 100, false);
                                m_tableModel->addRow(row);
                            }
                        }
                        
                        // Начинаем новую группу
                        groupStartDesignator = component->designator();
                        groupLastDesignator = component->designator();
                        groupCount = 1;
                        prevDesignation = currentDesignation;
                        
                        // Сохраняем исходное значение и компонент для правильного разделения
                        QMap<QString, QString> props = component->properties();
                        prevOriginalString = props.value(m_columnMappings.value(0, "<Пусто>"), "");
                        prevComponent = component;
                    } else {
                        // Продолжаем текущую группу - обновляем последний десигнатор
                        groupLastDesignator = component->designator();
                        groupCount++;
                    }
                }
                
                // Добавляем последнюю группу
                if (groupCount > 0) {
                    // Разделяем длинное наименование на несколько строк
                    // Используем сохраненные значения для правильного разделения
                    QList<QString> designationParts = splitLongDesignation(prevDesignation, prevOriginalString, prevComponent);
                    
                    for (int partIndex = 0; partIndex < designationParts.size(); ++partIndex) {
                        PerechenRowData row;
                        
                        // Только в первой строке показываем позицию и количество
                        if (partIndex == 0) {
                            QString positionText;
                            if (groupCount == 1) {
                                positionText = groupStartDesignator;
                            } else if (groupCount == 2) {
                                // Если в группе 2 элемента - через запятую
                                positionText = groupStartDesignator + ", " + groupLastDesignator;
                            } else {
                                // Если в группе 3 и более элементов - через дефис
                                positionText = groupStartDesignator + "-" + groupLastDesignator;
                            }
                            row.position = PerechenCellData(positionText, 0, 1, false, false, false, 100, false);
                            row.quantity = PerechenCellData(QString::number(groupCount), 0, 1, false, false, false, 100, false);
                        } else {
                            // В последующих строках оставляем пустыми позицию и количество
                            row.position = PerechenCellData("", 0, 1, false, false, false, 100, false);
                            row.quantity = PerechenCellData("", 0, 1, false, false, false, 100, false);
                        }
                        
                        row.designation = PerechenCellData(designationParts[partIndex], 0, 1, false, false, false, 100, false);
                        row.note = PerechenCellData("", 0, 1, false, false, false, 100, false);
                        m_tableModel->addRow(row);
                    }
                }
            } else {
                // Если компонент один, объединяем тип и обозначение
                ComponentModel *component = componentsInGroup.first();
                QString componentType = getComponentType(component);
                QString currentDesignation = getComponentValue(component, m_columnMappings.value(0, "<Пусто>"));
                QString fullDesignation = componentType + " " + currentDesignation;
                
                // Разделяем длинное наименование на несколько строк
                // Нужно получить исходное значение для правильного разделения
                QMap<QString, QString> props = component->properties();
                QString originalString = props.value(m_columnMappings.value(0, "<Пусто>"), "");
                QList<QString> designationParts = splitLongDesignation(fullDesignation, originalString, component);
                
                m_tableModel->addRow(emptyRow);
                
                for (int partIndex = 0; partIndex < designationParts.size(); ++partIndex) {
                    PerechenRowData row;
                    
                    // Только в первой строке показываем позицию и количество
                    if (partIndex == 0) {
                        row.position = PerechenCellData(component->designator(), 0, 1, false, false, false, 100, false);
                        row.quantity = PerechenCellData("1", 0, 1, false, false, false, 100, false);
                    } else {
                        // В последующих строках оставляем пустыми позицию и количество
                        row.position = PerechenCellData("", 0, 1, false, false, false, 100, false);
                        row.quantity = PerechenCellData("", 0, 1, false, false, false, 100, false);
                    }
                    
                    row.designation = PerechenCellData(designationParts[partIndex], 0, 1, false, false, false, 100, false);
                    row.note = PerechenCellData("", 0, 1, false, false, false, 100, false);
                    m_tableModel->addRow(row);
                }
            }
        }

        // for (const ComponentGroup &group : groups) {
        //     if (group.components.isEmpty()) {
        //         continue;
        //     }

        //     // Добавляем пустую строку между разными типами компонентов
        //     if (currentType != group.componentType && !currentType.isEmpty()) {
        //         PerechenRowData emptyRow;
        //         emptyRow.isEmpty = true;
        //         m_tableModel->addRow(emptyRow);
        //     }

        //     // Добавляем заголовок типа компонента, если он изменился
        //     if (currentType != group.componentType) {
        //         PerechenRowData typeHeaderRow;
        //         typeHeaderRow.isHeader = true;
        //         typeHeaderRow.designation = PerechenCellData(group.componentType, 0, 1, true);
        //         m_tableModel->addRow(typeHeaderRow);
        //         currentType = group.componentType;
        //     }

        //     // Если в группе один элемент, объединяем тип и наименование
        //     if (group.components.size() == 1) {
        //         PerechenRowData row;

        //         // Заполняем данные в зависимости от маппинга
        //         for (int col = 0; col < 4; ++col) {
        //             QString mapping = m_columnMappings.value(col, "<Пусто>");
        //             QString value;
        //             bool isAuto = false;

        //             if (mapping == "<Авто>") {
        //                 value = QString::number(rowNumber);
        //                 isAuto = true;
        //             } else if (mapping == "<Пусто>") {
        //                 value = "";
        //             } else if (mapping == "Designator") {
        //                 // Для колонки Designator используем дезигнатор компонента
        //                 value = group.components.first()->designator();
        //             } else if (mapping == "Quantity" || mapping == "Кол.") {
        //                 // Для колонки количества используем количество компонентов в группе
        //                 value = QString::number(group.components.size());
        //             } else if (mapping == "Name" || mapping == "Наименование") {
        //                 // Для наименования используем название группы (это то, что возвращает getComponentDesignation)
        //                 value = group.name;
        //             } else {
        //                 // Для остальных свойств берем значение из компонента
        //                 ComponentModel *component = group.components.first();
        //                 value = getComponentValue(component, mapping);
        //             }

        //             PerechenCellData cellData(value, rowNumber, 1, false, isAuto, value.isEmpty());

        //             switch (col) {
        //             case 0: row.position = cellData; break;
        //             case 1: row.designation = cellData; break;
        //             case 2: row.quantity = cellData; break;
        //             case 3: row.note = cellData; break;
        //             }
        //         }

        //         row.rowNumber = rowNumber++;
        //         m_tableModel->addRow(row);
        //     } else {
        //         // Если в группе несколько элементов, добавляем строку с диапазоном
        //         PerechenRowData row;

        //         // Заполняем данные в зависимости от маппинга
        //         for (int col = 0; col < 4; ++col) {
        //             QString mapping = m_columnMappings.value(col, "<Пусто>");
        //             QString value;
        //             bool isAuto = false;

        //             if (mapping == "<Авто>") {
        //                 value = QString::number(rowNumber);
        //                 isAuto = true;
        //             } else if (mapping == "<Пусто>") {
        //                 value = "";
        //             } else if (mapping == "Designator") {
        //                 // Для колонки Designator используем диапазон обозначений группы
        //                 value = group.designatorRange;
        //             } else if (mapping == "Quantity" || mapping == "Кол.") {
        //                 // Для колонки количества используем количество компонентов в группе
        //                 value = QString::number(group.components.size());
        //             } else if (mapping == "Name" || mapping == "Наименование") {
        //                 // Для наименования используем название группы (это то, что возвращает getComponentDesignation)
        //                 value = group.name;
        //             } else {
        //                 // Для остальных свойств берем значение из первого компонента группы
        //                 ComponentModel *firstComponent = group.components.first();
        //                 value = getComponentValue(firstComponent, mapping);
        //             }

        //             PerechenCellData cellData(value, rowNumber, 1, false, isAuto, value.isEmpty());

        //             switch (col) {
        //             case 0: row.position = cellData; break;
        //             case 1: row.designation = cellData; break;
        //             case 2: row.quantity = cellData; break;
        //             case 3: row.note = cellData; break;
        //             }
        //         }

        //         row.rowNumber = rowNumber++;
        //         m_tableModel->addRow(row);
        //     }
        // }

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

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

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

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

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

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

    qDebug() << "PerechenTableController::getComponentValue: propertyName =" << propertyName;
    qDebug() << "PerechenTableController::getComponentValue: Текущие настройки колонок:" << m_columnMappings;

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

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

    return value;
}

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

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

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

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

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

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

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

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

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

QStringList PerechenTableController::collectPropertyNames()
{
    QStringList propertyNames;

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

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

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

    return propertyNames;
}

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

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

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







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

    // Получаем тип компонента из маппинга дезигнаторов
    if (m_designatorMappingModel) {
        // Сначала пытаемся найти по полному дезигнатору (две буквы)
        QString componentType = m_designatorMappingModel->getComponentType(component->designator(), true); // true для множественного числа
        if (!componentType.isEmpty()) {
            return componentType;
        }
        
        // Если не найдено по двум буквам, пытаемся найти по первой букве
        QString designator = component->designator();
        if (designator.length() >= 1) {
            QString firstLetter = designator.left(1);
            componentType = m_designatorMappingModel->getComponentType(firstLetter, 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();
}







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

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

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

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

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

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

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

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

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

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

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

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