#ifndef DOCUMENTPROCESSOR_H
#define DOCUMENTPROCESSOR_H

#include <QObject>
#include <QTableView>
#include <QPushButton>
#include <QGroupBox>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QMenu>
#include <QAction>
#include <QClipboard>
#include <QMimeData>
#include "../model/componenttablemodel.h"
#include "../model/projectparamtablemodel.h"
#include "../model/perechentablemodel.h"
#include "../controller/perechentablecontroller.h"
#include "../model/specificationpcbtablemodel.h"
#include "../model/specificationtablemodel.h"
#include "../model/vedomosttablemodel.h"
#include "../controller/specificationpcbcontroller.h"
#include "../controller/specificationcontroller.h"
#include "../controller/vedomostcontroller.h"
#include "../model/simplelisttablemodel.h"
#include "../controller/simplelisttablecontroller.h"
#include "documentsettingsdialog.h"
#include "../model/titleinscriptionsmodel.h"

class MainController;

// Абстрактный класс для обработки документов
class DocumentProcessor : public QObject
{
    Q_OBJECT
public:
    explicit DocumentProcessor(QObject *parent = nullptr);
    virtual ~DocumentProcessor() = default;

    // Виртуальные методы для обработки данных
    virtual void processComponents(const QList<ComponentModel*> &components) = 0;
    virtual void processProjectParams(const QMap<QString, QString> &params) = 0;
    virtual QTableView* createTableView() = 0;

protected:
    QList<ComponentModel*> m_processedComponents;
    QMap<QString, QString> m_processedParams;
};

// Конкретные процессоры для каждого типа документа
class PerechenProcessor : public DocumentProcessor
{
    Q_OBJECT

public:
    explicit PerechenProcessor(QObject *parent = nullptr);
    ~PerechenProcessor();

    void processComponents(const QList<ComponentModel*> &components) override;
    void processProjectParams(const QMap<QString, QString> &params) override;
    QTableView* createTableView() override;

    // Методы для работы с настройками колонок
    void setColumnMappings(const QStringList &mappings);
    QStringList getColumnMappings() const;
    QStringList getAvailableProperties() const;
    
    // Метод для обновления таблицы по кнопке
    void updateTable();
    
    // Метод для получения контроллера
    PerechenTableController* getController() const { return m_controller; }
    
    // Метод для установки контроллера (для интеграции с MainController)
    void setController(PerechenTableController *controller);
    
    // Метод для установки модели (для интеграции с MainController)
    void setModel(PerechenTableModel *model);

private:
    PerechenTableController *m_controller;
};

class SpecificationPCBProcessor : public DocumentProcessor
{
    Q_OBJECT

public:
    explicit SpecificationPCBProcessor(QObject *parent = nullptr);
    ~SpecificationPCBProcessor();

    void processComponents(const QList<ComponentModel*> &components) override;
    void processProjectParams(const QMap<QString, QString> &params) override;
    QTableView* createTableView() override;

    // Методы для работы с настройками колонок
    void setColumnMappings(const QStringList &mappings);
    QStringList getColumnMappings() const;
    QStringList getAvailableProperties() const;
    
    // Метод для обновления таблицы по кнопке
    void updateTable();
    
    // Метод для получения контроллера
    SpecificationPCBController* getController() const { return m_controller; }
    
    // Метод для установки контроллера (для интеграции с MainController)
    void setController(SpecificationPCBController *controller);
    
    // Метод для установки модели (для интеграции с MainController)
    void setModel(SpecificationPCBTableModel *model);

private:
    SpecificationPCBController *m_controller;
};

class SpecificationProcessor : public DocumentProcessor
{
    Q_OBJECT
public:
    explicit SpecificationProcessor(QObject *parent = nullptr);
    
    void processComponents(const QList<ComponentModel*> &components) override;
    void processProjectParams(const QMap<QString, QString> &params) override;
    QTableView* createTableView() override;

    // Методы для работы с настройками колонок
    void setColumnMappings(const QStringList &mappings);
    QStringList getColumnMappings() const;
    QStringList getAvailableProperties() const;
    
    // Метод для обновления таблицы по кнопке
    void updateTable();
    
    // Метод для получения контроллера
    SpecificationController* getController() const { return m_controller; }
    
    // Метод для установки контроллера (для интеграции с MainController)
    void setController(SpecificationController *controller);
    
    // Метод для установки модели (для интеграции с MainController)
    void setModel(SpecificationTableModel *model);

private:
    SpecificationController *m_controller;
};



class VedomostProcessor : public DocumentProcessor
{
    Q_OBJECT
public:
    explicit VedomostProcessor(QObject *parent = nullptr);
    ~VedomostProcessor();
    
    void processComponents(const QList<ComponentModel*> &components) override;
    void processProjectParams(const QMap<QString, QString> &params) override;
    QTableView* createTableView() override;

    // Методы для работы с настройками колонок
    void setColumnMappings(const QStringList &mappings);
    QStringList getColumnMappings() const;
    QStringList getAvailableProperties() const;
    
    // Метод для обновления таблицы по кнопке
    void updateTable();
    
    // Метод для получения контроллера
    VedomostController* getController() const { return m_controller; }
    
    // Метод для установки контроллера (для интеграции с MainController)
    void setController(VedomostController *controller);
    
    // Метод для установки модели (для интеграции с MainController)
    void setModel(VedomostTableModel *model);

private:
    VedomostController *m_controller;
};

class SimpleListProcessor : public DocumentProcessor
{
    Q_OBJECT
public:
    explicit SimpleListProcessor(QObject *parent = nullptr);
    ~SimpleListProcessor();
    
    void processComponents(const QList<ComponentModel*> &components) override;
    void processProjectParams(const QMap<QString, QString> &params) override;
    QTableView* createTableView() override;
    
    // Метод для обновления таблицы по кнопке
    void updateTable();
    
    // Метод для получения контроллера
    SimpleListTableController* getController() const { return m_controller; }
    
    // Метод для установки контроллера (для интеграции с MainController)
    void setController(SimpleListTableController *controller);
    
    // Метод для установки модели (для интеграции с MainController)
    void setModel(SimpleListTableModel *model);

private:
    SimpleListTableController *m_controller;
};

// Универсальный виджет для работы с документами
class DocumentEditWidget : public QWidget
{
    Q_OBJECT
public:
    explicit DocumentEditWidget(DocumentProcessor *processor, QWidget *parent = nullptr);
    explicit DocumentEditWidget(DocumentProcessor *processor, MainController *controller, QWidget *parent = nullptr);
    
    void setData(ComponentTableModel *componentModel, ProjectParamTableModel *projectParamModel);
    void updateView();
    
    // Методы для работы с надписями титульного листа
    TitleInscriptionsModel* getTitleInscriptionsModel() const;
    
    // Методы для работы с таблицами документов
    PerechenTableModel* getPerechenTableModel() const;
    SpecificationPCBTableModel* getSpecificationPCBTableModel() const;
    SpecificationTableModel* getSpecificationTableModel() const;
    VedomostTableModel* getVedomostTableModel() const;

private slots:
    void onOpenColumnSettings();
    void onGenerateTable();
    void onRecalculateTable();
    
    // Новые слоты для управления строками
    void onAddRow();
    void onInsertRow(); // Слот для вставки строки в середину
    void onRemoveRow();
    
    // Слот для обновления состояния кнопок
    void onSelectionChanged();
    
    // Слот для контекстного меню
    void onContextMenuRequested(const QPoint &pos);
    
    // Слоты для контекстного меню
    void onContextMenuAddRow();
    void onContextMenuRemoveRow();
    void onContextMenuRemoveSelectedRows(); // Удаление нескольких выделенных строк
    void onContextMenuMergeRows(); // Объединение нескольких выделенных строк (все столбцы)
    void onContextMenuMergeColumn(); // Объединение только определенного столбца
    void onContextMenuCellSettings();
    
    // Слоты для копирования/вставки/вырезания
    void onContextMenuCopyRows(); // Копирование строк
    void onContextMenuCutRows(); // Вырезание строк
    void onContextMenuPasteRows(); // Вставка строк
    void onContextMenuCopyCells(); // Копирование ячеек
    void onContextMenuCutCells(); // Вырезание ячеек
    void onContextMenuPasteCells(); // Вставка ячеек

private:
    void setUp();
    void setWidgets();
    void setUpLayout();
    void setUpConnections();
    void setupSelectionConnection(); // Новый метод для установки соединения selectionChanged
    
    // Вспомогательные методы
    int getCurrentSelectedRow() const;
    void applyColumnStretching(); // Метод для применения настроек растягивания столбцов
    
    // Вспомогательные методы для копирования/вставки
    void copyRowsToClipboard(const QModelIndexList &rows);
    void pasteRowsFromClipboard(int insertPosition);
    void cutRows(int insertPosition); // Вырезает строки (копирует и удаляет)
    void copyCellsToClipboard(const QItemSelection &selection);
    void pasteCellsFromClipboard(const QModelIndex &topLeft);
    void cutCells(const QModelIndex &topLeft); // Вырезает ячейки (копирует и очищает)

    DocumentProcessor *m_processor;
    ComponentTableModel *m_componentModel;
    ProjectParamTableModel *m_projectParamModel;
    MainController *m_controller;
    TitleInscriptionsModel *m_titleInscriptionsModel;
    
    QPushButton* m_openSettingsButton;
    QPushButton* m_generateTableButton;
    QPushButton* m_recalculateTableButton;
    
    // Новые кнопки для управления строками
    QPushButton* m_addRowButton;
    QPushButton* m_insertRowButton; // Кнопка для вставки строки в середину
    QPushButton* m_removeRowButton;
    
    QTableView* m_tableView;
    QGroupBox* m_settingsGroupBox;
};

#endif // DOCUMENTPROCESSOR_H 