import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import qs.Commons
import qs.Services.Compositor
import qs.Services.Noctalia
import qs.Services.UI
import qs.Widgets

ColumnLayout {
  id: root

  spacing: Style.marginL

  // Available widgets model - declared early so Repeater delegates can access it
  property alias availableWidgetsModel: availableWidgets
  ListModel {
    id: availableWidgets
  }

  // Listen for plugin widget registration/unregistration
  Connections {
    target: DesktopWidgetRegistry
    function onPluginWidgetRegistryUpdated() {
      updateAvailableWidgetsModel();
    }
  }

  NToggle {
    Layout.fillWidth: true
    label: I18n.tr("panels.desktop-widgets.enabled-label")
    description: I18n.tr("panels.desktop-widgets.enabled-description")
    checked: Settings.data.desktopWidgets.enabled
    defaultValue: Settings.getDefaultValue("desktopWidgets.enabled")
    onToggled: checked => Settings.data.desktopWidgets.enabled = checked
  }

  NToggle {
    Layout.fillWidth: true
    enabled: Settings.data.desktopWidgets.enabled
    label: I18n.tr("panels.desktop-widgets.overview-enabled-label")
    description: I18n.tr("panels.desktop-widgets.overview-enabled-description")
    checked: Settings.data.desktopWidgets.overviewEnabled
    defaultValue: Settings.getDefaultValue("desktopWidgets.overviewEnabled")
    onToggled: checked => Settings.data.desktopWidgets.overviewEnabled = checked
  }

  ColumnLayout {
    enabled: Settings.data.desktopWidgets.enabled

    NLabel {
      description: I18n.tr("panels.desktop-widgets.cpu-intensive-note")
    }

    NButton {
      Layout.fillWidth: true
      Layout.topMargin: Style.marginM
      Layout.bottomMargin: Style.marginM
      text: DesktopWidgetRegistry.editMode ? I18n.tr("panels.desktop-widgets.edit-mode-exit-button") : I18n.tr("panels.desktop-widgets.edit-mode-button-label")
      icon: "edit"
      onClicked: {
        DesktopWidgetRegistry.editMode = !DesktopWidgetRegistry.editMode;
        if (DesktopWidgetRegistry.editMode && Settings.data.ui.settingsPanelMode !== "window") {
          var item = root.parent;
          while (item) {
            if (item.closeRequested !== undefined) {
              item.closeRequested();
              break;
            }
            item = item.parent;
          }
        }
      }
    }

    // One NSectionEditor per monitor
    Repeater {
      model: Quickshell.screens

      NSectionEditor {
        required property var modelData
        readonly property real compositorScale: {
          const info = CompositorService.displayScales[modelData.name];
          return (info && info.scale) ? info.scale : 1.0;
        }

        Layout.fillWidth: true
        sectionName: modelData.name
        sectionSubtitle: {
          // Format scale to 2 decimal places to prevent overly long text
          var formattedScale = compositorScale.toFixed(2);
          return "(" + modelData.width + "x" + modelData.height + " @ " + formattedScale + "x)";
        }

        sectionId: modelData.name
        screen: modelData
        settingsDialogComponent: Qt.resolvedUrl(Quickshell.shellDir + "/Modules/Panels/Settings/DesktopWidgets/DesktopWidgetSettingsDialog.qml")
        widgetRegistry: DesktopWidgetRegistry
        widgetModel: getWidgetsForMonitor(modelData.name)
        availableWidgets: root.availableWidgetsModel
        availableSections: root.getScreenNames()
        sectionLabels: root.getScreenLabels()
        sectionIcons: root.getScreenIcons()
        draggable: false // Desktop widgets are positioned by X,Y, not list order
        crossSectionDraggable: true
        maxWidgets: -1
        onAddWidget: (widgetId, section) => _addWidgetToMonitor(modelData.name, widgetId)
        onRemoveWidget: (section, index) => _removeWidgetFromMonitor(modelData.name, index)
        onMoveWidget: (fromSection, index, toSection) => _moveWidgetToMonitor(fromSection, index, toSection)
        onUpdateWidgetSettings: (section, index, settings) => _updateWidgetSettingsForMonitor(modelData.name, index, settings)
        pluginSettingsEntryPoints: ["desktopWidgetSettings", "settings"]
        onOpenPluginSettingsRequested: (manifest, entryPoint) => pluginSettingsDialog.openPluginSettings(manifest, entryPoint)
      }
    }
  }

  // Shared Plugin Settings Popup
  NPluginSettingsPopup {
    id: pluginSettingsDialog
    parent: Overlay.overlay
    showToastOnSave: false
  }

  Component.onCompleted: {
    // Use Qt.callLater to ensure DesktopWidgetRegistry is ready
    Qt.callLater(updateAvailableWidgetsModel);
  }

  // Helper to get screen names array
  function getScreenNames() {
    var names = [];
    for (var i = 0; i < Quickshell.screens.length; i++) {
      names.push(Quickshell.screens[i].name);
    }
    return names;
  }

  // Helper to get screen labels map (just screen names, NSectionEditor adds "Move to" prefix)
  function getScreenLabels() {
    var labels = {};
    for (var i = 0; i < Quickshell.screens.length; i++) {
      var screen = Quickshell.screens[i];
      labels[screen.name] = screen.name;
    }
    return labels;
  }

  // Helper to get screen icons map
  function getScreenIcons() {
    var icons = {};
    for (var i = 0; i < Quickshell.screens.length; i++) {
      icons[Quickshell.screens[i].name] = "device-desktop";
    }
    return icons;
  }

  function updateAvailableWidgetsModel() {
    availableWidgets.clear();
    try {
      if (typeof DesktopWidgetRegistry === "undefined" || !DesktopWidgetRegistry) {
        Logger.e("DesktopWidgetsTab", "DesktopWidgetRegistry is not available");
        // Retry after a short delay
        Qt.callLater(function () {
          if (typeof DesktopWidgetRegistry !== "undefined" && DesktopWidgetRegistry) {
            updateAvailableWidgetsModel();
          }
        });
        return;
      }
      var widgetIds = DesktopWidgetRegistry.getAvailableWidgets();
      Logger.d("DesktopWidgetsTab", "Found widgets:", widgetIds, "count:", widgetIds ? widgetIds.length : 0);
      if (!widgetIds || widgetIds.length === 0) {
        Logger.w("DesktopWidgetsTab", "No widgets found in registry");
        return;
      }
      for (var i = 0; i < widgetIds.length; i++) {
        var widgetId = widgetIds[i];
        var displayName = widgetId;

        // Get plugin name for plugin widgets
        var isPlugin = false;
        if (DesktopWidgetRegistry.isPluginWidget(widgetId)) {
          isPlugin = true;
          var pluginId = widgetId.replace("plugin:", "");
          var manifest = PluginRegistry.getPluginManifest(pluginId);
          if (manifest && manifest.name) {
            displayName = manifest.name;
          }
        }

        // Add plugin badge first (with custom color)
        const badges = [];
        if (isPlugin) {
          badges.push({
                        "icon": "plugin",
                        "color": Color.mSecondary
                      });
        }
        if (DesktopWidgetRegistry.isCpuIntensive(widgetId)) {
          badges.push({
                        "icon": "cpu-intensive",
                        "color": Color.mSecondary
                      });
        }

        availableWidgets.append({
                                  "key": widgetId,
                                  "name": displayName,
                                  "badges": badges
                                });
      }
      Logger.d("DesktopWidgetsTab", "Available widgets model count:", availableWidgets.count);
    } catch (e) {
      Logger.e("DesktopWidgetsTab", "Error updating available widgets:", e, e.stack);
    }
  }

  // Get widgets for a specific monitor
  function getWidgetsForMonitor(monitorName) {
    var monitorWidgets = Settings.data.desktopWidgets.monitorWidgets || [];
    for (var i = 0; i < monitorWidgets.length; i++) {
      if (monitorWidgets[i].name === monitorName) {
        return monitorWidgets[i].widgets || [];
      }
    }
    return [];
  }

  // Set widgets for a specific monitor
  function setWidgetsForMonitor(monitorName, widgets) {
    var monitorWidgets = Settings.data.desktopWidgets.monitorWidgets || [];
    var newMonitorWidgets = monitorWidgets.slice();
    var found = false;
    for (var i = 0; i < newMonitorWidgets.length; i++) {
      if (newMonitorWidgets[i].name === monitorName) {
        newMonitorWidgets[i] = {
          "name": monitorName,
          "widgets": widgets
        };
        found = true;
        break;
      }
    }
    if (!found) {
      newMonitorWidgets.push({
                               "name": monitorName,
                               "widgets": widgets
                             });
    }
    Settings.data.desktopWidgets.monitorWidgets = newMonitorWidgets;
  }

  function _addWidgetToMonitor(monitorName, widgetId) {
    var newWidget = {
      "id": widgetId
    };
    if (DesktopWidgetRegistry.widgetHasUserSettings(widgetId)) {
      var metadata = DesktopWidgetRegistry.widgetMetadata[widgetId];
      if (metadata) {
        Object.keys(metadata).forEach(function (key) {
          newWidget[key] = metadata[key];
        });
      }
    }
    // Set default positions
    if (widgetId === "Clock") {
      newWidget.x = 50;
      newWidget.y = 50;
    } else if (widgetId === "MediaPlayer") {
      newWidget.x = 100;
      newWidget.y = 200;
    } else if (widgetId === "AudioVisualizer") {
      newWidget.x = 120;
      newWidget.y = 280;
    } else if (widgetId === "Weather") {
      newWidget.x = 100;
      newWidget.y = 300;
    } else {
      // Default position for plugin widgets
      newWidget.x = 150;
      newWidget.y = 150;
    }
    var widgets = getWidgetsForMonitor(monitorName).slice();
    widgets.push(newWidget);
    setWidgetsForMonitor(monitorName, widgets);
  }

  function _removeWidgetFromMonitor(monitorName, index) {
    var widgets = getWidgetsForMonitor(monitorName);
    if (index >= 0 && index < widgets.length) {
      var newArray = widgets.slice();
      newArray.splice(index, 1);
      setWidgetsForMonitor(monitorName, newArray);
    }
  }

  function _updateWidgetSettingsForMonitor(monitorName, index, settings) {
    var widgets = getWidgetsForMonitor(monitorName);
    if (index >= 0 && index < widgets.length) {
      var newArray = widgets.slice();
      newArray[index] = Object.assign({}, newArray[index], settings);
      setWidgetsForMonitor(monitorName, newArray);
    }
  }

  function _moveWidgetToMonitor(fromMonitor, index, toMonitor) {
    Logger.i("DesktopWidgetsTab", "Moving widget from", fromMonitor, "index", index, "to", toMonitor);
    var sourceWidgets = getWidgetsForMonitor(fromMonitor);
    if (index < 0 || index >= sourceWidgets.length) {
      Logger.e("DesktopWidgetsTab", "Invalid index", index, "for monitor", fromMonitor);
      return;
    }

    // Get the widget to move
    var newSourceWidgets = sourceWidgets.slice();
    var widget = Object.assign({}, newSourceWidgets.splice(index, 1)[0]);

    // Reset position and scale to ensure widget is accessible on new screen
    widget.x = 100;
    widget.y = 100;
    widget.scale = 1.0;

    // Add to destination monitor
    var destWidgets = getWidgetsForMonitor(toMonitor).slice();
    destWidgets.push(widget);

    // Update both monitors
    setWidgetsForMonitor(fromMonitor, newSourceWidgets);
    setWidgetsForMonitor(toMonitor, destWidgets);
  }
}
