import QtQuick
import QtQuick.Controls
import QtQuick.Controls.impl
import QtQuick.Layouts
import ISC
import ISC.Tabs.components
import ISC.Wafer

// ===== Data Tab (Compare Content Only) =====
// Per docs/design/navigation-mock.html: the Data tab shows only the Compare
// Runs content — the raw CSV table ("Inspect Table" mode in earlier drafts)
// is intentionally not displayed in the application.
// Layout: left column = aligned-curves chart with alignment scrubber + wafer
// overlap map; right side panel = run selection dropdowns, overlap settings,
// and DTW readout cards.
Item {
    id: root
    anchors.fill: parent

    // Properties for DTW Comparison
    property int activeBox: 1 // 1 for Reference (Run A), 2 for Session (Run B), 0 for inactive
    property string compareFileA: ""
    property string compareFileB: ""
    property bool useMasterFile: false // Run A comes from settingsModel.masters[runBWaferType] instead of manual selection

    function waferTypeForFile(path) {
        if (!path) return ""
        // A file registered as a master carries that slot's family — this is
        // the only way a live recording gets a family (its filename/metadata
        // don't encode one reliably).
        for (var fam in settingsModel.masters)
            if (settingsModel.masters[fam] === path) return fam.toUpperCase()
        var rows = file_browser.files
        for (var i = 0; i < rows.length; i++) {
            if (rows[i].fileName === path) {
                if (rows[i].isRecording) return (rows[i].masterType || "").toUpperCase()
                return (rows[i].waferType || "").toUpperCase()
            }
        }
        var base = path.split("/").pop()
        if (base.toLowerCase().indexOf("live_") === 0) return ""
        return base ? base.charAt(0).toUpperCase() : ""
    }

    // Master file must match Run B's wafer family — looking it up by that
    // family is itself the comparability gate (a mismatched-family master
    // simply won't exist under this key).
    readonly property string runBWaferType: root.waferTypeForFile(root.compareFileB)
    readonly property string masterFileForRunB: root.runBWaferType !== "" ? (settingsModel.masters[root.runBWaferType] || "") : ""
    readonly property string runAWaferType: root.useMasterFile ? root.runBWaferType : root.waferTypeForFile(root.compareFileA)
    // Family gate: both runs must resolve to the same wafer family. An empty
    // family means an unassigned live recording — comparable only after it is
    // registered as a master file (Settings → Master Files).
    readonly property string familyGateError: {
        var fileA = root.useMasterFile ? root.masterFileForRunB : root.compareFileA
        if (fileA === "" || root.compareFileB === "") return ""
        if (root.runAWaferType === "" || root.runBWaferType === "")
            return "Recording has no wafer family — register it as a master file (Settings → Master Files)"
        if (root.runAWaferType !== root.runBWaferType)
            return "Wafer Family Mismatch: " + root.runAWaferType + " vs " + root.runBWaferType
        return ""
    }
    property real warpingDistance: -1
    property int frameOffset: 0
    property real frameOffsetSeconds: 0
    property real maxSensorDeviation: -1
    property bool comparing: false
    property var trendDataA: []
    property var trendDataB: []
    property var timeDataA: []
    property var timeDataB: []
    property int frameCountA: 0
    property int frameCountB: 0
    property string errorMessage: ""
    property string mismatchMessage: ""

    // Wafer overlap properties
    property var compareSensorLayout: []
    property var compareSensorDiff: []
    property string compareWaferShape: "round"
    property real compareWaferSize: 300.0

    readonly property bool hasSeries: trendDataA.length > 1 && trendDataB.length > 1
    readonly property int seriesLen: Math.max(trendDataA.length, trendDataB.length)

    function diffBands(diffs) {
        return diffs.map(d => d > 1.0 ? "high" : d < -1.0 ? "low" : "in_range")
    }

    function shortName(path) {
        return path ? path.split("/").pop() : ""
    }

    function scrubTimeLabel(idx) {
        var t = idx < root.timeDataA.length ? root.timeDataA[idx]
            : (idx < root.timeDataB.length ? root.timeDataB[idx] : null)
        return t !== null ? " (" + t.toFixed(1) + "s)" : ""
    }

    function formatMinutes(secondsValue) {
        var mins = Math.floor(secondsValue / 60)
        var secs = secondsValue % 60
        return mins + ":" + (secs < 10 ? "0" : "") + secs.toFixed(1)
    }

    function frameForTime(t) {
        var times = root.timeDataA.length > 0 ? root.timeDataA : root.timeDataB
        if (times.length === 0) return 0
        var closestIdx = 0
        var minDiff = Math.abs(times[0] - t)
        for (var i = 1; i < times.length; i++) {
            var diff = Math.abs(times[i] - t)
            if (diff < minDiff) {
                minDiff = diff
                closestIdx = i
            }
        }
        return closestIdx
    }

    function clearResults() {
        root.warpingDistance = -1
        root.frameOffset = 0
        root.frameOffsetSeconds = 0
        root.maxSensorDeviation = -1
        root.trendDataA = []
        root.trendDataB = []
        root.timeDataA = []
        root.timeDataB = []
        root.frameCountA = 0
        root.frameCountB = 0
        root.compareSensorLayout = []
        root.compareSensorDiff = []
        root.errorMessage = ""
        root.mismatchMessage = ""
        mismatchHideTimer.stop()
    }

    function resetComparison() {
        root.compareFileA = ""
        root.compareFileB = ""
        root.useMasterFile = false
        root.comparing = false
        root.activeBox = 1
        clearResults()
    }

    Component.onCompleted: file_browser.refreshFiles()

    Timer {
        id: mismatchHideTimer
        interval: 6000
        onTriggered: root.mismatchMessage = ""
    }

    // Clicking a file in the left rail's browser populates the armed run slot
    Connections {
        target: streamController
        function onLoadedFileChanged() {
            if (streamController.loadedFile && root.activeBox > 0) {
                if (root.activeBox === 1) {
                    root.compareFileA = streamController.loadedFile
                    root.activeBox = 2 // Auto-advance to box 2
                } else if (root.activeBox === 2) {
                    root.compareFileB = streamController.loadedFile
                    root.activeBox = 0 // Finished selecting
                }
            }
        }
        function onComparisonResult(result) {
            root.comparing = false
            if (result && result.success) {
                root.warpingDistance = result.distance
                root.frameOffset = result.frame_offset !== undefined ? result.frame_offset : 0
                root.frameOffsetSeconds = result.frame_offset_seconds !== undefined ? result.frame_offset_seconds : 0
                root.maxSensorDeviation = result.max_sensor_deviation !== undefined ? result.max_sensor_deviation : -1
                root.trendDataA = result.series_a || []
                root.trendDataB = result.series_b || []
                root.timeDataA = result.time_a || []
                root.timeDataB = result.time_b || []
                root.frameCountA = result.frame_count_a || 0
                root.frameCountB = result.frame_count_b || 0
                root.compareSensorLayout = result.sensor_layout || []
                root.compareSensorDiff = result.sensor_diff || []
                root.compareWaferShape = result.wafer_shape || "round"
                root.compareWaferSize = result.wafer_size || 300.0
                root.errorMessage = ""
                chartCard.frameIndex = Math.floor(root.seriesLen / 2)
                chartCard.focusScrubber()
                if (root.frameCountA !== root.frameCountB) {
                    var timeA = root.timeDataA.length > 0 ? root.timeDataA[root.timeDataA.length - 1] : 0
                    var timeB = root.timeDataB.length > 0 ? root.timeDataB[root.timeDataB.length - 1] : 0
                    root.mismatchMessage = "Run A: " + root.frameCountA + " frames (" + timeA.toFixed(1) + "s) · "
                        + "Run B: " + root.frameCountB + " frames (" + timeB.toFixed(1) + "s). "
                        + "Deviation beyond the shorter run shows as \"none\"."
                    mismatchHideTimer.restart()
                } else {
                    root.mismatchMessage = ""
                    mismatchHideTimer.stop()
                }
            } else {
                root.clearResults()
                root.errorMessage = (result && result.error) ? result.error : "Comparison failed"
            }
        }
    }

    // ── Main Layout ───────────────────────────────────────────────
    ColumnLayout {
        anchors.fill: parent
        anchors.margins: Theme.panelPadding
        spacing: Theme.rightPaneGap



        // ── Error Banner ───────────────────────────────────────────
        Rectangle {
            Layout.fillWidth: true
            Layout.preferredHeight: errorRow.implicitHeight + 16
            visible: root.errorMessage !== ""
            color: Theme.errorSurface
            border.color: Theme.statusErrorColor
            border.width: 1
            radius: Theme.radiusSm

            RowLayout {
                id: errorRow
                anchors.fill: parent
                anchors.margins: 8
                spacing: 8

                IconImage {
                    source: "icons/triangle-alert.svg"
                    width: 16; height: 16
                    sourceSize.width: 16
                    sourceSize.height: 16
                    color: Theme.errorTextSoft
                    Layout.alignment: Qt.AlignTop
                }

                Label {
                    id: errorLabel
                    text: root.errorMessage
                    color: Theme.errorTextSoft
                    font.pixelSize: Theme.fontSm
                    wrapMode: Text.WordWrap
                    Layout.fillWidth: true
                }
            }
        }

        // ── Body: main column | side panel ─────────────────────────
        RowLayout {
            Layout.fillWidth: true
            Layout.fillHeight: true
            spacing: 16

            // --- Left Column: chart + scrubber, wafer overlap map ---
            ColumnLayout {
                Layout.fillWidth: true
                Layout.fillHeight: true
                Layout.minimumWidth: 350
                spacing: 12

                // Wafer Map Overlap View card
                OverlapMapCard {
                    Layout.fillWidth: true
                    Layout.fillHeight: true
                    Layout.minimumHeight: 220
                    sensorLayout: root.compareSensorLayout
                    diffValues: streamController.getSensorDiffAt(Math.round(chartCard.frameIndex))
                    diffBands: root.diffBands
                    waferShape: root.compareWaferShape
                    waferSize: root.compareWaferSize
                    overlapEnabled: sidePanel.overlapEnabled
                    blendAmount: sidePanel.blendAmount
                }

                // Chart card with alignment scrubber
                ComparisonChartCard {
                    id: chartCard
                    Layout.fillWidth: true
                    trendDataA: root.trendDataA
                    trendDataB: root.trendDataB
                    seriesLen: root.seriesLen
                    hasSeries: root.hasSeries
                    comparing: root.comparing
                }
}

            // --- Right Column: run selection, overlap settings, readout ---
            ComparisonSidePanel {
                id: sidePanel
                Layout.fillWidth: false                
                Layout.preferredWidth: Theme.rightRailWidth
                Layout.minimumWidth: Theme.rightRailWidth
                Layout.maximumWidth: Theme.rightRailWidth
                Layout.fillHeight: true
                warpingDistance: root.warpingDistance
                frameOffset: root.frameOffset
                frameOffsetSeconds: root.frameOffsetSeconds
                maxSensorDeviation: root.maxSensorDeviation
                seriesLen: root.seriesLen
                hasSeries: root.hasSeries
                trendDataA: root.trendDataA
                trendDataB: root.trendDataB
                timeDataA: root.timeDataA
                timeDataB: root.timeDataB
                frameForTime: root.frameForTime
                frameIndex: chartCard.frameIndex
                onFrameIndexRequested: (idx) => chartCard.frameIndex = idx
                onScrubberFocusRequested: chartCard.focusScrubber()
            }
        }
    }

    // ── Frame Mismatch Banner (amber, floats over content, auto-hides) ──
    Rectangle {
        id: mismatchBanner
        visible: root.mismatchMessage !== ""
        z: 100
        anchors.top: parent.top
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.topMargin: 12
        width: Math.min(parent.width - 48, 640)
        height: mismatchRow.implicitHeight + 16
        color: Theme.cardBackground
        border.color: Theme.statusWarningColor
        border.width: 1
        radius: Theme.radiusSm

        RowLayout {
            id: mismatchRow
            anchors.fill: parent
            anchors.margins: 8
            spacing: 8

            IconImage {
                source: "icons/triangle-alert.svg"
                width: 16; height: 16
                sourceSize.width: 16
                sourceSize.height: 16
                color: Theme.statusWarningColor
                Layout.alignment: Qt.AlignTop
            }

            Label {
                text: root.mismatchMessage
                color: Theme.statusWarningColor
                font.pixelSize: Theme.fontSm
                wrapMode: Text.WordWrap
                Layout.fillWidth: true
            }

            Button {
                flat: true
                implicitWidth: 24
                implicitHeight: 24
                Layout.alignment: Qt.AlignTop
                onClicked: {
                    root.mismatchMessage = ""
                    mismatchHideTimer.stop()
                }
                background: Rectangle { color: "transparent" }
                contentItem: Label {
                    text: "✕"
                    color: Theme.statusWarningColor
                    font.pixelSize: Theme.fontXs
                    horizontalAlignment: Text.AlignHCenter
                    verticalAlignment: Text.AlignVCenter
                }
            }
        }
    }
}
