#include "maincontroller.h"
#include "../model/componenttablemodel.h"
#include "../model/projectparamtablemodel.h"
#include "../model/projectsettingsmodel.h"
#include "../model/designatormappingmodel.h"
#include "../model/perechentablemodel.h"
#include "../model/specificationpcbtablemodel.h"
#include "../model/specificationtablemodel.h"
#include "../model/vedomosttablemodel.h"
#include "../model/simplelisttablemodel.h"
#include "../model/titleinscriptionsmodel.h"
#include "../model/pcbmaterialmodel.h"
#include "perechentablecontroller.h"
#include "simplelisttablecontroller.h"
#include "specificationpcbcontroller.h"
#include "specificationcontroller.h"
#include "vedomostcontroller.h"
#include "databasecontroller.h"
#include "altiumparser.h"
#include "csvexporter.h"
#include <QDateTime>
#include <QFileInfo>
#include <QStandardPaths>
#include <QCoreApplication>
#include <QDir>
#include <QMap>

MainController::MainController(QObject *parent)
    : QObject(parent)
    , m_componentTableModel(new ComponentTableModel(this))
    , m_projectParamTableModel(new ProjectParamTableModel(this))
    , m_projectSettingsModel(new ProjectSettingsModel(this))
    , m_designatorMappingModel(new DesignatorMappingModel(this))
    , m_perechenTableModel(new PerechenTableModel(this))
    , m_perechenTableController(new PerechenTableController(this))
    , m_specificationPCBTableModel(new SpecificationPCBTableModel(this))
    , m_specificationPCBController(new SpecificationPCBController(this))
    , m_specificationTableModel(new SpecificationTableModel(this))
    , m_specificationController(new SpecificationController(this))
    , m_vedomostTableModel(new VedomostTableModel(this))
    , m_vedomostController(new VedomostController(this))
    , m_simpleListTableModel(new SimpleListTableModel(this))
    , m_simpleListTableController(new SimpleListTableController(this))
    , m_titleInscriptionsModel(new TitleInscriptionsModel(this))
    , m_pcbMaterialModel(new PCBMaterialModel(this))
    , m_databaseController(new DataBaseController(this))
    , m_globalDatabaseController(new DataBaseController(this))
    , m_altiumParser(new AltiumParser(this))
    , m_currentVariant(QString())
    , m_pdfController(new PDFController(this))
    , m_csvExporter(new CSVExporter(this))
{
    // Устанавливаем глобальный контроллер БД в модель маппинга дезигнаторов
    m_designatorMappingModel->setDatabaseController(m_globalDatabaseController);
    
    // Устанавливаем модель маппинга дезигнаторов в контроллер перечня
    m_perechenTableController->setDesignatorMappingModel(m_designatorMappingModel);
    
    // Устанавливаем контроллер БД в модель настроек проекта
    m_projectSettingsModel->setDatabaseController(m_databaseController);
    
    // Устанавливаем модель настроек проекта в контроллеры
    m_perechenTableController->setProjectSettingsModel(m_projectSettingsModel);
    m_specificationPCBController->setProjectSettingsModel(m_projectSettingsModel);
    m_specificationController->setProjectSettingsModel(m_projectSettingsModel);
    m_vedomostController->setProjectSettingsModel(m_projectSettingsModel);
    
    // Устанавливаем MainController в контроллеры
    m_specificationPCBController->setMainController(this);
    m_specificationController->setMainController(this);
    m_vedomostController->setMainController(this);
    
    // Устанавливаем модель маппинга дезигнаторов в контроллеры
    m_specificationPCBController->setDesignatorMappingModel(m_designatorMappingModel);
    m_vedomostController->setDesignatorMappingModel(m_designatorMappingModel);
    
    // Устанавливаем связь между PerechenTableModel и PerechenTableController
    m_perechenTableController->setModel(m_perechenTableModel);
    
    // Устанавливаем настройки колонок по умолчанию в контроллер перечня
    QStringList defaultColumnMappings = QStringList() << "Designator" << "Name" << "Quantity" << "Note";
    m_perechenTableController->setColumnMappings(defaultColumnMappings);
    
    // Устанавливаем настройки колонок по умолчанию в контроллер спецификации платы
    QStringList defaultSpecPCBColumnMappings = QStringList() << "Format" << "Zone" << "Position" << "Designator" << "Name" << "Quantity" << "Note";
    m_specificationPCBController->setColumnMappings(defaultSpecPCBColumnMappings);
    
    // Устанавливаем настройки колонок по умолчанию в контроллер спецификации материалов
    QStringList defaultSpecColumnMappings = QStringList() << "Format" << "Zone" << "Position" << "Designation" << "Name" << "Quantity" << "Note";
    m_specificationController->setColumnMappings(defaultSpecColumnMappings);
    
    // Устанавливаем настройки колонок по умолчанию в контроллер ведомости покупных изделий
    QStringList defaultVedomostColumnMappings = QStringList() << "Name" << "ProductCode" << "DocumentCode" << "Supplier" 
                                                              << "WhereUsed" << "QuantityPerItem" << "QuantityInSet" 
                                                              << "QuantityForReg" << "TotalQuantity" << "Note";
    m_vedomostController->setColumnMappings(defaultVedomostColumnMappings);
    
    // Устанавливаем модель ведомости в контроллер
    m_vedomostController->setModel(m_vedomostTableModel);
    
    // Устанавливаем модель SimpleList в контроллер
    m_simpleListTableController->setModel(m_simpleListTableModel);
    
    connect(m_databaseController, &DataBaseController::databaseError,
            this, &MainController::databaseError);

    // Подключаем сигналы от парсера к контроллеру
    connect(m_altiumParser, &AltiumParser::parsingStarted,
            this, &MainController::parsingStarted);
    connect(m_altiumParser, &AltiumParser::parsingProgress,
            this, &MainController::parsingProgress);
    connect(m_altiumParser, &AltiumParser::parsingFinished,
            this, &MainController::parsingFinished);
    connect(m_altiumParser, &AltiumParser::parsingError,
            this, &MainController::error);
    
    // Устанавливаем базу данных в парсер
    m_altiumParser->setDatabase(m_databaseController);
    
    // Устанавливаем базу данных в модель материалов платы
    m_pcbMaterialModel->setDatabase(m_databaseController);
}

MainController::~MainController() {
}

ComponentTableModel* MainController::componentTableModel() const {
    return m_componentTableModel;
}

ProjectParamTableModel* MainController::projectParamTableModel() const {
    return m_projectParamTableModel;
}

ProjectSettingsModel* MainController::projectSettingsModel() const {
    return m_projectSettingsModel;
}

DesignatorMappingModel* MainController::designatorMappingModel() const {
    return m_designatorMappingModel;
}

PerechenTableModel* MainController::perechenTableModel() const {
    return m_perechenTableModel;
}

PerechenTableController* MainController::perechenTableController() const {
    return m_perechenTableController;
}

SpecificationPCBTableModel* MainController::specificationPCBTableModel() const {
    return m_specificationPCBTableModel;
}

SpecificationPCBController* MainController::specificationPCBController() const {
    return m_specificationPCBController;
}

SpecificationTableModel* MainController::specificationTableModel() const {
    return m_specificationTableModel;
}

SpecificationController* MainController::specificationController() const {
    return m_specificationController;
}

VedomostTableModel* MainController::vedomostTableModel() const {
    return m_vedomostTableModel;
}

VedomostController* MainController::vedomostController() const {
    return m_vedomostController;
}

SimpleListTableModel* MainController::simpleListTableModel() const {
    return m_simpleListTableModel;
}

SimpleListTableController* MainController::simpleListTableController() const {
    return m_simpleListTableController;
}

TitleInscriptionsModel* MainController::titleInscriptionsModel() const {
    return m_titleInscriptionsModel;
}

PCBMaterialModel* MainController::pcbMaterialModel() const {
    return m_pcbMaterialModel;
}

bool MainController::initializeDatabase(const QString &dbPath) {
    // Генерируем уникальное имя соединения для проектной БД
    QString connectionName = "project_db_" + QString::number(QDateTime::currentMSecsSinceEpoch());
    
    if (!m_databaseController->initializeDatabase(dbPath, connectionName)) {
        return false;
    }
    
    return true;
}

bool MainController::initializeGlobalDatabase() {
    // Используем абсолютный путь для глобальной БД, чтобы она находилась в правильном месте
    // независимо от рабочей директории приложения
    QString globalDbPath;
    
    // Пробуем использовать стандартную директорию для данных приложения
    QString appDataPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
    if (!appDataPath.isEmpty()) {
        QDir appDataDir(appDataPath);
        if (!appDataDir.exists()) {
            appDataDir.mkpath(".");
        }
        globalDbPath = appDataDir.absoluteFilePath("components.db");
    } else {
        // Fallback: используем директорию приложения
        globalDbPath = QCoreApplication::applicationDirPath() + "/components.db";
    }
    
    // Инициализируем глобальную БД для настроек с уникальным именем соединения
    if (!m_globalDatabaseController->initializeDatabase(globalDbPath, "global_db")) {
        return false;
    }
    
    // Загружаем данные маппинга дезигнаторов из БД
    m_designatorMappingModel->loadDataFromDatabase();
    
    return true;
}

bool MainController::isDatabaseOpen() const {
    return m_databaseController->isDatabaseOpen();
}

QString MainController::lastError() const {
    return m_databaseController->lastError();
}

void MainController::clearAllData() {
    // Проверяем, открыта ли база данных проекта
    if (!m_databaseController->isDatabaseOpen()) {
        return;
    }
    
    m_databaseController->clearAllData();
    
    // Сначала загружаем настройки проекта, чтобы установить правильный текущий вариант
    loadProjectSettingsFromDatabase();
    
    // Затем загружаем компоненты с правильным текущим вариантом
    loadComponentsFromDatabase();
    loadProjectParamsFromDatabase();
    loadPCBMaterialsFromDatabase();
}

bool MainController::setCurrentVariant(const QString &variant) {
    m_currentVariant = variant;
    
    // Обновляем вариант в модели настроек
    if (m_projectSettingsModel) {
        m_projectSettingsModel->setCurrentVariant(variant);
    }
    
    // Проверяем, открыта ли база данных
    if (!m_databaseController->isDatabaseOpen()) {
        if (!m_databaseController->initializeDatabase("components.db")) {
            return false;
        }
    }
    
    return loadComponentsFromDatabase();
}

bool MainController::loadComponentsFromDatabase() {
    // Проверяем, открыта ли база данных проекта
    if (!m_databaseController->isDatabaseOpen()) {
        return false;
    }
    
    // Загружаем список вариантов
    QList<VariantData> variants = m_databaseController->getAllVariants();
    QStringList variantNames;
    for (const auto &variant : variants) {
        variantNames.append(variant.name);
    }
    
    // Устанавливаем варианты в модель таблицы
    m_componentTableModel->setVariants(variantNames);
    
    QList<ComponentData> components = m_databaseController->getAllComponents();
    
    m_componentTableModel->clearComponents();
    
    // Получаем текущий вариант из контроллера
    QString currentVariant = m_currentVariant;
    if (currentVariant.isEmpty()) {
        currentVariant = "No Variations";
    }
    
    // Собираем все уникальные имена свойств
    QSet<QString> allPropertyNames;
    
    for (const auto &data : components) {
        ComponentModel* component = new ComponentModel();
        component->setId(data.id);
        component->setDesignator(data.designator);
        component->setBaseProperties(data.baseProperties);
        
        // Устанавливаем текущий вариант для компонента
        component->setCurrentVariant(currentVariant);
        
        // Добавляем свойства вариантов
        for (auto it = data.variantProperties.begin(); it != data.variantProperties.end(); ++it) {
            QString variantName = it.key();
            QMap<QString, QString> variantProps = it.value();
            
            component->setVariantProperties(variantName, variantProps);
        }
        
        m_componentTableModel->addComponent(component);
        
        // Собираем имена всех свойств (базовых и вариативных)
        allPropertyNames.unite(data.baseProperties.keys().toSet());
        for (auto it = data.variantProperties.begin(); it != data.variantProperties.end(); ++it) {
            allPropertyNames.unite(it.value().keys().toSet());
        }
    }
    
    // Обновляем список имен свойств в модели таблицы
    QStringList propertyNames = allPropertyNames.values();
    propertyNames.sort();
    m_componentTableModel->setPropertyNames(propertyNames);
    
    // Устанавливаем текущий вариант в модели таблицы и обновляем свойства компонентов
    m_componentTableModel->setCurrentVariant(currentVariant);
    
    // Обновляем компоненты в контроллере перечня
    if (m_perechenTableController) {
        m_perechenTableController->setComponents(m_componentTableModel->getComponents());
    }
    
    // Обновляем компоненты в контроллере ведомости покупных изделий
    if (m_vedomostController) {
        m_vedomostController->setComponents(m_componentTableModel->getComponents());
    }
    
    // Загружаем материалы платы
    loadPCBMaterialsFromDatabase();
    
    return true;
}

bool MainController::saveComponentsToDatabase() {
    // При ручном сохранении сохраняем только основные данные компонентов
    // Свойства и варианты сохраняются только во время парсинга
    QList<ComponentModel*> components = m_componentTableModel->getComponents();
    
    bool success = true;
    for (ComponentModel* c : components) {
        // Обновляем только designator компонента
        if (!m_databaseController->updateComponentDesignator(c->id(), c->designator())) {
            success = false;
        }
    }
    
    return success;
}

bool MainController::saveProjectParamsToDatabase() {
    // Проверяем, открыта ли база данных проекта
    if (!m_databaseController->isDatabaseOpen()) {
        return false;
    }
    
    // Сохраняем параметры проекта
    QList<ProjectParamTableData> params = m_projectParamTableModel->getData();
    bool success = true;
    
    for (const auto &param : params) {
        if (!m_databaseController->setProjectParam(param.name, param.value)) {
            success = false;
        }
    }
    
    return success;
}

bool MainController::loadProjectParamsFromDatabase() {
    // Проверяем, открыта ли база данных проекта
    if (!m_databaseController->isDatabaseOpen()) {
        return false;
    }
    
    QList<ProjectParamData> params = m_databaseController->getAllProjectParams();
    
    m_projectParamTableModel->clear();
    for (const auto &p : params) {
        ProjectParamTableData param;
        param.id = p.id;
        param.name = p.name;
        param.value = p.value;
        m_projectParamTableModel->addProjectParam(param);
    }
    
    return true;
}

bool MainController::loadPCBMaterialsFromDatabase() {
    // Проверяем, открыта ли база данных проекта
    if (!m_databaseController->isDatabaseOpen()) {
        return false;
    }
    
    // Загружаем материалы платы через модель
    m_pcbMaterialModel->loadMaterials();
    
    return true;
}

bool MainController::loadProjectSettingsFromDatabase() {
    // Проверяем, открыта ли база данных проекта
    if (!m_databaseController->isDatabaseOpen()) {
        return false;
    }
    
    // Загружаем настройки из БД
    QString currentVariant = m_databaseController->getProjectSetting("currentVariant", "No Variations");
    QStringList columnMappings = m_databaseController->getProjectSettingList("columnMappings", QStringList() << "Designator" << "<Пусто>" << "<Пусто>" << "<Пусто>");
    
    // Устанавливаем настройки в модель
    m_projectSettingsModel->setCurrentVariant(currentVariant);
    m_projectSettingsModel->setColumnMappings(columnMappings);
    
    // Загружаем настройки маппинга для разных типов документов
    QStringList documentTypes = {"Perechen", "SpecificationPCB", "Specification", "Vedomost"};
    for (const QString &docType : documentTypes) {
        QString key = QString("columnMappings_%1").arg(docType);
        QStringList mappings = m_databaseController->getProjectSettingList(key, QStringList());
        if (!mappings.isEmpty()) {
            // Устанавливаем маппинги в модель
            for (int i = 0; i < mappings.size(); ++i) {
                m_projectSettingsModel->setColumnMapping(docType, i, mappings[i]);
            }
        }
        
        // Загружаем размер шрифта для каждого типа документа
        QString fontSizeKey = QString("fontSize_%1").arg(docType);
        int fontSize = m_databaseController->getProjectSetting(fontSizeKey, "12").toInt();
        m_projectSettingsModel->setFontSize(docType, fontSize);
        
        // Загружаем поджим по ширине для каждого типа документа
        QString stretchKey = QString("fontStretch_%1").arg(docType);
        int stretch = m_databaseController->getProjectSetting(stretchKey, "100").toInt();
        m_projectSettingsModel->setFontStretch(docType, stretch);
    }
    
    // Загружаем настройки бланка заказа
    if (m_simpleListTableController) {
        QString nameField = m_databaseController->getProjectSetting("SimpleList_nameField", "Name");
        int techReservePercent = m_databaseController->getProjectSetting("SimpleList_techReservePercent", "10").toInt();
        int boardsCount = m_databaseController->getProjectSetting("SimpleList_boardsCount", "1").toInt();
        m_simpleListTableController->setNameField(nameField);
        m_simpleListTableController->setTechReservePercent(techReservePercent);
        m_simpleListTableController->setBoardsCount(boardsCount);
    }
    
    m_projectSettingsModel->setModified(false);
    
    // Устанавливаем текущий вариант в контроллере
    m_currentVariant = currentVariant;
    
    // Обновляем текущий вариант в модели компонентов
    if (m_componentTableModel) {
        m_componentTableModel->setCurrentVariant(currentVariant);
    }
    
    // Синхронизируем настройки колонок со всеми контроллерами
    syncColumnMappingsWithPerechenController();
    syncColumnMappingsWithSpecificationPCBController();
    syncColumnMappingsWithSpecificationController();
    syncColumnMappingsWithVedomostController();
    
    return true;
}

bool MainController::saveProjectSettingsToDatabase() {
    // Проверяем, открыта ли база данных проекта
    if (!m_databaseController->isDatabaseOpen()) {
        return false;
    }
    
    // Сохраняем настройки в БД
    bool success = true;
    success &= m_databaseController->setProjectSetting("currentVariant", m_projectSettingsModel->currentVariant());
    success &= m_databaseController->setProjectSettingList("columnMappings", m_projectSettingsModel->columnMappings());
    
    // Сохраняем настройки маппинга для разных типов документов
    QStringList documentTypes = {"Perechen", "SpecificationPCB", "Specification", "Vedomost"};
    for (const QString &docType : documentTypes) {
        QStringList mappings = m_projectSettingsModel->getColumnMappings(docType);
        if (!mappings.isEmpty()) {
            QString key = QString("columnMappings_%1").arg(docType);
            success &= m_databaseController->setProjectSettingList(key, mappings);
        }
        
        // Сохраняем размер шрифта для каждого типа документа
        QString fontSizeKey = QString("fontSize_%1").arg(docType);
        int fontSize = m_projectSettingsModel->getFontSize(docType);
        success &= m_databaseController->setProjectSetting(fontSizeKey, QString::number(fontSize));
        
        // Сохраняем поджим по ширине для каждого типа документа
        QString stretchKey = QString("fontStretch_%1").arg(docType);
        int stretch = m_projectSettingsModel->getFontStretch(docType);
        success &= m_databaseController->setProjectSetting(stretchKey, QString::number(stretch));
    }
    
    // Сохраняем настройки бланка заказа
    if (m_simpleListTableController) {
        success &= m_databaseController->setProjectSetting("SimpleList_nameField", m_simpleListTableController->getNameField());
        success &= m_databaseController->setProjectSetting("SimpleList_techReservePercent", QString::number(m_simpleListTableController->getTechReservePercent()));
        success &= m_databaseController->setProjectSetting("SimpleList_boardsCount", QString::number(m_simpleListTableController->getBoardsCount()));
    }
    
    // Сохраняем маппинг дезигнаторов в глобальную БД
    if (m_designatorMappingModel->isModified()) {
        m_designatorMappingModel->saveToDatabase();
    }
    
    if (success) {
        m_projectSettingsModel->setModified(false);
        
        // Синхронизируем настройки колонок со всеми контроллерами
        syncColumnMappingsWithPerechenController();
        syncColumnMappingsWithSpecificationPCBController();
        syncColumnMappingsWithSpecificationController();
        syncColumnMappingsWithVedomostController();
    }
    
    return success;
}

bool MainController::parseFile(const QString &filePath) {
    // Проверяем, открыта ли база данных проекта
    if (!m_databaseController->isDatabaseOpen()) {
        emit error("База данных проекта не открыта");
        return false;
    }
    
    // Определяем тип файла и вызываем соответствующий метод парсинга
    QFileInfo fileInfo(filePath);
    QString extension = fileInfo.suffix().toLower();
    bool success = false;
    
    if (extension == "prjpcb") {
        // Создаем временную модель для парсинга
        ComponentModel tempModel;
        success = m_altiumParser->parsePrjPcbFile(filePath, &tempModel);
        // Сохраняем имя PcbDoc файла в контроллере спецификации, если оно было найдено
        if (success && m_specificationPCBController) {
            QString pcbDocFileName = m_altiumParser->getPcbDocFileName();
            if (!pcbDocFileName.isEmpty()) {
                m_specificationPCBController->setPcbDocFileName(pcbDocFileName);
            }
        }
    } else if (extension == "schdoc") {
        ComponentModel tempModel;
        success = m_altiumParser->parseSchDoc(filePath, &tempModel);
    } else if (extension == "pcbdoc") {
        ComponentModel tempModel;
        success = m_altiumParser->parsePcbDoc(filePath, &tempModel);
        // Сохраняем имя PcbDoc файла в контроллере спецификации
        if (success && m_specificationPCBController) {
            m_specificationPCBController->setPcbDocFileName(filePath);
        }
    } else if (extension == "csv") {
        ComponentModel tempModel;
        success = m_altiumParser->parseCsvBom(filePath, &tempModel);
    } else if (extension == "xls" || extension == "xlsx") {
        ComponentModel tempModel;
        success = m_altiumParser->parseXlsBom(filePath, &tempModel);
    } else {
        emit error("Неподдерживаемый тип файла: " + extension);
        return false;
    }
    
    if (success) {
        loadComponentsFromDatabase();
        loadProjectParamsFromDatabase();
        loadPCBMaterialsFromDatabase();
        emit parsingFinished(true);
    } else {
        emit error("Ошибка парсинга: " + m_altiumParser->lastError());
        emit parsingFinished(false);
    }
    
    return success;
}

bool MainController::parseFileAsync(const QString &filePath)
{
    // Проверяем, открыта ли база данных проекта
    if (!m_databaseController->isDatabaseOpen()) {
        emit error("База данных проекта не открыта");
        return false;
    }
    
    // Определяем тип файла и вызываем соответствующий метод парсинга
    QFileInfo fileInfo(filePath);
    QString extension = fileInfo.suffix().toLower();
    
    if (extension == "prjpcb") {
        // Создаем временную модель для парсинга
        ComponentModel tempModel;
        return m_altiumParser->parseFileAsync(filePath, &tempModel);
    } else {
        emit error("Асинхронный парсинг поддерживается только для .PrjPcb файлов");
        return false;
    }
}

bool MainController::isParsingAsync() const
{
    return m_altiumParser->isParsingAsync();
}

void MainController::cancelParsing()
{
    m_altiumParser->cancelParsing();
}

bool MainController::exportPerechen()
{
    if(!m_pdfController)
        return false;

    // Этот метод устарел, используйте exportPerechenToPdf
    return false;
}

bool MainController::exportPerechenToPdf(const QString &filePath)
{
    if (!m_pdfController) {
        return false;
    }

    // Передаем MainController в PDFController
    return m_pdfController->exportPerechenToPdf(filePath, this);
}

bool MainController::exportSpecificationPcbToPdf(const QString &filePath)
{
    if (!m_pdfController) {
        return false;
    }

    // Передаем MainController в PDFController
    return m_pdfController->exportSpecificationPcbToPdf(filePath, this);
}

void MainController::syncColumnMappingsWithPerechenController()
{
    if (m_perechenTableController && m_projectSettingsModel) {
        // Используем документ-специфичные настройки для Perechen
        QStringList columnMappings = m_projectSettingsModel->getColumnMappings("Perechen");
        
        if (!columnMappings.isEmpty()) {
            m_perechenTableController->setColumnMappings(columnMappings);
            
            // Дополнительно проверяем, что настройки передались в модель
            if (m_perechenTableModel) {
                QStringList modelMappings = m_perechenTableModel->columnMappings();
                
                if (modelMappings != columnMappings) {
                    m_perechenTableModel->setColumnMappings(columnMappings);
                }
            }
        }
    }
}

void MainController::syncColumnMappingsWithSpecificationPCBController()
{
    if (m_specificationPCBController && m_projectSettingsModel) {
        // Используем документ-специфичные настройки для SpecificationPCB
        QStringList columnMappings = m_projectSettingsModel->getColumnMappings("SpecificationPCB");
        m_specificationPCBController->setColumnMappings(columnMappings);
    }
}

void MainController::syncColumnMappingsWithSpecificationController()
{
    if (m_specificationController && m_projectSettingsModel) {
        // Используем документ-специфичные настройки для Specification
        QStringList columnMappings = m_projectSettingsModel->getColumnMappings("Specification");
        m_specificationController->setColumnMappings(columnMappings);
    }
}

void MainController::syncColumnMappingsWithVedomostController()
{
    if (m_vedomostController && m_projectSettingsModel) {
        // Используем документ-специфичные настройки для Vedomost
        QStringList columnMappings = m_projectSettingsModel->getColumnMappings("Vedomost");
        m_vedomostController->setColumnMappings(columnMappings);
    }
}

bool MainController::saveTitleInscriptionsToDatabase(const QMap<int, QString> &inscriptions)
{
    // Проверяем, открыта ли база данных проекта
    if (!m_databaseController->isDatabaseOpen()) {
        return false;
    }
    
    // Получаем имя текущего проекта из пути к файлу БД
    QString projectName = QFileInfo(m_databaseController->getDatabasePath()).baseName();
    
    bool success = m_databaseController->saveTitleInscriptions(inscriptions, projectName);
    
    return success;
}

bool MainController::loadTitleInscriptionsFromDatabase(QMap<int, QString> &inscriptions)
{
    // Проверяем, открыта ли база данных проекта
    if (!m_databaseController->isDatabaseOpen()) {
        return false;
    }
    
    // Получаем имя текущего проекта из пути к файлу БД
    QString projectName = QFileInfo(m_databaseController->getDatabasePath()).baseName();
    
    bool success = m_databaseController->loadTitleInscriptions(inscriptions, projectName);
    
    return success;
}

bool MainController::savePerechenTableToDatabase(const QByteArray &tableData, const QString &projectName)
{
    // Проверяем, открыта ли база данных проекта
    if (!m_databaseController->isDatabaseOpen()) {
        return false;
    }
    
    // Если имя проекта не указано, получаем его из пути к файлу БД
    QString actualProjectName = projectName;
    if (actualProjectName.isEmpty()) {
        actualProjectName = QFileInfo(m_databaseController->getDatabasePath()).baseName();
    }
    
    bool success = m_databaseController->savePerechenTable(tableData, actualProjectName);
    
    return success;
}

QByteArray MainController::loadPerechenTableFromDatabase(const QString &projectName)
{
    // Проверяем, открыта ли база данных проекта
    if (!m_databaseController->isDatabaseOpen()) {
        return QByteArray();
    }
    
    // Если имя проекта не указано, получаем его из пути к файлу БД
    QString actualProjectName = projectName;
    if (actualProjectName.isEmpty()) {
        actualProjectName = QFileInfo(m_databaseController->getDatabasePath()).baseName();
    }
    
    QByteArray tableData = m_databaseController->loadPerechenTable(actualProjectName);
    
    return tableData;
}

QString MainController::getPerechenTableInfo(const QString &projectName)
{
    // Проверяем, открыта ли база данных проекта
    if (!m_databaseController->isDatabaseOpen()) {
        return QString();
    }
    
    return m_databaseController->getPerechenTableInfo(projectName);
}

bool MainController::saveSpecificationPCBTableToDatabase(const QByteArray &tableData, const QString &projectName)
{
    // Проверяем, открыта ли база данных проекта
    if (!m_databaseController->isDatabaseOpen()) {
        return false;
    }
    
    // Если имя проекта не указано, получаем его из пути к файлу БД
    QString actualProjectName = projectName;
    if (actualProjectName.isEmpty()) {
        actualProjectName = QFileInfo(m_databaseController->getDatabasePath()).baseName();
    }
    
    bool success = m_databaseController->saveSpecificationPCBTable(tableData, actualProjectName);
    
    return success;
}

QByteArray MainController::loadSpecificationPCBTableFromDatabase(const QString &projectName)
{
    // Проверяем, открыта ли база данных проекта
    if (!m_databaseController->isDatabaseOpen()) {
        return QByteArray();
    }
    
    // Если имя проекта не указано, получаем его из пути к файлу БД
    QString actualProjectName = projectName;
    if (actualProjectName.isEmpty()) {
        actualProjectName = QFileInfo(m_databaseController->getDatabasePath()).baseName();
    }
    
    QByteArray tableData = m_databaseController->loadSpecificationPCBTable(actualProjectName);
    
    return tableData;
}

QString MainController::getSpecificationPCBTableInfo(const QString &projectName)
{
    // Проверяем, открыта ли база данных проекта
    if (!m_databaseController->isDatabaseOpen()) {
        return QString();
    }
    
    return m_databaseController->getSpecificationPCBTableInfo(projectName);
}

// Методы для работы со спецификацией материалов
bool MainController::saveSpecificationTableToDatabase(const QByteArray &tableData, const QString &projectName)
{
    // Проверяем, открыта ли база данных проекта
    if (!m_databaseController->isDatabaseOpen()) {
        return false;
    }
    
    // Если имя проекта не указано, получаем его из пути к файлу БД
    QString actualProjectName = projectName;
    if (actualProjectName.isEmpty()) {
        actualProjectName = QFileInfo(m_databaseController->getDatabasePath()).baseName();
    }
    
    bool success = m_databaseController->saveSpecificationTable(tableData, actualProjectName);
    
    return success;
}

QByteArray MainController::loadSpecificationTableFromDatabase(const QString &projectName)
{
    // Проверяем, открыта ли база данных проекта
    if (!m_databaseController->isDatabaseOpen()) {
        return QByteArray();
    }
    
    // Если имя проекта не указано, получаем его из пути к файлу БД
    QString actualProjectName = projectName;
    if (actualProjectName.isEmpty()) {
        actualProjectName = QFileInfo(m_databaseController->getDatabasePath()).baseName();
    }
    
    QByteArray tableData = m_databaseController->loadSpecificationTable(actualProjectName);
    
    return tableData;
}

QString MainController::getSpecificationTableInfo(const QString &projectName)
{
    // Проверяем, открыта ли база данных проекта
    if (!m_databaseController->isDatabaseOpen()) {
        return QString();
    }
    
    return m_databaseController->getSpecificationTableInfo(projectName);
}

// Методы для работы с ведомостью покупных изделий
bool MainController::saveVedomostTableToDatabase(const QByteArray &tableData, const QString &projectName)
{
    // Проверяем, открыта ли база данных проекта
    if (!m_databaseController->isDatabaseOpen()) {
        return false;
    }
    
    // Если имя проекта не указано, получаем его из пути к файлу БД
    QString actualProjectName = projectName;
    if (actualProjectName.isEmpty()) {
        actualProjectName = QFileInfo(m_databaseController->getDatabasePath()).baseName();
    }
    
    bool success = m_databaseController->saveVedomostTable(tableData, actualProjectName);
    
    return success;
}

QByteArray MainController::loadVedomostTableFromDatabase(const QString &projectName)
{
    // Проверяем, открыта ли база данных проекта
    if (!m_databaseController->isDatabaseOpen()) {
        return QByteArray();
    }
    
    // Если имя проекта не указано, получаем его из пути к файлу БД
    QString actualProjectName = projectName;
    if (actualProjectName.isEmpty()) {
        actualProjectName = QFileInfo(m_databaseController->getDatabasePath()).baseName();
    }
    
    QByteArray tableData = m_databaseController->loadVedomostTable(actualProjectName);
    
    return tableData;
}

QString MainController::getVedomostTableInfo(const QString &projectName)
{
    // Проверяем, открыта ли база данных проекта
    if (!m_databaseController->isDatabaseOpen()) {
        return QString();
    }
    
    return m_databaseController->getVedomostTableInfo(projectName);
}

bool MainController::exportSpecificationToPdf(const QString &filePath)
{
    if (!m_pdfController) {
        return false;
    }
    
    return m_pdfController->exportSpecificationToPdf(filePath, this);
}

bool MainController::exportVedomostToPdf(const QString &filePath)
{
    if (!m_pdfController) {
        return false;
    }
    
    return m_pdfController->exportVedomostToPdf(filePath, this);
}

bool MainController::exportPerechenToCsv(const QString &filePath)
{
    if (!m_csvExporter || !m_perechenTableModel) {
        return false;
    }
    
    return m_csvExporter->exportPerechen(filePath, m_perechenTableModel);
}

bool MainController::exportSpecificationPcbToCsv(const QString &filePath)
{
    if (!m_csvExporter || !m_specificationPCBTableModel) {
        return false;
    }
    
    return m_csvExporter->exportSpecificationPCB(filePath, m_specificationPCBTableModel);
}

bool MainController::exportSpecificationToCsv(const QString &filePath)
{
    if (!m_csvExporter || !m_specificationTableModel) {
        return false;
    }
    
    return m_csvExporter->exportSpecification(filePath, m_specificationTableModel);
}

bool MainController::exportVedomostToCsv(const QString &filePath)
{
    if (!m_csvExporter || !m_vedomostTableModel) {
        return false;
    }
    
    return m_csvExporter->exportVedomost(filePath, m_vedomostTableModel);
}

bool MainController::exportSimpleListToCsv(const QString &filePath)
{
    if (!m_csvExporter || !m_simpleListTableModel) {
        return false;
    }
    
    return m_csvExporter->exportSimpleList(filePath, m_simpleListTableModel);
}

bool MainController::saveSimpleListTableToDatabase(const QByteArray &tableData, const QString &projectName)
{
    // Проверяем, открыта ли база данных проекта
    if (!m_databaseController->isDatabaseOpen()) {
        return false;
    }
    
    // Если имя проекта не указано, получаем его из пути к файлу БД
    QString actualProjectName = projectName;
    if (actualProjectName.isEmpty()) {
        actualProjectName = QFileInfo(m_databaseController->getDatabasePath()).baseName();
    }
    
    bool success = m_databaseController->saveSimpleListTable(tableData, actualProjectName);
    
    return success;
}

QByteArray MainController::loadSimpleListTableFromDatabase(const QString &projectName)
{
    // Проверяем, открыта ли база данных проекта
    if (!m_databaseController->isDatabaseOpen()) {
        return QByteArray();
    }
    
    // Если имя проекта не указано, получаем его из пути к файлу БД
    QString actualProjectName = projectName;
    if (actualProjectName.isEmpty()) {
        actualProjectName = QFileInfo(m_databaseController->getDatabasePath()).baseName();
    }
    
    QByteArray tableData = m_databaseController->loadSimpleListTable(actualProjectName);
    
    return tableData;
}

PDFController* MainController::pdfController() const
{
    return m_pdfController;
}
