#include "simplelisttablecontroller.h"
#include "../model/componentmodel.h"
#include "../model/specificationpcbtablemodel.h"
#include <QDebug>
#include <QCollator>
#include <QRegExp>

SimpleListTableController::SimpleListTableController(QObject *parent)
    : QObject(parent)
    , m_tableModel(new SimpleListTableModel(this))
    , m_nameField("Name")
    , m_techReservePercent(10)
    , m_boardsCount(1)
{
    qDebug() << "SimpleListTableController::SimpleListTableController: Создан контроллер";
}

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

void SimpleListTableController::setModel(SimpleListTableModel *model)
{
    if (m_tableModel != model) {
        qDebug() << "SimpleListTableController::setModel: Заменяем модель таблицы";
        m_tableModel = model;
        // Синхронизируем процент тех запаса с моделью
        if (m_tableModel) {
            m_tableModel->setTechReservePercent(m_techReservePercent);
        }
    }
}

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

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

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

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

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

    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 = 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;
                  });

        // Группируем компоненты по наименованию (Name)
        QString prevName = "";
        QString groupStartDesignator = "";
        QString groupLastDesignator = "";
        int groupCount = 0;

        for (int i = 0; i < m_components.size(); ++i) {
            ComponentModel *component = m_components[i];
            if (!component) {
                qDebug() << "SimpleListTableController::generateTableFromComponents: Пропускаем nullptr компонент на позиции" << i;
                continue;
            }
            
            QString currentName = getComponentValue(component, m_nameField);

            if (i == 0 || currentName != prevName) {
                // Добавляем предыдущую группу, если она есть
                if (i > 0 && groupCount > 0) {
                    SimpleListRowData row;
                    
                    // Формируем строку десигнаторов
                    QString designatorText;
                    if (groupCount == 1) {
                        designatorText = groupStartDesignator;
                    } else if (groupCount == 2) {
                        designatorText = groupStartDesignator + ", " + groupLastDesignator;
                    } else {
                        designatorText = groupStartDesignator + "-" + groupLastDesignator;
                    }
                    
                    row.designator = SimpleListCellData(designatorText, false, false);
                    row.name = SimpleListCellData(prevName, false, false);
                    // (кол-во элементов * кол-во плат) + техзапас
                    int baseQty = groupCount * m_boardsCount;
                    int reserve = qMax(1, qRound(baseQty * m_techReservePercent / 100.0));
                    int quantityWithReserve = baseQty + reserve;
                    row.quantity = SimpleListCellData(QString::number(quantityWithReserve), false, false);
                    
                    if (m_tableModel) {
                        m_tableModel->addRow(row);
                    }
                }

                // Начинаем новую группу
                groupStartDesignator = component->designator();
                groupLastDesignator = component->designator();
                groupCount = 1;
                prevName = currentName;
            } else {
                // Продолжаем текущую группу - обновляем последний десигнатор
                groupLastDesignator = component->designator();
                groupCount++;
            }
        }

        // Добавляем последнюю группу
        if (groupCount > 0 && m_tableModel) {
            SimpleListRowData row;
            
            QString designatorText;
            if (groupCount == 1) {
                designatorText = groupStartDesignator;
            } else if (groupCount == 2) {
                designatorText = groupStartDesignator + ", " + groupLastDesignator;
            } else {
                designatorText = groupStartDesignator + "-" + groupLastDesignator;
            }
            
            row.designator = SimpleListCellData(designatorText, false, false);
            row.name = SimpleListCellData(prevName, false, false);
            // (кол-во элементов * кол-во плат) + техзапас
            int baseQty = groupCount * m_boardsCount;
            int reserve = qMax(1, qRound(baseQty * m_techReservePercent / 100.0));
            int quantityWithReserve = baseQty + reserve;
            row.quantity = SimpleListCellData(QString::number(quantityWithReserve), false, false);
            
            m_tableModel->addRow(row);
        }
    } catch (const std::exception &e) {
        qDebug() << "SimpleListTableController::generateTableFromComponents: Ошибка:" << e.what();
    }

    qDebug() << "SimpleListTableController::generateTableFromComponents: Генерация завершена";
}

void SimpleListTableController::generateTableFromSpecificationPCB(SpecificationPCBTableModel *specPCBModel)
{
    if (!m_tableModel || !specPCBModel) {
        qDebug() << "SimpleListTableController::generateTableFromSpecificationPCB: Модель недоступна";
        return;
    }

    qDebug() << "SimpleListTableController::generateTableFromSpecificationPCB: Начинаем генерацию из SpecificationPCB";

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

    // Получаем все строки из SpecificationPCB
    QList<SpecificationPCBRowData> allRows = specPCBModel->getRows();
    
    if (allRows.isEmpty()) {
        qDebug() << "SimpleListTableController::generateTableFromSpecificationPCB: Нет данных в SpecificationPCB";
        return;
    }

    // Находим индекс строки с "Прочие изделия"
    int startIndex = -1;
    for (int i = 0; i < allRows.size(); ++i) {
        if (allRows[i].name.value == "Прочие изделия" && allRows[i].isHeader) {
            startIndex = i;
            break;
        }
    }

    if (startIndex == -1) {
        qDebug() << "SimpleListTableController::generateTableFromSpecificationPCB: Не найдена строка 'Прочие изделия'";
        return;
    }

    // Находим индекс строки с "Примечание"
    int endIndex = -1;
    for (int i = startIndex + 1; i < allRows.size(); ++i) {
        if (allRows[i].name.value == "Примечание" && !allRows[i].isHeader) {
            endIndex = i;
            break;
        }
    }

    if (endIndex == -1) {
        qDebug() << "SimpleListTableController::generateTableFromSpecificationPCB: Не найдена строка 'Примечание'";
        // Если не найдено "Примечание", берем все строки до конца
        endIndex = allRows.size();
    }

    qDebug() << "SimpleListTableController::generateTableFromSpecificationPCB: Найдены строки от" << startIndex << "до" << endIndex;

    // Извлекаем строки между "Прочие изделия" и "Примечание"
    // Пропускаем саму строку "Прочие изделия" и пустые строки после нее
    QList<SpecificationPCBRowData> relevantRows;
    for (int i = startIndex + 1; i < endIndex; ++i) {
        // Пропускаем пустые строки
        if (allRows[i].isEmpty) {
            continue;
        }
        // Пропускаем заголовки
        if (allRows[i].isHeader) {
            continue;
        }
        relevantRows.append(allRows[i]);
    }

    if (relevantRows.isEmpty()) {
        qDebug() << "SimpleListTableController::generateTableFromSpecificationPCB: Нет релевантных строк";
        return;
    }

    qDebug() << "SimpleListTableController::generateTableFromSpecificationPCB: Найдено релевантных строк:" << relevantRows.size();

    // Группируем строки по позиции (position)
    // Строки с одинаковой позицией должны быть склеены вместе
    // Используем QMap для группировки, но обрабатываем в порядке появления
    QMap<QString, QList<SpecificationPCBRowData>> groupedByPosition;
    QStringList positionOrder; // Для сохранения порядка позиций
    
    QString currentPosition;
    for (const SpecificationPCBRowData &row : relevantRows) {
        QString position = row.position.value.trimmed();
        // Если позиция пуста, это продолжение предыдущей позиции
        if (position.isEmpty()) {
            // Добавляем к текущей позиции
            if (!currentPosition.isEmpty()) {
                groupedByPosition[currentPosition].append(row);
            }
        } else {
            // Новая позиция
            currentPosition = position;
            if (!groupedByPosition.contains(position)) {
                groupedByPosition[position] = QList<SpecificationPCBRowData>();
                positionOrder.append(position); // Сохраняем порядок
            }
            groupedByPosition[position].append(row);
        }
    }

    qDebug() << "SimpleListTableController::generateTableFromSpecificationPCB: Сгруппировано позиций:" << groupedByPosition.size();

    // Обрабатываем каждую группу позиций в порядке появления
    for (const QString &position : positionOrder) {
        if (!groupedByPosition.contains(position)) {
            continue;
        }
        QList<SpecificationPCBRowData> rowsForPosition = groupedByPosition[position];

        if (rowsForPosition.isEmpty()) {
            continue;
        }

        // Склеиваем наименование (name) и примечание (note) для всех строк этой позиции
        QStringList nameParts;
        QStringList noteParts;

        for (const SpecificationPCBRowData &row : rowsForPosition) {
            QString nameValue = row.name.value.trimmed();
            QString noteValue = row.note.value.trimmed();

            if (!nameValue.isEmpty()) {
                nameParts.append(nameValue);
            }
            // Примечание (десигнаторы): разбиваем по переносам строк внутри ячейки (R1, R3\nR5 -> R1, R3, R5)
            if (!noteValue.isEmpty()) {
                QString normalized = noteValue.replace("\r\n", "\n").replace('\r', '\n');
                for (const QString &line : normalized.split('\n', Qt::SkipEmptyParts)) {
                    QString trimmed = line.trimmed();
                    if (!trimmed.isEmpty()) {
                        noteParts.append(trimmed);
                    }
                }
            }
        }

        // Объединяем части наименования и примечания обратно в одну строку
        QString fullName = nameParts.join(" "); // Склеиваем многострочные наименования
        QString fullNote = noteParts.join(", "); // Десигнаторы (R1, R3, R5) — между частями после переноса ставим запятую

        // Получаем количество из первой строки позиции (остальные строки обычно пустые по количеству)
        int quantity = 0;
        for (const SpecificationPCBRowData &row : rowsForPosition) {
            QString qtyStr = row.quantity.value.trimmed();
            if (!qtyStr.isEmpty()) {
                bool ok;
                int qty = qtyStr.toInt(&ok);
                if (ok && qty > 0) {
                    quantity = qty;
                    break;
                }
            }
        }

        // Если количество не найдено, считаем количество строк с номерами позиций
        if (quantity == 0) {
            quantity = 1; // По умолчанию 1
        }

        // (кол-во элементов * кол-во плат) + техзапас
        int baseQty = quantity * m_boardsCount;
        int reserve = qMax(1, qRound(baseQty * m_techReservePercent / 100.0));
        int quantityWithReserve = baseQty + reserve;

        // Создаем строку для SimpleList
        SimpleListRowData row;
        row.designator = SimpleListCellData(fullNote, false, false); // Поз.обозначение из примечания (десигнаторы)
        row.name = SimpleListCellData(fullName, false, false); // Наименование (склеенное из всех строк позиции)
        row.quantity = SimpleListCellData(QString::number(quantityWithReserve), false, false);

        m_tableModel->addRow(row);

        qDebug() << "SimpleListTableController::generateTableFromSpecificationPCB: Добавлена строка - Позиция:" << position 
                 << "Поз.обозначение:" << fullNote << "Наименование:" << fullName << "Кол-во:" << quantityWithReserve;
    }

    qDebug() << "SimpleListTableController::generateTableFromSpecificationPCB: Генерация завершена, строк:" << m_tableModel->rowCount();
}

void SimpleListTableController::updateTableFromComponents()
{
    generateTableFromComponents();
}

void SimpleListTableController::addEmptyRow()
{
    if (!m_tableModel) {
        return;
    }
    m_tableModel->addEmptyRow();
}

void SimpleListTableController::addEmptyRowAt(int position)
{
    if (!m_tableModel) {
        return;
    }
    m_tableModel->addEmptyRowAt(position);
}

void SimpleListTableController::insertEmptyRowAt(int position)
{
    if (!m_tableModel) {
        return;
    }
    m_tableModel->addEmptyRowAt(position);
}

void SimpleListTableController::removeRow(int row)
{
    if (!m_tableModel) {
        return;
    }
    m_tableModel->removeRow(row);
}

void SimpleListTableController::clearTable()
{
    if (!m_tableModel) {
        return;
    }
    m_tableModel->clear();
}

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

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

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

    return value;
}

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

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

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

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

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

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

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

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

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

    return propertyNames;
}

QPair<QString, QString> SimpleListTableController::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 SimpleListTableController::setNameField(const QString &fieldName)
{
    qDebug() << "SimpleListTableController::setNameField: Устанавливаем поле наименования:" << fieldName;
    m_nameField = fieldName;
}

QString SimpleListTableController::getNameField() const
{
    return m_nameField;
}

void SimpleListTableController::setTechReservePercent(int percent)
{
    qDebug() << "SimpleListTableController::setTechReservePercent: Устанавливаем процент тех запаса:" << percent;
    m_techReservePercent = percent;
    
    // Синхронизируем с моделью для обновления заголовка
    if (m_tableModel) {
        m_tableModel->setTechReservePercent(percent);
    }
}

int SimpleListTableController::getTechReservePercent() const
{
    return m_techReservePercent;
}

void SimpleListTableController::setBoardsCount(int count)
{
    if (count < 1) {
        count = 1;
    }
    m_boardsCount = count;
}

int SimpleListTableController::getBoardsCount() const
{
    return m_boardsCount;
}

QStringList SimpleListTableController::getAvailableProperties() const
{
    return m_propertyNames;
}

