import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import QtQuick.Effects
import Quickshell
import Quickshell.Io
import qs.Commons
import qs.Services.UI
import qs.Widgets
import "../../../Helpers/FuzzySort.js" as FuzzySort

ColumnLayout {
  id: root

  property string selectedDirectory: ""
  property string selectedWallpaper: ""

  signal directoryChanged(string directory)
  signal wallpaperChanged(string wallpaper)

  spacing: Style.marginL

  // Beautiful header with icon
  ColumnLayout {
    Layout.fillWidth: true
    Layout.bottomMargin: Style.marginL
    spacing: Style.marginM

    RowLayout {
      spacing: Style.marginM

      Rectangle {
        width: 40
        height: 40
        radius: Style.radiusL
        color: Color.mSurfaceVariant
        opacity: 0.6

        NIcon {
          icon: "image"
          pointSize: Style.fontSizeL
          color: Color.mPrimary
          anchors.centerIn: parent
        }
      }

      ColumnLayout {
        spacing: Style.marginXS

        NText {
          text: I18n.tr("setup.wallpaper.header")
          pointSize: Style.fontSizeXL
          font.weight: Style.fontWeightBold
          color: Color.mPrimary
        }

        NText {
          text: I18n.tr("setup.wallpaper.subheader")
          pointSize: Style.fontSizeM
          color: Color.mOnSurfaceVariant
        }
      }
    }
  }

  // Large preview with rounded corners and shadow effect
  Rectangle {
    Layout.fillWidth: true
    Layout.fillHeight: true
    Layout.minimumHeight: 180
    color: Color.mSurfaceVariant
    radius: Style.radiusL
    border.color: selectedWallpaper !== "" ? Color.mPrimary : Color.mOutline
    border.width: selectedWallpaper !== "" ? 2 : 1
    clip: true

    // Mirror WallpaperPanel approach with rounded shader mask
    NImageCached {
      id: previewCached
      anchors.fill: parent
      anchors.margins: 4
      cacheFolder: Settings.cacheDirImagesWallpapers
      imagePath: selectedWallpaper !== "" ? "file://" + selectedWallpaper : ""
      visible: false // used as texture source for the shader
    }

    ShaderEffect {
      anchors.fill: parent
      anchors.margins: 4
      property var source: ShaderEffectSource {
        sourceItem: previewCached
        hideSource: true
        live: true
        recursive: false
        format: ShaderEffectSource.RGBA
      }
      property real itemWidth: width
      property real itemHeight: height
      property real cornerRadius: Style.radiusL
      property real imageOpacity: 1.0
      fragmentShader: Qt.resolvedUrl(Quickshell.shellDir + "/Shaders/qsb/rounded_image.frag.qsb")
      supportsAtlasTextures: false
      blending: true
    }

    // Loading placeholder
    Rectangle {
      anchors.fill: parent
      color: Color.mSurfaceVariant
      radius: Style.radiusL
      visible: (previewCached.status === Image.Loading || previewCached.status === Image.Null) && selectedWallpaper !== ""

      NIcon {
        icon: "image"
        pointSize: Style.fontSizeXXL
        color: Color.mOnSurfaceVariant
        anchors.centerIn: parent
      }
    }

    // Error placeholder
    Rectangle {
      anchors.fill: parent
      color: Color.mError
      opacity: 0.1
      radius: Style.radiusL
      visible: previewCached.status === Image.Error && selectedWallpaper !== ""

      ColumnLayout {
        anchors.centerIn: parent
        spacing: Style.marginS

        NIcon {
          icon: "alert-circle"
          pointSize: Style.fontSizeXXL
          color: Color.mError
          Layout.alignment: Qt.AlignHCenter
        }

        NText {
          text: I18n.tr("setup.wallpaper.preview-error")
          pointSize: Style.fontSizeS
          color: Color.mError
          Layout.alignment: Qt.AlignHCenter
        }
      }
    }

    NBusyIndicator {
      anchors.centerIn: parent
      visible: (previewCached.status === Image.Loading || previewCached.status === Image.Null) && selectedWallpaper !== ""
      running: visible
      size: 28
    }

    ColumnLayout {
      anchors.centerIn: parent
      spacing: Style.marginL
      visible: selectedWallpaper === ""
      opacity: 0.6

      Rectangle {
        Layout.alignment: Qt.AlignHCenter
        width: 64
        height: 64
        radius: width / 2
        color: Color.mPrimary
        opacity: 0.15

        NIcon {
          icon: "sparkles"
          pointSize: Style.fontSizeXXL
          color: Color.mPrimary
          anchors.centerIn: parent
        }
      }

      NText {
        text: I18n.tr("setup.wallpaper.select-prompt")
        pointSize: Style.fontSizeL
        color: Color.mOnSurfaceVariant
        Layout.alignment: Qt.AlignHCenter
        font.weight: Style.fontWeightMedium
      }
    }

    Behavior on border.color {
      ColorAnimation {
        duration: Style.animationFast
      }
    }
  }

  // Wallpaper gallery strip
  Item {
    Layout.fillWidth: true
    Layout.preferredHeight: 90
    visible: filteredWallpapers.length > 0

    ScrollView {
      id: galleryScroll
      anchors.fill: parent
      clip: true
      ScrollBar.horizontal.policy: ScrollBar.AsNeeded
      ScrollBar.vertical.policy: ScrollBar.AlwaysOff

      // Enable vertical mouse wheel to scroll the horizontal strip by moving contentX
      WheelHandler {
        target: galleryScroll.contentItem
        acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
        onWheel: event => {
                   const flick = galleryScroll.contentItem
                   if (!flick)
                   return
                   const delta = event.pixelDelta.x !== 0 || event.pixelDelta.y !== 0 ? (event.pixelDelta.y !== 0 ? event.pixelDelta.y : event.pixelDelta.x) : (event.angleDelta.y !== 0 ? event.angleDelta.y : event.angleDelta.x)
                   // Move opposite of wheel to scroll content to the right for wheel down
                   const step = -delta
                   const maxX = Math.max(0, flick.contentWidth - flick.width)
                   let newX = flick.contentX + step
                   if (newX < 0)
                   newX = 0
                   if (newX > maxX)
                   newX = maxX
                   flick.contentX = newX
                   event.accepted = true
                 }
      }

      RowLayout {
        spacing: Style.marginM
        height: parent.height

        Repeater {
          model: filteredWallpapers
          delegate: Rectangle {
            Layout.preferredWidth: 120
            Layout.preferredHeight: 80
            color: Color.mSurface
            border.color: selectedWallpaper === modelData ? Color.mPrimary : Color.mOutline
            border.width: selectedWallpaper === modelData ? 2 : 1
            clip: true

            // Cached thumbnail
            NImageCached {
              id: thumbCached
              anchors.fill: parent
              anchors.margins: 3
              source: "file://" + modelData
            }

            // Loading state
            Rectangle {
              anchors.fill: parent
              color: Color.mSurfaceVariant
              visible: thumbCached.status === Image.Loading

              NIcon {
                icon: "image"
                pointSize: Style.fontSizeL
                color: Color.mOnSurfaceVariant
                anchors.centerIn: parent
              }
            }

            // Error state
            Rectangle {
              anchors.fill: parent
              color: Color.mSurfaceVariant
              radius: Style.radiusM
              visible: thumbCached.status === Image.Error

              NIcon {
                icon: "image"
                pointSize: Style.fontSizeL
                color: Color.mOnSurfaceVariant
                anchors.centerIn: parent
              }
            }

            NBusyIndicator {
              anchors.centerIn: parent
              visible: thumbCached.status === Image.Loading || thumbCached.status === Image.Null
              running: visible
              size: 18
            }

            Rectangle {
              anchors.fill: parent
              color: Color.mPrimary
              opacity: hoverHandler.hovered ? 0.1 : 0
              Behavior on opacity {
                NumberAnimation {
                  duration: Style.animationFast
                }
              }
            }

            Rectangle {
              visible: selectedWallpaper === modelData
              anchors.right: parent.right
              anchors.bottom: parent.bottom
              anchors.margins: 6
              width: 24
              height: 24
              radius: width / 2
              color: Color.mPrimary

              NIcon {
                icon: "check"
                pointSize: Style.fontSizeS
                color: Color.mOnPrimary
                anchors.centerIn: parent
              }
            }

            HoverHandler {
              id: hoverHandler
            }

            TapHandler {
              onTapped: {
                selectedWallpaper = modelData
                wallpaperChanged(modelData)
              }
            }
          }
        }
      }
    }
  }

  // Helpful info card
  Rectangle {
    Layout.fillWidth: true
    Layout.preferredHeight: 80
    color: Color.mSurfaceVariant
    radius: Style.radiusM
    opacity: 0.4
    visible: filteredWallpapers.length === 0

    RowLayout {
      anchors.fill: parent
      anchors.margins: Style.marginL
      spacing: Style.marginM

      NIcon {
        icon: "folder-open"
        pointSize: Style.fontSizeL
        color: Color.mOnSurfaceVariant
      }

      ColumnLayout {
        Layout.fillWidth: true
        spacing: Style.marginXS
        NText {
          text: filteredWallpapers.length === 0 && selectedDirectory !== "" ? I18n.tr("setup.wallpaper.none-in-dir") : I18n.tr("setup.wallpaper.no-dir")
          pointSize: Style.fontSizeM
          font.weight: Style.fontWeightBold
          color: Color.mOnSurfaceVariant
        }
        NText {
          text: selectedDirectory !== "" ? I18n.tr("setup.wallpaper.no-valid", {
                                                     "dir": selectedDirectory
                                                   }) : I18n.tr("setup.wallpaper.choose-dir")
          pointSize: Style.fontSizeS
          color: Color.mOnSurfaceVariant
          wrapMode: Text.WordWrap
          Layout.fillWidth: true
          opacity: 0.8
        }
      }
    }
  }

  // Directory selection
  ColumnLayout {
    Layout.fillWidth: true
    spacing: Style.marginM

    NTextInputButton {
      id: wallpaperPathInput
      label: I18n.tr("setup.wallpaper.dir.label")
      description: I18n.tr("setup.wallpaper.dir.description")
      text: selectedDirectory
      buttonIcon: "folder-open"
      buttonTooltip: I18n.tr("setup.wallpaper.dir.browse")
      Layout.fillWidth: true
      onInputEditingFinished: {
        selectedDirectory = text
        directoryChanged(text)
      }
      onButtonClicked: directoryPicker.open()
    }
  }

  // Internal properties and functions
  property list<string> wallpapersList: []
  property list<string> filteredWallpapers: []

  function updateFilteredWallpapers() {
    filteredWallpapers = wallpapersList
  }

  function refreshWallpapers() {
    if (!selectedDirectory || selectedDirectory === "") {
      wallpapersList = []
      filteredWallpapers = []
      return
    }
    if (typeof WallpaperService !== "undefined" && WallpaperService.getWallpapersList) {
      var wallpapers = WallpaperService.getWallpapersList(Screen.name)
      wallpapersList = wallpapers
      updateFilteredWallpapers()
      if (wallpapersList.length > 0 && selectedWallpaper === "") {
        selectedWallpaper = wallpapersList[0]
      }
    } else {
      readDirectoryImages(selectedDirectory)
    }
  }

  function readDirectoryImages(directoryPath) {
    directoryScanner.command = ["find", directoryPath, "-type", "f", "\\(-iname", "*.jpg", "-o", "-iname", "*.jpeg", "-o", "-iname", "*.png", "-o", "-iname", "*.bmp", "-o", "-iname", "*.webp", "-o", "-iname", "*.svg", "\\)"]
    directoryScanner.running = true
    return []
  }

  onSelectedDirectoryChanged: {
    if (typeof Settings !== "undefined" && Settings.data && Settings.data.wallpaper) {
      Settings.data.wallpaper.directory = selectedDirectory
    }
    if (typeof WallpaperService !== "undefined" && WallpaperService.refreshWallpapersList) {
      WallpaperService.refreshWallpapersList()
    }
    Qt.callLater(refreshWallpapers)
  }

  Connections {
    target: WallpaperService
    enabled: typeof WallpaperService !== "undefined"
    function onWallpaperListChanged(screenName, count) {
      if (screenName === Screen.name) {
        Qt.callLater(refreshWallpapers)
      }
    }
  }

  Timer {
    id: initialRefreshTimer
    interval: 1000
    running: false
    repeat: false
    onTriggered: refreshWallpapers()
  }

  Component.onCompleted: {
    if (typeof Settings !== "undefined" && Settings.data && Settings.data.wallpaper && Settings.data.wallpaper.directory) {
      selectedDirectory = Settings.data.wallpaper.directory
    } else {
      selectedDirectory = Quickshell.env("HOME") + "/Pictures/Wallpapers"
    }
    if (typeof WallpaperService !== "undefined" && WallpaperService.currentWallpaper) {
      selectedWallpaper = WallpaperService.currentWallpaper
    }
    initialRefreshTimer.start()
  }

  NFilePicker {
    id: directoryPicker
    selectionMode: "folders"
    title: I18n.tr("setup.wallpaper.dir.select-title")
    initialPath: selectedDirectory || Quickshell.env("HOME") + "/Pictures"
    onAccepted: paths => {
                  if (paths.length > 0) {
                    selectedDirectory = paths[0]
                    directoryChanged(paths[0])
                  }
                }
  }

  Process {
    id: directoryScanner
    command: ["find", "", "-type", "f", "\\(-iname", "*.jpg", "-o", "-iname", "*.jpeg", "-o", "-iname", "*.png", "-o", "-iname", "*.bmp", "-o", "-iname", "*.webp", "-o", "-iname", "*.svg", "\\)"]
    running: false
    stdout: StdioCollector {}
    stderr: StdioCollector {}
    onExited: function (exitCode) {
      if (exitCode === 0) {
        var lines = stdout.text.split('\n')
        var images = []
        for (var i = 0; i < lines.length; i++) {
          var line = lines[i].trim()
          if (line !== '') {
            images.push(line)
          }
        }
        wallpapersList = images
        updateFilteredWallpapers()
        if (wallpapersList.length > 0 && selectedWallpaper === "") {
          selectedWallpaper = wallpapersList[0]
        }
      }
    }
  }
}
