import QtQuick
import qs.Common
import qs.Services
import qs.Widgets

Item {
    id: root

    property bool editMode: false
    property var widgetData: null
    property int widgetIndex: -1
    property bool isSlider: false
    property Component widgetComponent: null
    property real gridCellWidth: 100
    property real gridCellHeight: 60
    property int gridColumns: 4
    property var gridLayout: null

    z: dragArea.drag.active ? 10000 : 1

    signal widgetMoved(int fromIndex, int toIndex)
    signal removeWidget(int index)
    signal toggleWidgetSize(int index)
    signal configRequested(int index, var widgetData, var anchor)

    width: {
        const widgetWidth = widgetData?.width || 50;
        if (widgetWidth <= 25)
            return gridCellWidth;
        else if (widgetWidth <= 50)
            return gridCellWidth * 2;
        else if (widgetWidth <= 75)
            return gridCellWidth * 3;
        else
            return gridCellWidth * 4;
    }
    height: isSlider ? 16 : gridCellHeight

    Rectangle {
        id: dragIndicator
        anchors.fill: parent
        color: "transparent"
        border.color: Theme.primary
        border.width: dragArea.drag.active ? 2 : 0
        radius: Theme.cornerRadius
        opacity: dragArea.drag.active ? 0.8 : 1.0
        z: dragArea.drag.active ? 10000 : 1

        Behavior on border.width {
            NumberAnimation {
                duration: 150
            }
        }
        Behavior on opacity {
            NumberAnimation {
                duration: 150
            }
        }
    }

    Loader {
        id: widgetLoader
        anchors.fill: parent
        sourceComponent: widgetComponent
        property var widgetData: root.widgetData
        property int widgetIndex: root.widgetIndex
        property int globalWidgetIndex: root.widgetIndex
        property int widgetWidth: root.widgetData?.width || 50

        MouseArea {
            id: editModeBlocker
            anchors.fill: parent
            enabled: root.editMode
            acceptedButtons: Qt.AllButtons
            onPressed: function (mouse) {
                mouse.accepted = true;
            }
            onWheel: function (wheel) {
                wheel.accepted = true;
            }
            z: 100
        }
    }

    MouseArea {
        id: dragArea
        anchors.fill: parent
        enabled: editMode
        cursorShape: editMode ? Qt.OpenHandCursor : Qt.PointingHandCursor
        drag.target: editMode ? root : null
        drag.axis: Drag.XAndYAxis
        drag.smoothed: true

        onPressed: function (mouse) {
            if (editMode) {
                cursorShape = Qt.ClosedHandCursor;
                if (root.gridLayout && root.gridLayout.moveToTop) {
                    root.gridLayout.moveToTop(root);
                }
            }
        }

        onReleased: function (mouse) {
            if (editMode) {
                cursorShape = Qt.OpenHandCursor;
                root.snapToGrid();
            }
        }
    }

    Drag.active: dragArea.drag.active
    Drag.hotSpot.x: width / 2
    Drag.hotSpot.y: height / 2

    function swapIndices(i, j) {
        if (i === j)
            return;
        const arr = SettingsData.controlCenterWidgets;
        if (!arr || i < 0 || j < 0 || i >= arr.length || j >= arr.length)
            return;

        const copy = arr.slice();
        const tmp = copy[i];
        copy[i] = copy[j];
        copy[j] = tmp;

        SettingsData.set("controlCenterWidgets", copy);
    }

    function snapToGrid() {
        if (!editMode || !gridLayout)
            return;
        const globalPos = root.mapToItem(gridLayout, 0, 0);
        const cellWidth = gridLayout.width / gridColumns;
        const cellHeight = gridCellHeight + Theme.spacingS;

        const centerX = globalPos.x + (root.width / 2);
        const centerY = globalPos.y + (root.height / 2);

        let targetCol = Math.max(0, Math.floor(centerX / cellWidth));
        let targetRow = Math.max(0, Math.floor(centerY / cellHeight));

        targetCol = Math.min(targetCol, gridColumns - 1);

        const newIndex = findBestInsertionIndex(targetRow, targetCol);

        if (newIndex !== widgetIndex && newIndex >= 0 && newIndex < (SettingsData.controlCenterWidgets?.length || 0)) {
            swapIndices(widgetIndex, newIndex);
        }
    }

    function findBestInsertionIndex(targetRow, targetCol) {
        const widgets = SettingsData.controlCenterWidgets || [];
        const n = widgets.length;
        if (!n || widgetIndex < 0 || widgetIndex >= n)
            return -1;

        function spanFor(width) {
            const w = width ?? 50;
            if (w <= 25)
                return 1;
            if (w <= 50)
                return 2;
            if (w <= 75)
                return 3;
            return 4;
        }

        const cols = gridColumns || 4;

        let row = 0, col = 0;
        let draggedOrigKey = null;

        const pos = [];

        for (let i = 0; i < n; i++) {
            const span = Math.min(spanFor(widgets[i].width), cols);

            if (col + span > cols) {
                row++;
                col = 0;
            }

            const startCol = col;
            const centerKey = row * cols + (startCol + (span - 1) / 2);

            if (i === widgetIndex) {
                draggedOrigKey = centerKey;
            } else {
                pos.push({
                    index: i,
                    row,
                    startCol,
                    span,
                    centerKey
                });
            }

            col += span;
            if (col >= cols) {
                row++;
                col = 0;
            }
        }

        if (pos.length === 0)
            return -1;

        const centerColCoord = targetCol + 0.5;
        const targetKey = targetRow * cols + centerColCoord;

        for (let k = 0; k < pos.length; k++) {
            const p = pos[k];
            if (p.row === targetRow && centerColCoord >= p.startCol && centerColCoord < (p.startCol + p.span)) {
                return p.index;
            }
        }

        let lo = 0, hi = pos.length - 1;
        if (targetKey <= pos[0].centerKey)
            return pos[0].index;
        if (targetKey >= pos[hi].centerKey)
            return pos[hi].index;

        while (lo <= hi) {
            const mid = (lo + hi) >> 1;
            const mk = pos[mid].centerKey;
            if (targetKey < mk)
                hi = mid - 1;
            else if (targetKey > mk)
                lo = mid + 1;
            else
                return pos[mid].index;
        }
        const movingUp = (draggedOrigKey != null) ? (targetKey < draggedOrigKey) : false;
        return (movingUp ? pos[lo].index : pos[hi].index);
    }

    Rectangle {
        id: removeButton
        width: 16
        height: 16
        radius: 8
        color: Theme.error
        anchors.top: parent.top
        anchors.right: parent.right
        anchors.margins: -4
        visible: editMode
        z: 10

        DankIcon {
            anchors.centerIn: parent
            name: "close"
            size: 12
            color: Theme.primaryText
        }

        MouseArea {
            anchors.fill: parent
            cursorShape: Qt.PointingHandCursor
            onClicked: removeWidget(widgetIndex)
        }
    }

    SizeControls {
        anchors.bottom: parent.bottom
        anchors.left: parent.left
        anchors.margins: -6
        visible: editMode
        z: 10
        currentSize: root.widgetData?.width || 50
        isSlider: root.isSlider
        widgetIndex: root.widgetIndex
        onSizeChanged: newSize => {
            var widgets = SettingsData.controlCenterWidgets.slice();
            if (widgetIndex >= 0 && widgetIndex < widgets.length) {
                widgets[widgetIndex].width = newSize;
                SettingsData.set("controlCenterWidgets", widgets);
            }
        }
    }

    readonly property bool hasConfigMenu: widgetData?.id === "diskUsage"

    Rectangle {
        id: configButton
        width: 16
        height: 16
        radius: 8
        color: Theme.primary
        anchors.top: removeButton.top
        anchors.right: removeButton.left
        anchors.rightMargin: 4
        visible: editMode && root.hasConfigMenu
        z: 10

        DankIcon {
            anchors.centerIn: parent
            name: "settings"
            size: 12
            color: Theme.primaryText
        }

        MouseArea {
            anchors.fill: parent
            cursorShape: Qt.PointingHandCursor
            onClicked: root.configRequested(root.widgetIndex, root.widgetData, configButton)
        }
    }

    Rectangle {
        id: dragHandle
        width: 16
        height: 12
        radius: 2
        color: Theme.primary
        anchors.top: parent.top
        anchors.left: parent.left
        anchors.margins: 4
        visible: editMode
        z: 15
        opacity: dragArea.drag.active ? 1.0 : 0.7

        DankIcon {
            anchors.centerIn: parent
            name: "drag_indicator"
            size: 10
            color: Theme.primaryText
        }

        Behavior on opacity {
            NumberAnimation {
                duration: 150
            }
        }
    }

    Rectangle {
        anchors.fill: parent
        color: editMode ? Theme.primaryHoverLight : Theme.withAlpha(Theme.primaryHoverLight, 0)
        radius: Theme.cornerRadius
        border.color: "transparent"
        border.width: 0
        z: -1

        Behavior on color {
            ColorAnimation {
                duration: Theme.shortDuration
            }
        }
    }
}
