#ifndef LAYERED_DIALOG_H
#define LAYERED_DIALOG_H

#include "../DialogFrame/frameless-dialog.h"
#include <QPointer>
#include <functional>

// LayeredDialog: a helper for chaining modal dialogs where
// - The first (root) dialog is ApplicationModal
// - Subsequent dialogs (children) are WindowModal blocking only their parent
// - Each child is guaranteed to stay above its parent (Qt parent/child stacking)
// - Provides convenience methods for opening child dialogs without nested exec()
// - Optional size reduction per depth for visual differentiation.
//
// Usage pattern:
//   auto *dlg = new SomeLayeredDialogDerived(host); // derives from LayeredDialog
//   dlg->openLayer(); // show as root (ApplicationModal)
//   ... inside dialog:
//      openChild<AnotherLayeredDialog>(...); // returns pointer, already shown & raised
//      // Later: closeChain(); // closes this dialog and all its parents.
// Note: Overlay panels (AddUserPanel, ChangePasswordPanel 等) 不使用 LayeredDialog，
// 而是通过 ModalOverlayManager 在同一窗口内部叠加显示。
//
// NOTE: openLayer() / openChild() use show() instead of exec() to avoid nested event loops.
// If blocking behaviour is required for legacy code, you can still call exec(),
// but prefer signals to react to completion.

class LayeredDialog : public FramelessDialog {
    Q_OBJECT
public:
    explicit LayeredDialog(const QString &title,
                           int fixedWidth = 464,
                           QWidget *parent = nullptr,
                           bool enableSizeReduction = true)
        : FramelessDialog(title, fixedWidth, parent),
          m_enableSizeReduction(enableSizeReduction) {
        applyLayerModality();
        applyDepthSizing();
    }

    virtual ~LayeredDialog() = default;

    // Depth in chain (root == 1)
    int depth() const {
        int d = 1;
        const QWidget *p = parentWidget();
        while (p) {
            if (qobject_cast<const LayeredDialog*>(p)) {
                ++d;
            }
            p = p->parentWidget();
        }
        return d;
    }

    // Show this dialog with appropriate stacking + focus.
    LayeredDialog* openLayer() {
        this->show();
        this->raise();
        this->activateWindow();
        return this;
    }

    // Template helper to create and open a child LayeredDialog-derived class.
    template <typename DialogT, typename... Args>
    DialogT* openChild(Args&&... args) {
        // Parent is this, depth auto-configured in child's ctor.
        auto *child = new DialogT(std::forward<Args>(args)...);
        // If passed parent manually in arguments, skip; ensure parentWidget is this.
        if (child->parentWidget() != this) {
            child->setParent(this); // Rare case; usually ctors will accept parent.
        }
        centerChild(child);
        child->openLayer();
        return child;
    }

    // Close this dialog and its ancestor chain (like Russian doll collapse).
    void closeChain() {
        QWidget *w = this;
        while (w) {
            QWidget *parent = w->parentWidget();
            w->close();
            w = parent;
        }
    }

protected:
    void applyLayerModality() {
        if (qobject_cast<LayeredDialog*>(parentWidget()) == nullptr) {
            // Root dialog
            setWindowModality(Qt::ApplicationModal);
        } else {
            setWindowModality(Qt::WindowModal);
        }
    }

    void applyDepthSizing() {
        if (!m_enableSizeReduction) return;
        const int d = depth();
        // Similar visual differentiation: subtract 30px per depth after 1.
        const int baseW = width(); // FramelessDialog already sets fixed width.
        const int baseH = sizeHint().height();
        int reduction = (d - 1) * 30;
        int finalW = baseW - reduction;
        int finalH = baseH - reduction;
        const int minW = 280; // keep reasonable minimums
        const int minH = 180;
        if (finalW < minW) finalW = minW;
        if (finalH < minH) finalH = minH;
        resize(finalW, finalH);
    }

    void centerChild(QWidget *child) {
        if (!child) return;
        // Center relative to this dialog's geometry.
        QRect parentGeom = this->geometry();
        QPoint center = parentGeom.center();
        QSize childSize = child->size();
        QPoint topLeft = center - QPoint(childSize.width()/2, childSize.height()/2);
        child->move(topLeft);
    }

private:
    bool m_enableSizeReduction { true };
};

#endif // LAYERED_DIALOG_H
