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

Item {
  id: root

  property string title: ""
  property string description: ""
  property string icon: ""
  property string type: "notice"
  property int duration: 3000
  property string actionLabel: ""
  property var actionCallback: null
  readonly property real initialScale: 0.7

  signal hidden

  readonly property bool isCompact: Settings.data.notifications?.density === "compact"
  readonly property int notificationWidth: Math.round((isCompact ? 320 : 440) * Style.uiScaleRatio)
  readonly property int shadowPadding: Style.shadowBlurMax + Style.marginL

  width: notificationWidth + shadowPadding * 2
  height: Math.round(contentLayout.implicitHeight + Style.margin2M * 2 + shadowPadding * 2)
  visible: true
  opacity: 0
  scale: initialScale

  property real progress: 1.0
  property bool isHovered: false
  property real swipeOffset: 0
  property real swipeOffsetY: 0
  property real pressGlobalX: 0
  property real pressGlobalY: 0
  property bool isSwiping: false
  readonly property string location: Settings.data.notifications?.location || "top_right"
  readonly property bool isLeft: location.endsWith("_left")
  readonly property bool isRight: location.endsWith("_right")
  readonly property bool useVerticalSwipe: location === "bottom" || location === "top"
  readonly property real swipeStartThreshold: Math.round(18 * Style.uiScaleRatio)
  readonly property real swipeDismissThreshold: Math.max(110, background.width * 0.32)
  readonly property real verticalSwipeDismissThreshold: Math.max(70, background.height * 0.35)

  transform: Translate {
    x: root.swipeOffset
    y: root.swipeOffsetY
  }

  function clampSwipeDelta(deltaX) {
    if (isRight)
      return Math.max(0, deltaX);
    if (isLeft)
      return Math.min(0, deltaX);
    return deltaX;
  }

  function clampVerticalSwipeDelta(deltaY) {
    if (location === "bottom")
      return Math.max(0, deltaY);
    if (location === "top")
      return Math.min(0, deltaY);
    return deltaY;
  }

  HoverHandler {
    onHoveredChanged: {
      isHovered = hovered;
      if (isHovered) {
        resumeTimer.stop();
        if (progressAnimation.running && !progressAnimation.paused) {
          progressAnimation.pause();
        }
      } else {
        resumeTimer.start();
      }
    }
  }

  Timer {
    id: resumeTimer
    interval: 50
    repeat: false
    onTriggered: {
      if (!isHovered && progressAnimation.paused) {
        progressAnimation.resume();
      }
    }
  }

  // Background rectangle (apply shadows here)
  Rectangle {
    id: background
    anchors.fill: parent
    anchors.margins: shadowPadding
    radius: Style.radiusL
    color: Qt.alpha(Color.mSurface, Color.adaptiveOpacity(Settings.data.notifications.backgroundOpacity) || 1.0)

    // Colored border based on type
    border.width: Style.borderS
    border.color: {
      var baseColor;
      switch (root.type) {
      case "error":
        baseColor = Color.mError;
        break;
      default:
        baseColor = Color.mOutline;
        break;
      }
      return Qt.alpha(baseColor, Color.adaptiveOpacity(Settings.data.notifications.backgroundOpacity) || 1.0);
    }

    // Progress bar
    Rectangle {
      anchors.top: parent.top
      anchors.left: parent.left
      anchors.right: parent.right
      height: 2
      color: "transparent"

      Rectangle {
        id: progressBar
        readonly property real progressWidth: background.width - (2 * background.radius)
        height: parent.height
        // Mirrored logic: centers the bar as it shrinks
        x: background.radius + (progressWidth * (1 - root.progress)) / 2
        width: progressWidth * root.progress

        color: {
          var baseColor;
          switch (root.type) {
          case "warning":
            baseColor = Color.mPrimary;
            break;
          case "error":
            baseColor = Color.mError;
            break;
          default:
            baseColor = Color.mPrimary; // Match standard notification color
            break;
          }
          return Qt.alpha(baseColor, Color.adaptiveOpacity(Settings.data.notifications.backgroundOpacity) || 1.0);
        }
      }
    }
  }

  NDropShadow {
    anchors.fill: background
    source: background
    autoPaddingEnabled: true
  }

  NumberAnimation {
    id: progressAnimation
    target: root
    property: "progress"
    from: 1.0
    to: 0.0
    duration: root.duration
    easing.type: Easing.Linear
    onFinished: {
      if (root.progress === 0.0 && root.visible) {
        root.hide();
      }
    }
  }

  // Timer: hideTimer removed, using progressAnimation

  Behavior on opacity {
    NumberAnimation {
      duration: Style.animationNormal
      easing.type: Easing.OutCubic
    }
  }

  Behavior on scale {
    NumberAnimation {
      duration: Style.animationNormal
      easing.type: Easing.OutCubic
    }
  }

  Behavior on swipeOffset {
    enabled: !root.isSwiping
    NumberAnimation {
      duration: Style.animationFast
      easing.type: Easing.OutCubic
    }
  }

  Behavior on swipeOffsetY {
    enabled: !root.isSwiping
    NumberAnimation {
      duration: Style.animationFast
      easing.type: Easing.OutCubic
    }
  }

  Timer {
    id: hideAnimation
    interval: Style.animationFast
    onTriggered: {
      root.visible = false;
      root.hidden();
    }
  }

  // Cleanup on destruction
  Component.onDestruction: {
    progressAnimation.stop();
    hideAnimation.stop();
  }

  // Click anywhere dismiss the toast (must be before content so action link can override)
  MouseArea {
    id: toastDragArea
    anchors.fill: background
    acceptedButtons: Qt.LeftButton
    hoverEnabled: true
    onPressed: mouse => {
                 const globalPoint = toastDragArea.mapToGlobal(mouse.x, mouse.y);
                 root.pressGlobalX = globalPoint.x;
                 root.pressGlobalY = globalPoint.y;
                 root.isSwiping = false;
               }
    onPositionChanged: mouse => {
                         if (!(mouse.buttons & Qt.LeftButton))
                         return;
                         const globalPoint = toastDragArea.mapToGlobal(mouse.x, mouse.y);
                         const rawDeltaX = globalPoint.x - root.pressGlobalX;
                         const rawDeltaY = globalPoint.y - root.pressGlobalY;
                         const deltaX = root.clampSwipeDelta(rawDeltaX);
                         const deltaY = root.clampVerticalSwipeDelta(rawDeltaY);
                         if (!root.isSwiping) {
                           if (root.useVerticalSwipe) {
                             if (Math.abs(deltaY) < root.swipeStartThreshold)
                             return;
                             root.isSwiping = true;
                           } else {
                             if (Math.abs(deltaX) < root.swipeStartThreshold)
                             return;
                             root.isSwiping = true;
                           }
                         }
                         if (root.useVerticalSwipe) {
                           root.swipeOffset = 0;
                           root.swipeOffsetY = deltaY;
                         } else {
                           root.swipeOffset = deltaX;
                           root.swipeOffsetY = 0;
                         }
                       }
    onReleased: mouse => {
                  if (mouse.button !== Qt.LeftButton)
                  return;
                  if (root.isSwiping) {
                    root.isSwiping = false;
                    const dismissDistance = root.useVerticalSwipe ? Math.abs(root.swipeOffsetY) : Math.abs(root.swipeOffset);
                    const threshold = root.useVerticalSwipe ? root.verticalSwipeDismissThreshold : root.swipeDismissThreshold;
                    if (dismissDistance >= threshold) {
                      root.hide();
                    } else {
                      root.swipeOffset = 0;
                      root.swipeOffsetY = 0;
                    }
                    return;
                  }
                  root.hide();
                }
    onCanceled: {
      root.isSwiping = false;
      root.swipeOffset = 0;
      root.swipeOffsetY = 0;
    }
    cursorShape: Qt.PointingHandCursor
  }

  RowLayout {
    id: contentLayout
    anchors.fill: background
    anchors.topMargin: isCompact ? Style.marginS : Style.marginM
    anchors.bottomMargin: isCompact ? Style.marginS : Style.marginM
    anchors.leftMargin: isCompact ? Style.marginM : Style.margin2M
    anchors.rightMargin: isCompact ? Style.marginM : Style.margin2M
    spacing: isCompact ? Style.marginM : Style.marginL

    // Icon
    NIcon {
      icon: if (root.icon !== "") {
              return root.icon;
            } else if (type === "warning") {
              return "toast-warning";
            } else if (type === "error") {
              return "toast-error";
            } else {
              return "toast-notice";
            }
      color: {
        switch (type) {
        case "warning":
          return Color.mPrimary;
        case "error":
          return Color.mError;
        default:
          return Color.mOnSurface;
        }
      }
      pointSize: isCompact ? Style.fontSizeXL : Style.fontSizeXXL * 1.5
      Layout.alignment: Qt.AlignVCenter
    }

    // Label and description
    ColumnLayout {
      spacing: Style.marginXXS
      Layout.fillWidth: true
      Layout.alignment: Qt.AlignVCenter

      NText {
        Layout.fillWidth: true
        text: root.title
        color: Color.mOnSurface
        pointSize: isCompact ? Style.fontSizeM : Style.fontSizeL
        font.weight: Style.fontWeightBold
        wrapMode: Text.WordWrap
        visible: text.length > 0
      }

      NText {
        Layout.fillWidth: true
        text: root.description
        color: Color.mOnSurface
        pointSize: isCompact ? Style.fontSizeS : Style.fontSizeM
        wrapMode: Text.WordWrap
        maximumLineCount: isCompact ? 2 : 20
        elide: isCompact ? Text.ElideRight : Text.ElideNone
        visible: text.length > 0
      }

      // Action button
      NButton {
        text: root.actionLabel
        visible: root.actionLabel.length > 0 && root.actionCallback !== null
        Layout.topMargin: Style.marginXS
        fontSize: Style.fontSizeS
        backgroundColor: Color.mPrimary
        textColor: hovered ? Color.mOnHover : Color.mOnPrimary
        hoverColor: Color.mHover
        outlined: false
        implicitHeight: 24

        onClicked: {
          if (root.actionCallback) {
            root.actionCallback();
            root.hide();
          }
        }
      }
    }
  }

  function show(msgTitle, msgDescription, msgIcon, msgType, msgDuration, msgActionLabel, msgActionCallback) {
    // Stop all timers first
    progressAnimation.stop();
    hideAnimation.stop();

    title = msgTitle;
    description = msgDescription || "";
    icon = msgIcon || "";
    type = msgType || "notice";
    duration = msgDuration || 3000;
    actionLabel = msgActionLabel || "";
    actionCallback = msgActionCallback || null;

    visible = true;
    opacity = 1.0;
    scale = 1.0;
    progress = 1.0;
    isHovered = false;
    isSwiping = false;
    swipeOffset = 0;
    swipeOffsetY = 0;

    // Configure and start animation
    progressAnimation.duration = duration;
    progressAnimation.from = 1.0;
    progressAnimation.to = 0.0;
    progressAnimation.restart();
  }

  function hide() {
    progressAnimation.stop();
    isSwiping = false;
    swipeOffset = 0;
    swipeOffsetY = 0;
    opacity = 0;
    scale = initialScale;
    hideAnimation.restart();
  }

  function hideImmediately() {
    hideAnimation.stop();
    progressAnimation.stop();
    isSwiping = false;
    swipeOffset = 0;
    swipeOffsetY = 0;
    opacity = 0;
    scale = initialScale;
    root.hidden();
  }
}
