import QtQuick
import QtQuick.Effects
import QtQuick.Layouts
import Quickshell
import Quickshell.Services.Mpris
import Quickshell.Io
import qs.Common
import qs.Services
import qs.Widgets
import qs.Modules.Plugins

DesktopPluginComponent {
    id: root

    // settings data here
    property real backgroundOpacity: (pluginData.backgroundOpacity ?? 80) / 100
    property real borderOpacity: (pluginData.borderOpacity ?? 100) / 100

    LayoutMirroring.enabled: I18n.isRtl
    LayoutMirroring.childrenInherit: true

    opacity: showNoPlayerNow ? 0 : 1
    Behavior on opacity { NumberAnimation { duration: 300 } }

    property MprisPlayer activePlayer: MprisController.activePlayer
    property var allPlayers: MprisController.availablePlayers

    property bool isSwitching: false
    property string _lastArtUrl: ""
    property string _bgArtSource: ""

    property string activeTrackArtFile: ""

    function loadArtwork(url) {
        if (!url)
            return;
        if (url.startsWith("http://") || url.startsWith("https://")) {
            const filename = "/tmp/.dankshell/trackart_" + Date.now() + ".jpg";
            activeTrackArtFile = filename;

            cleanupProcess.command = ["sh", "-c", "mkdir -p /tmp/.dankshell && find /tmp/.dankshell -name 'trackart_*' ! -name '" + filename.split('/').pop() + "' -delete"];
            cleanupProcess.running = true;

            imageDownloader.command = ["curl", "-L", "-s", "--user-agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36", "-o", filename, url];
            imageDownloader.targetFile = filename;
            imageDownloader.running = true;
            return;
        }
        _bgArtSource = url;
    }

    function maybeFinishSwitch() {
        if (activePlayer && activePlayer.trackTitle !== "") {
            isSwitching = false;
            _switchHold = false;
            _stalePositionDetected = false;
        }
    }
    
    function getDisplayPosition() {
        if (!activePlayer) return 0;
        
        const rawPos = Math.max(0, activePlayer.position || 0);
        const length = Math.max(1, activePlayer.length || 1);
        
        // If we detected stale position, show 0 until proper data arrives
        if (_stalePositionDetected) {
            return 0;
        }
        
        // Handle stale position data when switching videos
        if (isSwitching && rawPos >= length * 0.9) {
            return 0;
        }
        
        const pos = activePlayer.length ? rawPos % Math.max(1, activePlayer.length) : rawPos;
        return pos;
    }
    
    function formatTime(seconds) {
        const minutes = Math.floor(seconds / 60);
        const secs = Math.floor(seconds % 60);
        return minutes + ":" + (secs < 10 ? "0" : "") + secs;
    }
    
    Component.onCompleted: {
        // Initialize with current player state if available
        if (activePlayer) {
            // Get actual position after MPRIS fully loads
            Qt.callLater(() => {
                try {
                    const actualPos = activePlayer.position || 0;
                    const length = activePlayer.length || 1;
                    root._positionSnapshot = actualPos;
                    if (progressSeekbar && actualPos > 0) {
                        progressSeekbar.value = Math.min(1, actualPos / length);
                    }
                } catch (e) {
                    // Handle MPRIS errors
                }
            });
        }
    }

    // Derived "no players" state: always correct, no timers.
    readonly property int _playerCount: allPlayers ? allPlayers.length : 0
    readonly property bool _noneAvailable: _playerCount === 0
    readonly property bool _trulyIdle: activePlayer && activePlayer.playbackState === MprisPlaybackState.Stopped && !activePlayer.trackTitle && !activePlayer.trackArtist
    readonly property bool showNoPlayerNow: (!_switchHold) && (_noneAvailable || _trulyIdle)

    property bool _switchHold: false
    Timer {
        id: _switchHoldTimer
        interval: 650
        repeat: false
        onTriggered: {
            _switchHold = false;
            if (isSwitching) {
                isSwitching = false;
            }
        }
    }

    onActivePlayerChanged: {
        root._positionSnapshot = 0;
        root._forceUpdate = !root._forceUpdate;
        if (!activePlayer) {
            isSwitching = false;
            _switchHold = false;
            return;
        }
        isSwitching = true;
        _switchHold = true;
        _switchHoldTimer.restart();
        if (activePlayer.trackArtUrl)
            loadArtwork(activePlayer.trackArtUrl);
        
        // Get actual current position after a short delay to allow MPRIS to sync
        Qt.callLater(() => {
            try {
                const actualPos = activePlayer.position || 0;
                root._positionSnapshot = actualPos;
                if (progressSeekbar && actualPos > 0) {
                    progressSeekbar.value = Math.min(1, actualPos / Math.max(1, activePlayer.length || 1));
                    isSwitching = false;
                }
            } catch (e) {
                // Handle errors gracefully
            }
        });
    }



    // Responsive sizing with min/max constraints
    property real userScale: 1.0
    readonly property real minWidth: 320
    readonly property real maxWidth: 800
    readonly property real minHeight: 160
    readonly property real maxHeight: 400
    readonly property real baseWidth: 380
    readonly property real baseHeight: 200

    implicitWidth: Math.max(minWidth, Math.min(maxWidth, baseWidth * userScale))
    implicitHeight: Math.max(minHeight, Math.min(maxHeight, baseHeight * userScale))

    Connections {
        target: activePlayer
        function onTrackTitleChanged() {
            root._positionSnapshot = 0;
            root._forceUpdate = !root._forceUpdate;
            // Force immediate position reset for new track
            if (activePlayer.position > 0 && activePlayer.length > 0) {
                const progressRatio = activePlayer.position / activePlayer.length;
                if (progressRatio > 0.9) {
                    // Likely stale data - force reset
                    root._stalePositionDetected = true;
                }
            }
            _switchHoldTimer.restart();
            maybeFinishSwitch();
            // Reset progress bar immediately on track change
            if (progressSeekbar) {
                progressSeekbar.value = 0;
            }
        }
        function onTrackArtUrlChanged() {
            if (activePlayer?.trackArtUrl) {
                _lastArtUrl = activePlayer.trackArtUrl;
                loadArtwork(activePlayer.trackArtUrl);
            }
        }
        function onPositionChanged() {
            try {
                if (root._stalePositionDetected && activePlayer.position < activePlayer.length * 0.5) {
                    // Position updated properly now
                    root._stalePositionDetected = false;
                    root._forceUpdate = !root._forceUpdate;
                }
            } catch (e) {
                // MPRIS service disappeared - reset state
                root._stalePositionDetected = false;
            }
        }
    }

    Connections {
        target: MprisController
        function onAvailablePlayersChanged() {
            const count = (MprisController.availablePlayers?.length || 0);
            if (count === 0) {
                isSwitching = false;
                _switchHold = false;
            } else {
                _switchHold = true;
                _switchHoldTimer.restart();
            }
        }
    }

    Process {
        id: imageDownloader
        running: false
        property string targetFile: ""

        onExited: exitCode => {
            if (exitCode === 0 && targetFile)
                _bgArtSource = "file://" + targetFile;
        }
    }

    Process {
        id: cleanupProcess
        running: false
    }



    property bool isSeeking: false
    property real _positionSnapshot: 0
    property bool _forceUpdate: false
    property real _animationTick: 0
    property bool _stalePositionDetected: false

    Timer {
        id: positionUpdateTimer
        interval: 100
        running: true
        repeat: true
        onTriggered: {
            // Update snapshot to trigger binding re-evaluation
            if (activePlayer) {
                try {
                    const newPosition = activePlayer.position || 0;
                    root._positionSnapshot = newPosition;
                    // Force progress bar refresh when switching
                    if (isSwitching || _stalePositionDetected) {
                        if (progressSeekbar) {
                            progressSeekbar.value = progressSeekbar.calculateProgress();
                        }
                    }
                } catch (e) {
                    // Handle MPRIS service errors gracefully
                    root._positionSnapshot = 0;
                }
            }
        }
    }

    // Use animation to drive constant updates for smooth progress bar
    NumberAnimation {
        id: progressUpdateAnimation
        target: root
        property: "_animationTick"
        from: 0
        to: 10000
        duration: 10000
        loops: Animation.Infinite
        running: activePlayer?.playbackState === MprisPlaybackState.Playing && !isSeeking
    }

    Item {
        id: bgContainer
        anchors.fill: parent
        visible: _bgArtSource !== ""

        Image {
            id: bgImage
            anchors.centerIn: parent
            width: Math.max(parent.width, parent.height) * 1.1
            height: width
            // source: _bgArtSource
            fillMode: Image.PreserveAspectCrop
            asynchronous: true
            cache: true
            visible: false
            onStatusChanged: {
                if (status === Image.Ready)
                    maybeFinishSwitch();
            }
        }

        Item {
            id: blurredBg
            anchors.fill: parent
            visible: false

            MultiEffect {
                anchors.centerIn: parent
                width: bgImage.width
                height: bgImage.height
                source: bgImage
                blurEnabled: true
                blurMax: 64
                blur: 2
                saturation: -0.2
                brightness: -0.25
            }
        }

        Rectangle {
            id: bgMask
            anchors.fill: parent
            radius: Theme.cornerRadius
            visible: false
            layer.enabled: true
        }

        MultiEffect {
            anchors.fill: parent
            source: blurredBg
            maskEnabled: true
            maskSource: bgMask
            maskThresholdMin: 0.5
            maskSpreadAtMin: 1.0
            opacity: 0.7
        }

        Rectangle {
            anchors.fill: parent
            radius: Theme.cornerRadius
            color: Theme.withAlpha(Theme.surface, root.backgroundOpacity)
        }
    }

    // --- Ocean Wave Background ---
    Canvas {
        id: waveCanvas
        anchors.fill: parent
        z: 1 // Ensures it stays behind the main content
        opacity: activePlayer && activePlayer.playbackState === MprisPlaybackState.Playing ? 0.4 : 0.1
        
        property real phase: 0
        
        // This timer drives the animation "movement"
        Timer {
            interval: 16 // ~60 FPS
            running: activePlayer && activePlayer.playbackState === MprisPlaybackState.Playing
            repeat: true
            onTriggered: {
                waveCanvas.phase += 0.05;
                waveCanvas.requestPaint();
            }
        }

        onPaint: {
            var ctx = getContext("2d");
            ctx.clearRect(0, 0, width, height);
            
            // Draw two overlapping waves for a "deep" ocean feel
            drawWave(ctx, "#40" + Theme.primary.toString().substring(1), 0.5, 15, phase);
            drawWave(ctx, "#60" + Theme.primary.toString().substring(1), 0.8, 10, phase * 0.7);
            drawWave(ctx, "#70" + Theme.primary.toString().substring(1), 0.8, 10, phase * 0.9);
        }

        function drawWave(ctx, color, speed, amplitude, currentPhase) {
            ctx.beginPath();
            ctx.fillStyle = color;
            
            var waveHeight = height * 0.7; // Position waves at the bottom 30%
            ctx.moveTo(0, height);
            
            for (var x = 0; x <= width; x += 5) {
                // Sine wave calculation: y = amplitude * sin(frequency * x + phase)
                var y = waveHeight + Math.sin(x * 0.02 + currentPhase) * amplitude;
                ctx.lineTo(x, y);
            }
            
            ctx.lineTo(width, height);
            ctx.closePath();
            ctx.fill();
        }
    }
    // --- End Ocean Wave Background ---

    Column {
        anchors.centerIn: parent
        spacing: Theme.spacingM
        visible: showNoPlayerNow

        DankIcon {
            name: "music_note"
            size: Theme.iconSize * 3
            color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5)
            anchors.horizontalCenter: parent.horizontalCenter
        }
    }

    // Main content container - Layout with thumbnail
    Item {
        anchors.fill: parent
        anchors.margins: Theme.spacingM * userScale
        visible: !_noneAvailable && (!showNoPlayerNow)

        Row {
            anchors.fill: parent
            spacing: Theme.spacingM * userScale

            // Album Thumbnail Section (Left)
            Rectangle {
                id: thumbnailContainer
                width: parent.height * 0.85
                height: parent.height * 0.85
                anchors.verticalCenter: parent.verticalCenter
                radius: 6 * userScale
                color: "transparent"
                clip: true

                property real albumRotation: 0

                NumberAnimation {
                    id: rotationAnimation
                    target: thumbnailContainer
                    property: "albumRotation"
                    from: 0
                    to: 360
                    duration: 20000
                    running: activePlayer?.playbackState === MprisPlaybackState.Playing
                    loops: Animation.Infinite
                }

                DankAlbumArt {
                    id: albumArt
                    width: parent.width * 0.76
                    height: parent.height * 0.76
                    anchors.centerIn: parent
                    activePlayer: root.activePlayer
                    rotation: thumbnailContainer.albumRotation
                }

                // Subtle border
                Rectangle {
                    anchors.fill: parent
                    radius: parent.radius
                    color: "transparent"
                    border.color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, root.borderOpacity)
                    border.width: 1
                }
            }

            // Content Section (Right)
            Column {
                width: parent.width - thumbnailContainer.width - parent.spacing
                height: parent.height
                spacing: Theme.spacingS * userScale

                // Song Info Section (Top)
                Column {
                    id: songInfo
                    width: parent.width
                    spacing: 2 * userScale

                    StyledText {
                        text: activePlayer?.trackTitle || "The (Overdue) Collapse of Wind..."
                        font.pixelSize: Theme.fontSizeMedium * 1.1 * userScale
                        font.weight: Font.Bold
                        color: Theme.surfaceText
                        width: parent.width
                        elide: Text.ElideRight
                        maximumLineCount: 1
                    }

                    StyledText {
                        text: activePlayer?.trackArtist || "Catalyst"
                        font.pixelSize: Theme.fontSizeSmall * userScale
                        color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6)
                        width: parent.width
                        elide: Text.ElideRight
                        maximumLineCount: 1
                    }
                }

                // Spacer
                Item {
                    width: parent.width
                    height: Theme.spacingXS * userScale
                }

                // Controls Row (Middle)
                Row {
                    id: controlsRow
                    width: parent.width
                    spacing: Theme.spacingS * userScale

                    // Previous Button
                    Rectangle {
                        width: 32 * userScale
                        height: 32 * userScale
                        radius: 4 * userScale
                        color: "transparent"
                        anchors.verticalCenter: parent.verticalCenter

                        DankIcon {
                            anchors.centerIn: parent
                            name: "skip_previous"
                            size: 28 * userScale
                            color: Theme.primary
                        }

                        MouseArea {
                            id: prevBtnArea
                            anchors.fill: parent
                            hoverEnabled: true
                            cursorShape: Qt.PointingHandCursor
                            onClicked: {
                                if (!activePlayer)
                                    return;
                                if (activePlayer.position > 8 && activePlayer.canSeek) {
                                    activePlayer.position = 0;
                                } else {
                                    activePlayer.previous();
                                }
                            }
                        }
                    }

                    // Play/Pause Button
                    Rectangle {
                        width: 32 * userScale
                        height: 32 * userScale
                        radius: 4 * userScale
                        color: "transparent"
                        anchors.verticalCenter: parent.verticalCenter

                        DankIcon {
                            anchors.centerIn: parent
                            name: activePlayer && activePlayer.playbackState === MprisPlaybackState.Playing ? "pause" : "play_arrow"
                            size: 28 * userScale
                            color: Theme.primary
                        }

                        MouseArea {
                            anchors.fill: parent
                            hoverEnabled: true
                            cursorShape: Qt.PointingHandCursor
                            onClicked: activePlayer && activePlayer.togglePlaying()
                        }
                    }

                    // Next Button
                    Rectangle {
                        width: 32 * userScale
                        height: 32 * userScale
                        radius: 4 * userScale
                        color: "transparent"
                        anchors.verticalCenter: parent.verticalCenter

                        DankIcon {
                            anchors.centerIn: parent
                            name: "skip_next"
                            size: 28 * userScale
                            color: Theme.primary
                        }

                        MouseArea {
                            id: nextBtnArea
                            anchors.fill: parent
                            hoverEnabled: true
                            cursorShape: Qt.PointingHandCursor
                            onClicked: activePlayer && activePlayer.next()
                        }
                    }

                    // Spacer to push buttons to right
                    Item {
                        width: parent.width - (32 * 3 * userScale) - (Theme.spacingS * 3 * userScale)
                        height: 1
                    }
                }

                // Seekbar Section (Bottom)
                Column {
                    id: seekbarSection
                    width: parent.width
                    spacing: 2 * userScale

                    // Integrated DankSeekbar
                    DankSeekbar {
                        id: progressSeekbar
                        width: parent.width
                        height: 16 * userScale // Consistent with previous design
                        activePlayer: root.activePlayer
                        
                        // Keep the Tab's seeking state in sync with the component
                        onIsSeekingChanged: root.isSeeking = isSeeking
                        
                        function calculateProgress() {
                            if (!root.activePlayer || root.activePlayer.length <= 0) return 0;
                            
                            const rawPos = Math.max(0, root.activePlayer.position || 0);
                            const length = Math.max(1, root.activePlayer.length || 1);
                            
                            // If we detected stale position, show 0 until proper data arrives
                            if (root._stalePositionDetected) {
                                // Check if position is now valid
                                if (rawPos < length * 0.8) {
                                    root._stalePositionDetected = false;
                                    root.isSwitching = false;
                                } else {
                                    return 0;
                                }
                            }
                            
                            // Reset if position seems stale (at end for new video)
                            if (root.isSwitching && rawPos >= length * 0.9) {
                                root._stalePositionDetected = true;
                                return 0;
                            }
                            
                            // Force position refresh when switching videos
                            if (root.isSwitching && rawPos > 0 && rawPos < length * 0.8) {
                                root.isSwitching = false;
                            }
                            
                            return Math.min(1, rawPos / length);
                        }

        // Connect position updates to seekbar value directly
                        Timer {
                            interval: 50
                            running: true
                            repeat: true
                            onTriggered: {
                                if (progressSeekbar && activePlayer) {
                                    try {
                                        progressSeekbar.value = progressSeekbar.calculateProgress();
                                    } catch (e) {
                                        // Handle MPRIS errors
                                    }
                                }
                            }
                        }
                    }

                    // Time labels
                    Item {
                        width: parent.width
                        height: 12 * userScale

                        StyledText {
                            anchors.left: parent.left
                            anchors.verticalCenter: parent.verticalCenter
                            text: {
                                // Force dependency on position updates
                                root._positionSnapshot;
                                return formatTime(getDisplayPosition());
                            }
                            font.pixelSize: Theme.fontSizeSmall * 0.9 * userScale
                            color: Theme.surfaceVariantText
                        }

                        StyledText {
                            anchors.right: parent.right
                            anchors.verticalCenter: parent.verticalCenter
                            text: {
                                if (!activePlayer || !activePlayer.length)
                                    return "0:00";
                                const dur = Math.max(0, activePlayer.length || 0);
                                const minutes = Math.floor(dur / 60);
                                const seconds = Math.floor(dur % 60);
                                return minutes + ":" + (seconds < 10 ? "0" : "") + seconds;
                            }
                            font.pixelSize: Theme.fontSizeSmall * 0.9 * userScale
                            color: Theme.surfaceVariantText
                        }
                    }
                }
            }
        }
    }


}
