#ifndef DBTREEVIEWMANAGER_H
#define DBTREEVIEWMANAGER_H

#include <QWidget>
#include <QTreeView>
#include <QJsonObject>
#include <QStandardItemModel>
#include <QCheckBox>
#include <QJsonArray>
#include <QFile>
#include <QLineEdit>
#include <QComboBox>
#include <QRadioButton>
#include <QButtonGroup>
#include <QStyleFactory>
#include <QEvent>
#include <QStringList>
#include <QSettings>
#include <QSet>
#include <QVariant>
#include <QMenu>
#include <QAction>
#include <QTimeEdit>
#include <QCursor>
#include <QScrollArea>
#include <QToolButton>
#include <QtSql>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QMessageBox>
#include <QPainter>
#include <QTimer>
#include <QFileInfo>
#include <QLabel>
#include <QHBoxLayout>
#include <QPushButton>
#include <QDebug>
#include <QVBoxLayout>
#include <QStandardItem>
#include <QMap>
#include <QJsonDocument>

class OriginalWnd; ///< 前向声明

/**
 * @class DbTreeViewManager
 * @brief 管理树状视图、导航栏、以及与数据库交互的相关逻辑。
 *
 * 该类负责从数据库加载目录树 ，并根据用户权限和配置 ID 显示相应的字段与控件。
 * 同时还支持切换 Home 界面或其他配置界面、隐藏/显示按钮与分隔线等功能。
 */
class DbTreeViewManager : public QWidget
{
    Q_OBJECT

public:

    /**
     * @brief 构造函数
     * @param originalWnd  指向 OriginalWnd 对象的指针
     * @param widget2      另一个父级或容器部件，用于添加子控件
     * @param parent       父窗口指针，可为空
     */
    explicit DbTreeViewManager(OriginalWnd* originalWnd,
                               QWidget* widget2, QWidget* parent = nullptr);

    /**
     * @brief 析构函数，清理资源
     */
    ~DbTreeViewManager();

    /**
     * @brief 初始化目录树，从数据库加载数据
     * @param configId       配置ID，对应数据库中的 Configurations 表
     * @param userPrivilege  当前用户的权限等级
     */
    void initializeTree(int configId, const int &userPrivilege);

    /**
     * @brief 清理所有分隔线（内部调用，用于清除旧有的一级目录分隔线等）
     */
    void clearAllSeparators();

    /**
     * @brief 收集所有第三层目录的 QStandardItem
     * @return 包含第三层目录项的列表
     */
    QList<QStandardItem*> collectAllThirdLevelItems();

    /**
     * @brief 保存所有当前已展开的路径
     *   对应 expandedPaths 中的路径保存到持久化存储（如 QSettings）
     */
    void saveExpandedPaths();

    /**
     * @brief 加载已展开的路径
     *   从持久化存储（如 QSettings）中读取展开路径并恢复
     */
    void loadExpandedPaths();

    /**
     * @brief 存储已展开路径的容器
     *   格式通常为 "Root/Child/Child" 的字符串
     */
    QSet<QString> expandedPaths;

signals:


private slots:

    /**
     * @brief 当树中某个项目被点击时触发
     * @param index 被点击的 QModelIndex
     */
    void onTreeViewClicked(const QModelIndex &index);

    /**
     * @brief 当树中某个项目被点击时触发,专门给up和down按钮使用
     * @param index 被点击的 QModelIndex
     */
    void onTreeViewClicked_updown(const QModelIndex &index);
    /**
     * @brief “返回”按钮点击槽函数
     *   用于在第三层目录与上层目录间进行返回逻辑
     */
    void onButtonBackClicked();

    /**
     * @brief “上”按钮点击槽函数
     *   用于在所有第三层目录间向上移动
     */
    void onButtonUpClicked();

    /**
     * @brief “下”按钮点击槽函数
     *   用于在所有第三层目录间向下移动
     */
    void onButtonDownClicked();

    /**
     * @brief “左”按钮点击槽函数
     *   用于目录层级的向左逻辑（如果有需要）
     */
    void onButtonLeftClicked();

    /**
     * @brief “右”按钮点击槽函数
     *   用于目录层级的向右逻辑（如果有需要）
     */
    void onButtonRightClicked();

    /**
     * @brief 当树状模型中某个 QStandardItem 的复选框状态发生变化时触发
     * @param item 发生变化的 QStandardItem
     */
    void onItemChanged(QStandardItem *item);

private:

    /**
     * @brief 指向 OriginalWnd 对象的指针，用于访问或联动其它窗口功能
     */
    OriginalWnd* m_originalWnd;

    /**
     * @brief widget2 外部传入的父级/容器，用于承载子控件
     */
    QWidget *widget2;

    /**
     * @brief 树视图控件
     */
    QTreeView *treeViewDown;

    /**
     * @brief 导航栏 QWidget，用于显示路径信息
     */
    QWidget *navigationWidget;

    /**
     * @brief 树状模型，用于存放目录层级
     */
    QStandardItemModel *model;

    /**
     * @brief 用于存储第三层字段展示窗口的指针（单实例）
     */
    QWidget* m_thirdLevelFieldWnd = nullptr;

    /**
     * @brief 上部的几个操作按钮（例如 “返回”、“上”、“下”、“左”、“右”）
     */
    QPushButton *ButtonBack;       ///< 返回按钮
    QPushButton *buttonUp;        ///< 上按钮
    QPushButton *buttonDown;      ///< 下按钮
    QPushButton *buttonLeft;      ///< 左按钮
    QPushButton *buttonRight;     ///< 右按钮




    //  定义一个结构来记录当前所处页面的信息
    struct PageState {
        QStringList path;    // 记录目录的文本路径
        bool isThirdLevel;   // 是否是第三层目录
        int  directoryId;    // 第三层目录ID
    };


    //  存储“后退栈”和“前进栈”，
    QList<PageState> m_backStack;
    QList<PageState> m_forwardStack;

    //  每次切换控制屏幕时，清空历史
    void clearHistory();

    //  用于把当前选中的目录或第三层界面封装成 PageState
    PageState getCurrentPageState();

    // 加载指定 PageState，相当于“跳转”到该状态
    void loadPageState(const PageState &st, bool isByHistoryNav = false);



    /**
     * @brief restoring 标记是否在恢复阶段
     */
    bool restoring;

    /**
     * @brief 存储“一级目录”和相应分隔线的映射，用于更新和控制分隔线位置、可见性等
     */
    QMap<QStandardItem*, QFrame*> firstLevelSeparators;

    /**
     * @brief 标记是否阻止触发 onItemChanged 等复选框变更响应
     */
    bool m_blockItemChanged;

    /**
     * @brief  用于存储第三层界面生成的控件列表，方便统一管理和销毁
     */
    QList<QWidget*> m_fieldWidgets;


    /**
     * @brief  当前正在使用的配置ID
     */
    int m_currentConfigId = -1;

    /**
     * @brief  特定分隔线，Home 界面时隐藏，其他界面时显示
     */
    QFrame* lineFrame1;

    /**
     * @brief 从数据库加载指定 configId 下的目录记录，并构建树状结构
     * @param configId       配置ID
     * @param userPrivilege  当前用户权限
     */
    void loadDirectories(int configId, const int &userPrivilege);

    /**
     * @brief 在给定父节点内，DFS 查找第一个第三层目录项
     * @param parentItem 父节点
     * @return 若找到第三层节点则返回指针，否则返回 nullptr
     */
    QStandardItem* findFirstThirdLevelItemDFS(QStandardItem *parentItem);

    /**
     * @brief 递归更新父级目录的复选框状态
     * @param item 当前变更的子项
     */
    void updateParentItems(QStandardItem *parentItem);

    /**
     * @brief 由 loadDirectories 获取的目录列表，构建树模型
     * @param directories 包含目录信息的 QJsonObject 列表
     */
    void buildTreeFromDirectories(const QList<QJsonObject> &directories);

    /**
     * @brief 更新父项的复选框状态（如果所有子项选中则父项也选中，否则取消）
     * @param item 当前变更的子项
     */
    void updateParentCheckState(QStandardItem *item);

    /**
     * @brief 更新按钮可见性：Home 界面隐藏，其他配置显示
     */
    void updateButtonsVisibility();

    /**
     * @brief 清理并隐藏第三层菜单内容
     */
    void clearThirdLevelMenu();

    /**
     * @brief 由给定的 DirectoryId 查询数据库中的字段信息（BondHead、Buttons）并返回
     * @param directoryId    目录ID
     * @param userPrivilege  当前用户权限
     * @return 包含第三层目录字段和按钮信息的 QJsonObject
     */
    QJsonObject fetchThirdLevelData(int directoryId, const int &userPrivilege);

    /**
     * @brief 自定义事件过滤器，用于在 QTreeView 上绘制虚线等
     * @param watched 监视的对象
     * @param event   事件
     * @return 是否拦截事件
     */
    bool eventFilter(QObject *watched, QEvent *event) override;

    /**
     * @brief 递归绘制所有分支
     * @param parentIndex 父节点索引
     * @param painter     QPainter 引用
     */
    void paintAllBranches(const QModelIndex &parentIndex, QPainter &painter);

    /**
     * @brief 绘制父节点到子节点的“拐角线”
     * @param childIndex  子节点索引
     * @param painter     QPainter 引用
     */
    void drawParentChildLine(const QModelIndex &childIndex, QPainter &painter);

    /**
     * @brief 兄弟节点之间的竖线连接
     * @param childIndex  当前节点索引
     * @param painter     QPainter 引用
     */
    void drawSiblingLine(const QModelIndex &childIndex, QPainter &painter);

    /**
     * @brief 应用自定义样式（例如树的图标、复选框等）
     */
    void applyCustomStyles();

    /**
     * @brief 创建顶部按钮，并绑定槽函数
     */
    void setupButton();

    /**
     * @brief 创建并返回一个统一样式的分隔线 QFrame
     * @param parent 父对象
     * @param height 分隔线高度
     * @return 分隔线 QFrame 指针
     */
    QFrame* createUnifiedSeparator(QWidget *parent, int height);

    /**
     * @brief 更新分隔线位置和可见性（主要针对一级目录和其子项）
     */
    void updateSeparatorLine();

    /**
     * @brief 查找父节点下最后一个可见子项，用于放置分隔线
     * @param parentIndex 父节点索引
     * @return 最后一个可见子节点的索引
     */
    QModelIndex findLastVisibleChild(const QModelIndex &parentIndex);

    /**
     * @brief 更新导航栏，显示选中的路径信息
     * @param index 选中节点的 QModelIndex
     */
    void updateNavigationBar(const QModelIndex &index);

    /**
     * @brief 加载第三层目录按钮配置并在 widget_left 显示
     * @param thirdLevelObj 包含第三层目录 button 信息的 JSON
     */
    void loadButtonConfigForThirdLevel(const QJsonObject &thirdLevelObj);

    /**
     * @brief 显示第三层目录的字段信息
     * @param data    第三层目录数据（包含 fields, buttons 等）
     * @param isHome  是否是 Home 界面，若是则填满 widget2
     */
    void displayThirdLevelFields(const QJsonObject &data, bool isHome);

    /**
     * @brief 保存当前选中的复选框路径到 QSettings
     */
    void saveCheckedPaths();

    /**
     * @brief 从 QSettings 中加载复选框选中路径，并恢复
     */
    void loadCheckedPaths();

    /**
     * @brief 收集所有被选中的复选框路径
     * @return 被选中的路径列表，每项为 "Root/Child/Child"
     */
    QStringList collectCheckedPaths();

    /**
     * @brief 递归收集选中的路径
     * @param item 当前节点
     * @param path 当前路径
     * @return 收集到的选中路径列表
     */
    QStringList collectCheckedPathsRecursive(QStandardItem *item, QStringList path);

    /**
     * @brief 批量设置选中的复选框
     * @param checkedPathsList 已选中的路径列表
     */
    void setCheckedPaths(const QStringList &checkedPathsList);

    /**
     * @brief 构建节点的完整路径
     * @param item 当前 QStandardItem
     * @return 路径列表，如 ["Root", "Child", "Child2"]
     */
    QStringList buildItemPath(QStandardItem *item);

    /**
     * @brief 根据路径查找对应的节点索引
     * @param path 路径列表
     * @return 对应的 QModelIndex，若未找到则无效
     */
    QModelIndex findItemByPath(const QStringList &path);

    /**
     * @brief 检查权限，用于判断某字段/按钮是否可见
     * @param UserGrade      数据库中存储的权限列表，如 "1,2,3"
     * @param userPrivilege  当前用户权限
     * @return 是否包含此权限
     */
    bool hasPrivilege(const int &UserGrade, const int &userPrivilege);
    /**
     * @brief 实时的数据写入库
     * @param TableName      数据所在表的name
     * @param Id            在表中的id
     * @param currentValue  当前修改的id
     */
    void updateDb(const QString &TableName, const int &Id,const QString currentValue);
public:
    struct menuInfo{
        int menuId;
        bool isthird;
        int  index;

    };
    int currentMenuId;
    std::array<menuInfo,5> menuArray;
    void loadpage(const int &configId);
    QList<QStandardItem*> thirdLevelListtest;
    QStandardItem* deepCopyItem(const QStandardItem *item);
};

#endif // DBTREEVIEWMANAGER_H
