#ifndef DATABASECONTROLLER_H
#define DATABASECONTROLLER_H

#include <QObject>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>
#include <QMap>
#include <QList>
#include "altiumparser.h"

struct ComponentData {
    int id;
    QString designator;
    QMap<QString, QString> baseProperties;
    QMap<QString, QMap<QString, QString>> variantProperties;
    QMap<QString, bool> variantFitted;
};

struct VariantData {
    int id;
    QString name;
};

struct ProjectParamData {
    int id;
    QString name;
    QString value;
};

struct DesignatorMappingData {
    int id;
    QString designator;
    QString singularName;
    QString pluralName;
    bool isCustom;
};

struct PCBData {
    int id;
    int layerCount;
    QList<DielProperty> dielMaterials;
};

class DataBaseController : public QObject
{
    Q_OBJECT
public:
    explicit DataBaseController(QObject *parent = nullptr);
    ~DataBaseController();

    // Инициализация БД
    bool initializeDatabase(const QString &dbPath = "components.db", const QString &connectionName = QString());
    bool createTables();
    
    // Работа с вариантами
    int addVariant(const QString &name);
    bool removeVariant(int variantId);
    QList<VariantData> getAllVariants();
    int getVariantId(const QString &name);
    
    // Работа с компонентами
    int addComponent(const QString &designator);
    bool removeComponent(int componentId);
    bool updateComponentDesignator(int componentId, const QString &designator);
    QList<ComponentData> getAllComponents();
    ComponentData getComponent(int componentId);
    ComponentData getComponent(const QString &designator);
    bool saveComponents(const QList<ComponentData> &components);
    
    // Пакетная вставка компонентов (оптимизация)
    bool beginTransaction();
    bool commitTransaction();
    bool rollbackTransaction();
    bool addComponentBatch(const QString &designator, const QMap<QString, QString> &properties);
    bool addComponentPropertiesBatch(int componentId, const QMap<QString, QString> &properties);
    bool addComponentVariantsBatch(int componentId, const QStringList &variantNames);
    
    // Работа со свойствами компонентов
    bool setComponentProperty(int componentId, const QString &propertyName, const QString &propertyValue);
    bool removeComponentProperty(int componentId, const QString &propertyName);
    QMap<QString, QString> getComponentProperties(int componentId);
    
    // Работа с вариантами компонентов
    bool setComponentVariantFitted(int componentId, int variantId, bool fitted);
    bool setVariantProperty(int componentId, int variantId, const QString &propertyName, const QString &propertyValue);
    bool removeVariantProperty(int componentId, int variantId, const QString &propertyName);
    
    // Работа с параметрами проекта
    int addProjectParam(const QString &name, const QString &value);
    bool updateProjectParam(int paramId, const QString &name, const QString &value);
    bool removeProjectParam(int paramId);
    QList<ProjectParamData> getAllProjectParams();
    ProjectParamData getProjectParam(int paramId);
    bool setProjectParam(const QString &name, const QString &value);
    
    // Работа с данными PCB
    int addPCBData(int layerCount);
    bool updatePCBLayerCount(int pcbId, int layerCount);
    bool addDielMaterial(int pcbId, const QString &name, const QString &value, double height, int dielType = 0, int layerNumber = 0);
    bool updateDielMaterial(int pcbId, const QString &name, const QString &value, double height, int dielType = 0, int layerNumber = 0);
    bool removeDielMaterial(int pcbId, int layerNumber);
    PCBData getPCBData(int pcbId);
    PCBData getPCBData(); // Получить последние данные PCB
    QList<DielProperty> getDielMaterials(int pcbId);
    QList<DielProperty> getDielMaterials(); // Получить все материалы
    bool savePCBData(const PCBData &pcbData);
    bool clearPCBData();
    
    // Работа с настройками проекта
    bool setProjectSetting(const QString &key, const QString &value);
    QString getProjectSetting(const QString &key, const QString &defaultValue = QString());
    bool setProjectSettingList(const QString &key, const QStringList &value);
    QStringList getProjectSettingList(const QString &key, const QStringList &defaultValue = QStringList());
    
    // Работа с маппингами дезигнаторов
    int addDesignatorMapping(const QString &designator, const QString &singularName, 
                           const QString &pluralName, bool isCustom = false);
    bool updateDesignatorMapping(int mappingId, const QString &designator, 
                               const QString &singularName, const QString &pluralName, bool isCustom);
    bool removeDesignatorMapping(int mappingId);
    bool removeDesignatorMapping(const QString &designator);
    QList<DesignatorMappingData> getAllDesignatorMappings();
    DesignatorMappingData getDesignatorMapping(int mappingId);
    DesignatorMappingData getDesignatorMapping(const QString &designator);
    bool saveDesignatorMappings(const QList<DesignatorMappingData> &mappings);
    bool clearCustomDesignatorMappings();
    bool resetDesignatorMappingsToDefaults();
    
    // Работа с надписями титульного листа
    bool saveTitleInscriptions(const QMap<int, QString> &inscriptions, const QString &projectName = QString());
    bool loadTitleInscriptions(QMap<int, QString> &inscriptions, const QString &projectName = QString());
    bool deleteTitleInscriptions(const QString &projectName = QString());
    QStringList getAvailableTitleInscriptionProjects();
    
    // Работа с перечнем элементов
    bool savePerechenTable(const QByteArray &tableData, const QString &projectName = QString());
    QByteArray loadPerechenTable(const QString &projectName = QString());
    bool deletePerechenTable(const QString &projectName = QString());
    QStringList getAvailablePerechenProjects();
    
    // Метод для получения информации о структуре перечня в БД
    QString getPerechenTableInfo(const QString &projectName = QString());
    
    // Работа со спецификацией платы
    bool saveSpecificationPCBTable(const QByteArray &tableData, const QString &projectName = QString());
    QByteArray loadSpecificationPCBTable(const QString &projectName = QString());
    bool deleteSpecificationPCBTable(const QString &projectName = QString());
    QStringList getAvailableSpecificationPCBProjects();
    
    // Метод для получения информации о структуре спецификации платы в БД
    QString getSpecificationPCBTableInfo(const QString &projectName = QString());
    
    // Работа со спецификацией материалов
    bool saveSpecificationTable(const QByteArray &tableData, const QString &projectName = QString());
    QByteArray loadSpecificationTable(const QString &projectName = QString());
    bool deleteSpecificationTable(const QString &projectName = QString());
    QStringList getAvailableSpecificationProjects();
    
    // Метод для получения информации о структуре спецификации материалов в БД
    QString getSpecificationTableInfo(const QString &projectName = QString());
    
    // Работа с ведомостью покупных изделий
    bool saveVedomostTable(const QByteArray &tableData, const QString &projectName = QString());
    QByteArray loadVedomostTable(const QString &projectName = QString());
    bool deleteVedomostTable(const QString &projectName = QString());
    QStringList getAvailableVedomostProjects();
    
    // Метод для получения информации о структуре ведомости покупных изделий в БД
    QString getVedomostTableInfo(const QString &projectName = QString());
    
    // Работа с бланком заказа
    bool saveSimpleListTable(const QByteArray &tableData, const QString &projectName = QString());
    QByteArray loadSimpleListTable(const QString &projectName = QString());
    
    // Получение данных для отображения
    QList<ComponentData> getComponentsForVariant(int variantId);
    QList<ComponentData> getComponentsForVariant(const QString &variantName);
    
    // Получение всех уникальных свойств
    QStringList getAllPropertyNames();
    
    // Очистка БД
    void clearAllData();
    
    // Проверка состояния БД
    bool isDatabaseOpen() const;
    QString lastError() const;
    QString getDatabasePath() const;

signals:
    void databaseError(const QString &error);
    void dataChanged();

private:
    QSqlDatabase m_database;
    QString m_lastError;
    static int s_connectionCounter;
    
    // Вспомогательные методы
    bool executeQuery(const QString &query, const QVariantMap &params = QVariantMap());
    QSqlQuery prepareQuery(const QString &query);
    void setLastError(const QString &error);
    
    // Миграции базы данных
    void migrateAddCellStretchesColumn();
};

#endif // DATABASECONTROLLER_H
