const equipmentId = document.body.dataset.equipmentId;

const latestEndpoint =
    `/equipment/${encodeURIComponent(equipmentId)}/measurements/latest`;

const analysisEndpoint =
    `/equipment/${encodeURIComponent(equipmentId)}/analysis`;

const historyEndpoint =
    `/equipment/${encodeURIComponent(equipmentId)}/measurements/history`;


const profileEndpoint =
    `/equipment/${encodeURIComponent(equipmentId)}/profile`;

function formatProfileValue(value, unit, decimals = 2) {
    const number = Number(value);
    if (!Number.isFinite(number)) {
        return "—";
    }
    return `${number.toFixed(decimals)} ${unit}`;
}

async function refreshEquipmentProfile() {
    try {
        const response = await fetch(
            `${profileEndpoint}?t=${Date.now()}`,
            {cache: "no-store"}
        );

        if (!response.ok) {
            throw new Error(
                `Equipment profile HTTP ${response.status}`
            );
        }

        const profile = await response.json();

        setText("profile-status", "Profile available");
        setText(
            "profile-internal-temperature",
            formatProfileValue(
                profile.internal_temperature.mean,
                "°C"
            )
        );
        setText(
            "profile-compressor-temperature",
            formatProfileValue(
                profile.compressor_temperature.mean,
                "°C"
            )
        );
        setText(
            "profile-compressor-current",
            formatProfileValue(
                profile.compressor_current.mean,
                "A",
                3
            )
        );
        setText(
            "profile-evaporator-delta",
            formatProfileValue(
                profile.evaporator_delta.mean,
                "°C"
            )
        );
        setText(
            "profile-run-cycle",
            profile.cycle_profile.average_run_minutes === null
                ? "Not detected"
                : formatProfileValue(
                    profile.cycle_profile.average_run_minutes,
                    "min"
                )
        );
        setText(
            "profile-rest-cycle",
            profile.cycle_profile.average_rest_minutes === null
                ? "Not detected"
                : formatProfileValue(
                    profile.cycle_profile.average_rest_minutes,
                    "min"
                )
        );
        setText(
            "profile-sample-count",
            profile.sample_count
        );
    } catch (error) {
        console.error(error);
        setText("profile-status", "Learning");
    }
}


const brainHistoryEndpoint =
    `/equipment/${encodeURIComponent(equipmentId)}/brain/history`;

const brainTrendEndpoint =
    `/equipment/${encodeURIComponent(equipmentId)}/brain/trend`;


async function refreshBrainMemory() {
    try {
        const response = await fetch(
            `${brainTrendEndpoint}?limit=500&t=${Date.now()}`,
            {
                cache: "no-store",
            }
        );

        if (!response.ok) {
            throw new Error(
                `Brain trend HTTP ${response.status}`
            );
        }

        const trend = await response.json();

        setText(
            "brain-memory-count",
            trend.sample_count
        );

        setText(
            "brain-memory-first",
            trend.first_health_score === undefined
                ? "—"
                : `${Number(
                    trend.first_health_score
                ).toFixed(1)}%`
        );

        setText(
            "brain-memory-current",
            trend.latest_health_score === undefined
                ? "—"
                : `${Number(
                    trend.latest_health_score
                ).toFixed(1)}%`
        );

        setText(
            "brain-memory-change",
            trend.health_change === undefined
                ? "—"
                : `${Number(
                    trend.health_change
                ).toFixed(1)} points`
        );

        setText(
            "brain-memory-trend",
            trend.trend.replaceAll("_", " ")
        );
    } catch (error) {
        console.error(error);
        setText(
            "brain-memory-trend",
            "Unavailable"
        );
    }
}

let historyLimit = 720;
let temperatureChart = null;


function formatNumber(value, decimals = 2) {
    const number = Number(value);

    if (!Number.isFinite(number)) {
        return "—";
    }

    return number.toFixed(decimals);
}


function formatTimestamp(timestamp) {
    if (!timestamp) {
        return "—";
    }

    const normalized = timestamp.includes("T")
        ? timestamp
        : `${timestamp.replace(" ", "T")}Z`;

    const date = new Date(normalized);

    if (Number.isNaN(date.getTime())) {
        return timestamp;
    }

    return new Intl.DateTimeFormat("en-GB", {
        day: "2-digit",
        month: "2-digit",
        hour: "2-digit",
        minute: "2-digit",
        second: "2-digit",
    }).format(date);
}


function setText(id, value) {
    const element = document.getElementById(id);

    if (element) {
        element.textContent = value;
    }
}


function applyHealthStatus(status) {
    const badge = document.getElementById("health-state");
    const ring = document.getElementById("health-ring");

    if (!badge || !ring) {
        return;
    }

    badge.classList.remove(
        "health-good",
        "health-monitoring",
        "health-warning",
        "health-critical"
    );

    if (status === "EXCELLENT") {
        badge.classList.add("health-good");
        ring.style.setProperty("--health-color", "#57dfa3");
        return;
    }

    if (
        status === "SURVEILLANCE"
        || status === "MONITORING"
    ) {
        badge.classList.add("health-monitoring");
        ring.style.setProperty("--health-color", "#f0d45d");
        return;
    }

    if (
        status === "ATTENTION"
        || status === "WARNING"
    ) {
        badge.classList.add("health-warning");
        ring.style.setProperty("--health-color", "#ff9d66");
        return;
    }

    badge.classList.add("health-critical");
    ring.style.setProperty("--health-color", "#ff657d");
}


function findingSymbol(severity) {
    if (severity === "INFO") {
        return "✓";
    }

    if (severity === "LOW") {
        return "i";
    }

    if (severity === "MEDIUM") {
        return "!";
    }

    if (severity === "HIGH") {
        return "!!";
    }

    return "×";
}


function updateFindings(findings) {
    const grid = document.getElementById("findings-grid");

    if (!grid) {
        return;
    }

    setText(
        "findings-count",
        `${findings.length} findings`
    );

    grid.innerHTML = "";

    findings.forEach(finding => {
        const card = document.createElement("article");

        card.className =
            `finding-card finding-${finding.severity.toLowerCase()}`;

        const title = finding.code.replaceAll("_", " ");

        card.innerHTML = `
            <div class="finding-top">
                <span class="finding-icon">
                    ${findingSymbol(finding.severity)}
                </span>

                <span class="finding-severity">
                    ${finding.severity}
                </span>
            </div>

            <h3>${title}</h3>
            <p>${finding.explanation}</p>

            <div class="finding-values">
                <div>
                    <span>Value</span>

                    <strong>
                        ${formatNumber(finding.value, 4)}
                        ${finding.unit}
                    </strong>
                </div>

                <div>
                    <span>Confidence</span>

                    <strong>
                        ${Math.round(finding.confidence)}%
                    </strong>
                </div>
            </div>
        `;

        grid.appendChild(card);
    });
}


function updateSubsystemScore(
    scoreId,
    labelId,
    value
) {
    if (value === null || value === undefined) {
        setText(scoreId, "—");
        setText(labelId, "Not evaluated");
        return;
    }

    setText(
        scoreId,
        Math.round(Number(value))
    );

    setText(labelId, "%");
}


async function refreshLatestMeasurement() {
    try {
        const response = await fetch(
            `${latestEndpoint}?t=${Date.now()}`,
            {
                cache: "no-store",
            }
        );

        if (!response.ok) {
            throw new Error(
                `Latest measurement HTTP ${response.status}`
            );
        }

        const measurement = await response.json();

        setText(
            "internal-temperature",
            formatNumber(
                measurement.internal_temperature_c
            )
        );

        setText(
            "ambient-temperature",
            formatNumber(
                measurement.ambient_temperature_c
            )
        );

        setText(
            "evaporator-temperature",
            formatNumber(
                measurement.evaporator_temperature_c
            )
        );

        setText(
            "compressor-temperature",
            formatNumber(
                measurement.compressor_temperature_c
            )
        );

        setText(
            "compressor-current",
            formatNumber(
                measurement.compressor_current_a,
                3
            )
        );

        setText(
            "recorded-at",
            formatTimestamp(measurement.recorded_at)
        );

        setText(
            "measurement-id",
            `#${measurement.id}`
        );

        setText(
            "device-id",
            measurement.device_id
        );

        setText(
            "equipment-id",
            measurement.equipment_id
        );

        setText(
            "connection-status",
            "Receiving data"
        );
    } catch (error) {
        console.error(error);

        setText(
            "connection-status",
            "Connection lost"
        );
    }
}


async function refreshBrainAnalysis() {
    try {
        const response = await fetch(
            `${analysisEndpoint}?t=${Date.now()}`,
            {
                cache: "no-store",
            }
        );

        if (!response.ok) {
            throw new Error(
                `Brain analysis HTTP ${response.status}`
            );
        }

        const analysis = await response.json();

        const roundedScore = Math.round(
            Number(analysis.health_score)
        );

        setText("health-score", roundedScore);
        setText("health-state", analysis.status);
        setText("health-summary", analysis.status);
        setText("brain-analysis", analysis.analysis);

        setText(
            "brain-recommendation",
            analysis.recommendation
        );

        setText(
            "brain-confidence",
            Math.round(
                Number(analysis.confidence)
            )
        );


        setText(
            "root-cause",
            analysis.root_cause ?? "Not available"
        );

        setText(
            "root-cause-code",
            analysis.root_cause_code ?? "NOT_AVAILABLE"
        );

        setText(
            "root-cause-explanation",
            analysis.root_cause_explanation
                ?? "No root-cause explanation available."
        );

        setText(
            "root-cause-confidence",
            analysis.root_cause_confidence === null
                || analysis.root_cause_confidence === undefined
                ? "—"
                : Math.round(
                    Number(analysis.root_cause_confidence)
                )
        );

        setText(
            "prediction-horizon",
            analysis.prediction_horizon_days
                ? `${analysis.prediction_horizon_days} days`
                : "Not available yet"
        );

        const ring = document.getElementById(
            "health-ring"
        );

        ring?.style.setProperty(
            "--score",
            roundedScore
        );

        applyHealthStatus(analysis.status);

        updateSubsystemScore(
            "thermal-score",
            "thermal-score-label",
            analysis.thermal_score
        );

        updateSubsystemScore(
            "electrical-score",
            "electrical-score-label",
            analysis.electrical_score
        );

        updateSubsystemScore(
            "cooling-score",
            "cooling-score-label",
            analysis.cooling_score
        );

        updateSubsystemScore(
            "sensor-score",
            "sensor-score-label",
            analysis.sensor_score
        );

        updateFindings(analysis.findings ?? []);
    } catch (error) {
        console.error(error);

        setText(
            "brain-analysis",
            "Sentinel Brain analysis unavailable."
        );
    }
}


function buildDatasets(history) {
    return [
        {
            label: "Internal",
            data: history.map(
                item => item.internal_temperature_c
            ),
            borderColor: "#63dbff",
            backgroundColor:
                "rgba(99, 219, 255, 0.10)",
            pointRadius: 0,
            pointHoverRadius: 5,
            borderWidth: 2.2,
            tension: 0.22,
        },
        {
            label: "Evaporator",
            data: history.map(
                item => item.evaporator_temperature_c
            ),
            borderColor: "#8d8eff",
            backgroundColor:
                "rgba(141, 142, 255, 0.09)",
            pointRadius: 0,
            pointHoverRadius: 5,
            borderWidth: 1.8,
            tension: 0.22,
        },
        {
            label: "Compressor",
            data: history.map(
                item => item.compressor_temperature_c
            ),
            borderColor: "#ff9d66",
            backgroundColor:
                "rgba(255, 157, 102, 0.09)",
            pointRadius: 0,
            pointHoverRadius: 5,
            borderWidth: 1.8,
            tension: 0.22,
        },
        {
            label: "Ambient",
            data: history.map(
                item => item.ambient_temperature_c
            ),
            borderColor: "#57dfa3",
            backgroundColor:
                "rgba(87, 223, 163, 0.09)",
            pointRadius: 0,
            pointHoverRadius: 5,
            borderWidth: 1.6,
            tension: 0.22,
        },
    ];
}


function createTemperatureChart(history) {
    const canvas = document.getElementById(
        "temperature-chart"
    );

    if (!canvas) {
        return;
    }

    temperatureChart = new Chart(canvas, {
        type: "line",

        data: {
            labels: history.map(
                item => formatTimestamp(
                    item.recorded_at
                )
            ),

            datasets: buildDatasets(history),
        },

        options: {
            responsive: true,
            maintainAspectRatio: false,
            animation: false,
            normalized: true,

            interaction: {
                mode: "index",
                intersect: false,
                axis: "x",
            },

            plugins: {
                legend: {
                    position: "top",
                    align: "end",

                    labels: {
                        color: "#b9cad9",
                        usePointStyle: true,
                        boxWidth: 8,
                        padding: 17,
                    },
                },

                tooltip: {
                    enabled: true,
                    mode: "index",
                    intersect: false,

                    backgroundColor:
                        "rgba(3, 15, 27, 0.97)",

                    borderColor:
                        "rgba(99, 219, 255, 0.33)",

                    borderWidth: 1,
                    titleColor: "#ffffff",
                    bodyColor: "#d6e6f3",
                    padding: 13,

                    callbacks: {
                        label(context) {
                            return (
                                `${context.dataset.label}: `
                                + `${formatNumber(context.raw)} °C`
                            );
                        },
                    },
                },

                zoom: {
                    pan: {
                        enabled: true,
                        mode: "x",
                    },

                    zoom: {
                        wheel: {
                            enabled: true,
                            speed: 0.08,
                        },

                        pinch: {
                            enabled: true,
                        },

                        drag: {
                            enabled: true,

                            backgroundColor:
                                "rgba(99, 219, 255, 0.10)",

                            borderColor:
                                "rgba(99, 219, 255, 0.52)",

                            borderWidth: 1,
                        },

                        mode: "x",
                    },

                    limits: {
                        x: {
                            minRange: 10,
                        },
                    },
                },
            },

            scales: {
                x: {
                    grid: {
                        color:
                            "rgba(151, 181, 210, 0.07)",
                    },

                    ticks: {
                        color: "#71879a",
                        maxTicksLimit: 9,
                        maxRotation: 0,
                    },
                },

                y: {
                    grid: {
                        color:
                            "rgba(151, 181, 210, 0.08)",
                    },

                    ticks: {
                        color: "#71879a",

                        callback(value) {
                            return `${value} °C`;
                        },
                    },
                },
            },
        },
    });
}


async function refreshHistory() {
    try {
        const response = await fetch(
            `${historyEndpoint}?limit=${historyLimit}`
            + `&t=${Date.now()}`,
            {
                cache: "no-store",
            }
        );

        if (!response.ok) {
            throw new Error(
                `History HTTP ${response.status}`
            );
        }

        const history = await response.json();

        if (!temperatureChart) {
            createTemperatureChart(history);
            return;
        }

        const zoomed =
            temperatureChart.getZoomLevel
            && temperatureChart.getZoomLevel() > 1;

        temperatureChart.data.labels = history.map(
            item => formatTimestamp(item.recorded_at)
        );

        temperatureChart.data.datasets =
            buildDatasets(history);

        temperatureChart.update("none");

        if (!zoomed) {
            temperatureChart.resetZoom();
        }
    } catch (error) {
        console.error(error);
    }
}


document
    .querySelectorAll(".period-button")
    .forEach(button => {
        button.addEventListener(
            "click",
            async () => {
                document
                    .querySelectorAll(".period-button")
                    .forEach(item => {
                        item.classList.remove("active");
                    });

                button.classList.add("active");

                historyLimit = Number(
                    button.dataset.limit
                );

                temperatureChart?.resetZoom();

                await refreshHistory();
            }
        );
    });


document
    .getElementById("reset-zoom")
    ?.addEventListener(
        "click",
        () => {
            temperatureChart?.resetZoom();
        }
    );


document
    .getElementById("fullscreen-chart")
    ?.addEventListener(
        "click",
        async () => {
            const panel = document.getElementById(
                "chart-panel"
            );

            if (!document.fullscreenElement) {
                await panel.requestFullscreen();
            } else {
                await document.exitFullscreen();
            }
        }
    );


document.addEventListener(
    "fullscreenchange",
    () => {
        window.setTimeout(
            () => temperatureChart?.resize(),
            150
        );
    }
);


refreshLatestMeasurement();
refreshBrainAnalysis();
refreshBrainMemory();
refreshEquipmentProfile();
refreshHistory();

window.setInterval(
    refreshLatestMeasurement,
    5000
);

window.setInterval(
    refreshBrainAnalysis,
    5000
);

window.setInterval(
    refreshHistory,
    15000
);
