import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import qs.Commons
import qs.Widgets

NBox {
  id: root

  property string sectionName: ""
  property var widgetModel: []
  property var availableWidgets: []

  signal addWidget(string widgetName, string section)
  signal removeWidget(string section, int index)
  signal reorderWidget(string section, int fromIndex, int toIndex)

  color: Color.mSurface
  Layout.fillWidth: true
  Layout.minimumHeight: {
    var widgetCount = widgetModel.length
    if (widgetCount === 0)
      return 140 * scaling

    var availableWidth = parent.width
    var avgWidgetWidth = 150 * scaling
    var widgetsPerRow = Math.max(1, Math.floor(availableWidth / avgWidgetWidth))
    var rows = Math.ceil(widgetCount / widgetsPerRow)

    return (50 + 20 + (rows * 48) + ((rows - 1) * Style.marginS) + 20) * scaling
  }

  // Generate widget color from name checksum
  function getWidgetColor(name) {
    const totalSum = name.split('').reduce((acc, character) => {
                                             return acc + character.charCodeAt(0)
                                           }, 0)
    switch (totalSum % 5) {
    case 0:
      return Color.mPrimary
    case 1:
      return Color.mSecondary
    case 2:
      return Color.mTertiary
    case 3:
      return Color.mError
    case 4:
      return Color.mOnSurface
    }
  }

  ColumnLayout {
    anchors.fill: parent
    anchors.margins: Style.marginL * scaling
    spacing: Style.marginM * scaling

    RowLayout {
      Layout.fillWidth: true

      NText {
        text: sectionName + " Section"
        font.pointSize: Style.fontSizeL * scaling
        font.weight: Style.fontWeightBold
        color: Color.mSecondary
        Layout.alignment: Qt.AlignVCenter
      }

      Item {
        Layout.fillWidth: true
      }
      NComboBox {
        id: comboBox
        model: availableWidgets
        label: ""
        description: ""
        placeholder: "Add widget to the " + sectionName.toLowerCase() + " section..."
        onSelected: key => {
                      comboBox.currentKey = key
                    }
        Layout.alignment: Qt.AlignVCenter
      }

      NIconButton {
        icon: "add"

        colorBg: Color.mPrimary
        colorFg: Color.mOnPrimary
        colorBgHover: Color.mSecondary
        colorFgHover: Color.mOnSecondary
        enabled: comboBox.selectedKey !== ""
        Layout.alignment: Qt.AlignVCenter
        Layout.leftMargin: Style.marginS * scaling
        onClicked: {
          if (comboBox.currentKey !== "") {
            addWidget(comboBox.currentKey, sectionName.toLowerCase())
            comboBox.currentKey = "battery"
          }
        }
      }
    }

    // Drag and Drop Widget Area
    Flow {
      id: widgetFlow
      Layout.fillWidth: true
      Layout.fillHeight: true
      Layout.minimumHeight: 65 * scaling
      spacing: Style.marginS * scaling
      flow: Flow.LeftToRight

      Repeater {
        model: widgetModel
        delegate: Rectangle {
          id: widgetItem
          required property int index
          required property string modelData

          width: widgetContent.implicitWidth + 16 * scaling
          height: 40 * scaling
          radius: Style.radiusL * scaling
          color: root.getWidgetColor(modelData)
          border.color: Color.mOutline
          border.width: Math.max(1, Style.borderS * scaling)

          // Drag properties
          Drag.keys: ["widget"]
          Drag.active: mouseArea.drag.active
          Drag.hotSpot.x: width / 2
          Drag.hotSpot.y: height / 2

          // Store the widget index for drag operations
          property int widgetIndex: index

          // Visual feedback during drag
          states: State {
            when: mouseArea.drag.active
            PropertyChanges {
              target: widgetItem
              scale: 1.1
              opacity: 0.9
              z: 1000
            }
          }

          RowLayout {
            id: widgetContent
            anchors.centerIn: parent
            spacing: Style.marginXS * scaling

            NText {
              text: modelData
              font.pointSize: Style.fontSizeS * scaling
              color: Color.mOnPrimary
              horizontalAlignment: Text.AlignHCenter
            }

            NIconButton {
              icon: "close"
              sizeRatio: 0.6
              colorBorder: Color.applyOpacity(Color.mOutline, "40")
              colorBg: Color.mOnSurface
              colorFg: Color.mOnPrimary
              colorBgHover: Color.applyOpacity(Color.mOnPrimary, "40")
              colorFgHover: Color.mOnPrimary
              onClicked: {
                removeWidget(sectionName.toLowerCase(), index)
              }
            }
          }

          // Mouse area for drag and drop
          MouseArea {
            id: mouseArea
            anchors.fill: parent
            drag.target: parent

            onPressed: mouse => {
                         // Check if the click is on the close button area
                         const closeButtonX = widgetContent.x + widgetContent.width - 20 * scaling
                         const closeButtonY = widgetContent.y
                         const closeButtonWidth = 20 * scaling
                         const closeButtonHeight = 20 * scaling

                         if (mouseX >= closeButtonX && mouseX <= closeButtonX + closeButtonWidth
                             && mouseY >= closeButtonY && mouseY <= closeButtonY + closeButtonHeight) {
                           // Click is on the close button, don't start drag
                           mouse.accepted = false
                           return
                         }

                         //Logger.log("NSectionEditor", `Started dragging widget: ${modelData} at index ${index}`)
                         // Bring to front when starting drag
                         widgetItem.z = 1000
                       }

            onReleased: {
              //Logger.log("NSectionEditor", `Released widget: ${modelData} at index ${index}`)
              // Reset z-index when drag ends
              widgetItem.z = 0

              // Get the global mouse position
              const globalDropX = mouseArea.mouseX + widgetItem.x + widgetFlow.x
              const globalDropY = mouseArea.mouseY + widgetItem.y + widgetFlow.y

              // Find which widget the drop position is closest to
              let targetIndex = -1
              let minDistance = Infinity

              for (var i = 0; i < widgetModel.length; i++) {
                if (i !== index) {
                  // Get the position of other widgets
                  const otherWidget = widgetFlow.children[i]
                  if (otherWidget && otherWidget.widgetIndex !== undefined) {
                    // Calculate the center of the other widget
                    const otherCenterX = otherWidget.x + otherWidget.width / 2 + widgetFlow.x
                    const otherCenterY = otherWidget.y + otherWidget.height / 2 + widgetFlow.y

                    // Calculate distance to the center of this widget
                    const distance = Math.sqrt(Math.pow(globalDropX - otherCenterX,
                                                        2) + Math.pow(globalDropY - otherCenterY, 2))

                    if (distance < minDistance) {
                      minDistance = distance
                      targetIndex = otherWidget.widgetIndex
                    }
                  }
                }
              }

              // Only reorder if we found a valid target and it's different from current position
              if (targetIndex !== -1 && targetIndex !== index) {
                const fromIndex = index
                const toIndex = targetIndex
                // Logger.log(
                //       "NSectionEditor",
                //       `Dropped widget from index ${fromIndex} to position ${toIndex} (distance: ${minDistance.toFixed(
                //         2)})`)
                reorderWidget(sectionName.toLowerCase(), fromIndex, toIndex)
              } else {
                Logger.warn("NSectionEditor", `No valid drop target found for widget at index ${index}`)
              }
            }
          }
        }
      }
    }

    // Drop zone at the beginning (positioned absolutely)
    DropArea {
      id: startDropZone
      width: 40 * scaling
      height: 40 * scaling
      x: widgetFlow.x
      y: widgetFlow.y + (widgetFlow.height - height) / 2
      keys: ["widget"]
      z: 1001 // Above the Flow

      Rectangle {
        anchors.fill: parent
        color: startDropZone.containsDrag ? Color.applyOpacity(Color.mPrimary, "20") : Color.transparent
        border.color: startDropZone.containsDrag ? Color.mPrimary : Color.transparent
        border.width: startDropZone.containsDrag ? 2 : 0
        radius: Style.radiusS * scaling
      }

      onEntered: function (drag) {//Logger.log("NSectionEditor", "Entered start drop zone")
      }

      onDropped: function (drop) {
        //Logger.log("NSectionEditor", "Dropped on start zone")
        if (drop.source && drop.source.widgetIndex !== undefined) {
          const fromIndex = drop.source.widgetIndex
          const toIndex = 0 // Insert at the beginning
          if (fromIndex !== toIndex) {
            //Logger.log("NSectionEditor", `Dropped widget from index ${fromIndex} to beginning`)
            reorderWidget(sectionName.toLowerCase(), fromIndex, toIndex)
          }
        }
      }
    }

    // Drop zone at the end (positioned absolutely)
    DropArea {
      id: endDropZone
      width: 40 * scaling
      height: 40 * scaling
      x: widgetFlow.x + widgetFlow.width - width
      y: widgetFlow.y + (widgetFlow.height - height) / 2
      keys: ["widget"]
      z: 1001 // Above the Flow

      Rectangle {
        anchors.fill: parent
        color: endDropZone.containsDrag ? Color.applyOpacity(Color.mPrimary, "20") : Color.transparent
        border.color: endDropZone.containsDrag ? Color.mPrimary : Color.transparent
        border.width: endDropZone.containsDrag ? 2 : 0
        radius: Style.radiusS * scaling
      }

      onEntered: function (drag) {//Logger.log("NSectionEditor", "Entered end drop zone")
      }

      onDropped: function (drop) {
        //Logger.log("NSectionEditor", "Dropped on end zone")
        if (drop.source && drop.source.widgetIndex !== undefined) {
          const fromIndex = drop.source.widgetIndex
          const toIndex = widgetModel.length // Insert at the end
          if (fromIndex !== toIndex) {
            //Logger.log("NSectionEditor", `Dropped widget from index ${fromIndex} to end`)
            reorderWidget(sectionName.toLowerCase(), fromIndex, toIndex)
          }
        }
      }
    }
  }
}
