document.addEventListener('DOMContentLoaded', () => {
    const socket = io();
    const BASE_TITLE = '机器人控制中枢';

    const listenButton = document.getElementById('listenButton');
    const listenStatus = document.getElementById('listenStatus');
    const startButton = document.getElementById('startButton');
    const stopButton = document.getElementById('stopButton');
    const recordingStatus = document.getElementById('recordingStatus');
    const frequencyCanvas = document.getElementById('frequencyChart');

    const cameraStream = document.getElementById('cameraStream');
    const cameraReload = document.getElementById('cameraReload');
    const cameraStart = document.getElementById('cameraStart');
    const cameraStop = document.getElementById('cameraStop');
    const cameraPlaceholder = document.getElementById('cameraPlaceholder');
    const cameraStatus = document.getElementById('cameraStatus');

    const driverStatus = document.getElementById('driverStatus');
    const driverSpeed = document.getElementById('driver-speed');
    const driverSpeedVal = document.getElementById('driver-speed-val');
    const driverForward = document.getElementById('driver-forward');
    const driverBack = document.getElementById('driver-back');
    const driverLeft = document.getElementById('driver-left');
    const driverRight = document.getElementById('driver-right');
    const driverStop = document.getElementById('driver-stop');

    const knockStatus = document.getElementById('knockStatus');

    const sliderStatus = document.getElementById('sliderStatus');
    const sliderPosition = document.getElementById('sliderPosition');
    const sliderCalibrate = document.getElementById('sliderCalibrate');
    const sliderGoZero = document.getElementById('sliderGoZero');
    const sliderTarget = document.getElementById('sliderTarget');
    const sliderGoAbs = document.getElementById('sliderGoAbs');

    let isListening = false;
    let chartPoints = [];
    const MAX_WINDOW_SECONDS = 20;

    const setPill = (el, text, mode = 'ok') => {
        if (!el) return;
        el.textContent = text;
        el.classList.remove('alert', 'warn');
        if (mode === 'error') {
            el.classList.add('alert');
        } else if (mode === 'warn') {
            el.classList.add('warn');
        }
    };

    const fetchJson = async (url, options = {}) => {
        const opts = { ...options };
        if (opts.body && !(opts.body instanceof FormData)) {
            opts.headers = { 'Content-Type': 'application/json', ...(opts.headers || {}) };
            opts.body = JSON.stringify(opts.body);
        }
        const res = await fetch(url, opts);
        let data = {};
        try {
            data = await res.json();
        } catch (err) {
            data = {};
        }
        if (!res.ok) {
            const msg = data?.message || data?.error || `HTTP ${res.status}`;
            throw new Error(msg);
        }
        if (data && Object.prototype.hasOwnProperty.call(data, 'ok') && data.ok === false) {
            throw new Error(data.error || data.message || '操作失败');
        }
        if (data && data.status === 'error') {
            throw new Error(data.message || '操作失败');
        }
        return data;
    };

    const ctx = frequencyCanvas?.getContext('2d');
    const chart = frequencyCanvas ? new Chart(ctx, {
        type: 'line',
        data: {
            datasets: [{
                label: '主频率 (Hz)',
                data: [],
                borderColor: 'rgb(75, 192, 192)',
                borderWidth: 2,
                pointRadius: 0,
                fill: false,
            }],
        },
        options: {
            animation: false,
            responsive: true,
            scales: {
                x: {
                    type: 'linear',
                    title: { display: true, text: '工作时间 (秒)' },
                    ticks: { maxTicksLimit: 10 },
                },
                y: {
                    beginAtZero: true,
                    suggestedMax: 5000,
                    title: { display: true, text: '频率 (Hz)' },
                },
            },
            plugins: {
                legend: { display: false },
            },
        },
    }) : null;

    const updateFrequencyChart = (point) => {
        if (!chart || !point) return;
        chartPoints.push(point);
        const cutoff = point.time - MAX_WINDOW_SECONDS;
        chartPoints = chartPoints.filter((p) => p.time >= cutoff);
        chart.data.datasets[0].data = chartPoints.map((p) => ({ x: Number(p.time.toFixed(2)), y: Number(p.frequency.toFixed(2)) }));
        chart.update('none');
    };

    const applyListenUI = (listening) => {
        isListening = listening;
        if (listenButton) {
            listenButton.textContent = listening ? '停止实时监听' : '开始实时监听';
        }
    };

    const refreshDriverHealth = async () => {
        try {
            const data = await fetchJson('/driver/health');
            if (data.rosmaster_ready) {
                setPill(driverStatus, '底盘在线');
            } else {
                setPill(driverStatus, `初始化失败: ${data.error || '未知错误'}`, 'warn');
            }
        } catch (err) {
            setPill(driverStatus, `健康检查失败: ${err.message}`, 'error');
        }
    };

    const driverCommand = async (direction) => {
        try {
            const payload = await fetchJson('/driver/move', {
                method: 'POST',
                body: { dir: direction, speed: Number(driverSpeed?.value ?? 70) },
            });
            const speed = payload.speed ?? driverSpeed?.value;
            setPill(driverStatus, `执行 ${payload.dir || direction} @ ${speed}%`);
        } catch (err) {
            setPill(driverStatus, `指令失败: ${err.message}`, 'error');
        }
    };

    const updateSliderReadout = (data, hint) => {
        if (!data) return;
        const cm = Number(data.working_position_cm ?? 0);
        const delay = Number(data.current_speed_delay ?? 0);
        if (sliderPosition) {
            sliderPosition.textContent = cm.toFixed(2);
        }
        const base = `位置: ${cm.toFixed(2)} cm · 延时 ${delay.toFixed(4)}s`;
        const message = hint ? `${hint} · ${base}` : base;
        setPill(sliderStatus, message);
    };

    const fetchSliderStatus = async (hint) => {
        try {
            const data = await fetchJson('/slider/status');
            updateSliderReadout(data, hint);
        } catch (err) {
            setPill(sliderStatus, `状态读取失败: ${err.message}`, 'error');
        }
    };

    const sliderAction = async (endpoint, body, hint) => {
        const options = { method: 'POST' };
        if (body !== undefined && body !== null) {
            options.body = body;
        }
        try {
            const data = await fetchJson(endpoint, options);
            updateSliderReadout(data, hint);
            return true;
        } catch (err) {
            setPill(sliderStatus, `操作失败: ${err.message}`, 'error');
            return false;
        }
    };

    if (driverSpeed && driverSpeedVal) {
        driverSpeedVal.textContent = `${driverSpeed.value}%`;
        driverSpeed.addEventListener('input', () => {
            driverSpeedVal.textContent = `${driverSpeed.value}%`;
        });
    }

    driverForward?.addEventListener('click', () => driverCommand('forward'));
    driverBack?.addEventListener('click', () => driverCommand('back'));
    driverLeft?.addEventListener('click', () => driverCommand('left'));
    driverRight?.addEventListener('click', () => driverCommand('right'));
    driverStop?.addEventListener('click', () => driverCommand('stop'));

    window.addEventListener('keydown', (event) => {
        if (event.repeat) return;
        let handled = false;
        const key = event.key.toLowerCase();
        if (['w', 'arrowup'].includes(key)) {
            driverCommand('forward');
            handled = true;
        } else if (['s', 'arrowdown'].includes(key)) {
            driverCommand('back');
            handled = true;
        } else if (['a', 'arrowleft'].includes(key)) {
            driverCommand('left');
            handled = true;
        } else if (['d', 'arrowright'].includes(key)) {
            driverCommand('right');
            handled = true;
        } else if (event.code === 'Space') {
            driverCommand('stop');
            handled = true;
        }
        if (handled) {
            event.preventDefault();
        }
    });

    document.querySelectorAll('.knock-grid button[data-channel]').forEach((btn) => {
        btn.addEventListener('click', async () => {
            const index = Number(btn.dataset.channel);
            try {
                const data = await fetchJson('/knock/api/activate', {
                    method: 'POST',
                    body: { index },
                });
                const pin = data.pin ?? index;
                setPill(knockStatus, `通道 ${index} 已触发 (GPIO ${pin})`);
            } catch (err) {
                setPill(knockStatus, `触发失败: ${err.message}`, 'error');
            }
        });
    });

    sliderCalibrate?.addEventListener('click', async () => {
        await sliderAction('/slider/calibrate', null, '校准完成');
    });
    sliderGoZero?.addEventListener('click', async () => {
        await sliderAction('/slider/go_zero', null, '返回工作 0 点');
    });

    document.querySelectorAll('.slider-card button.ghost[data-speed]').forEach((btn) => {
        btn.addEventListener('click', async () => {
            const speed = btn.dataset.speed;
            await sliderAction('/slider/set_speed', { speed }, `速度设为 ${speed}`);
        });
    });

    document.querySelectorAll('.slider-card button.control[data-move]').forEach((btn) => {
        btn.addEventListener('click', async () => {
            const direction = btn.dataset.move;
            await sliderAction('/slider/move_relative', { direction, cm: 0.5 }, direction === 'left' ? '左移 0.5cm' : '右移 0.5cm');
        });
    });

    sliderGoAbs?.addEventListener('click', async () => {
        if (!sliderTarget) return;
        const value = sliderTarget.value.trim();
        const cm = Number(value);
        if (Number.isNaN(cm)) {
            setPill(sliderStatus, '请输入合法的数字', 'warn');
            return;
        }
        if (cm < 0 || cm > 20) {
            setPill(sliderStatus, '目标需在 0-20 cm 范围', 'warn');
            return;
        }
        const ok = await sliderAction('/slider/move_absolute', { target_cm: cm }, `移动至 ${cm.toFixed(2)} cm`);
        if (ok) {
            sliderTarget.value = '';
        }
    });

    let isCameraActive = false;

    const updateCameraUI = (active) => {
        isCameraActive = active;
        if (cameraStart) cameraStart.disabled = active;
        if (cameraStop) cameraStop.disabled = !active;
        if (cameraReload) cameraReload.disabled = !active;
        if (cameraPlaceholder) cameraPlaceholder.hidden = active;
        if (cameraStream) cameraStream.hidden = !active;
    };

    cameraStart?.addEventListener('click', () => {
        if (!cameraStream) return;
        cameraStream.src = `/video0?ts=${Date.now()}`;
        updateCameraUI(true);
        setPill(cameraStatus, '流已开启: /video0');
    });

    cameraStop?.addEventListener('click', () => {
        if (!cameraStream) return;
        cameraStream.src = '';
        cameraStream.removeAttribute('src');
        updateCameraUI(false);
        setPill(cameraStatus, '待命: 点击开启视频', 'warn');
    });

    cameraReload?.addEventListener('click', () => {
        if (!cameraStream || !isCameraActive) return;
        cameraStream.src = `/video0?ts=${Date.now()}`;
        setPill(cameraStatus, '流已刷新');
    });

    const toggleListen = async (start) => {
        if (!listenButton) return;
        listenButton.disabled = true;
        try {
            const url = start ? '/start_listen' : '/stop_listen';
            await fetchJson(url, { method: 'POST' });
            applyListenUI(start);
            const msg = start ? '状态: 正在监听...' : '状态: 未监听';
            setPill(listenStatus, msg, start ? 'ok' : 'warn');
        } catch (err) {
            const prefix = start ? '开启监听失败: ' : '停止监听失败: ';
            setPill(listenStatus, `状态: ${prefix}${err.message}`, 'error');
        } finally {
            listenButton.disabled = false;
        }
    };

    listenButton?.addEventListener('click', () => toggleListen(!isListening));

    startButton?.addEventListener('click', async () => {
        startButton.disabled = true;
        try {
            await fetchJson('/start_work', { method: 'POST' });
            setPill(recordingStatus, '状态: 正在工作中... (最长 10 分钟)');
            stopButton && (stopButton.disabled = false);
            chartPoints = [];
            if (chart) {
                chart.data.datasets[0].data = [];
                chart.update('none');
            }
        } catch (err) {
            setPill(recordingStatus, `状态: 开始工作失败: ${err.message}`, 'error');
            startButton.disabled = false;
        }
    });

    stopButton?.addEventListener('click', async () => {
        stopButton.disabled = true;
        try {
            await fetchJson('/stop_work', { method: 'POST' });
            setPill(recordingStatus, '状态: 正在停止...');
        } catch (err) {
            setPill(recordingStatus, `状态: 结束工作失败: ${err.message}`, 'error');
            stopButton.disabled = false;
        }
    });

    socket.on('status_update', (payload) => {
        const msg = payload?.msg || '';
        if (!msg) return;
        if (msg.includes('监听')) {
            const listening = msg.includes('启动');
            applyListenUI(listening);
            setPill(listenStatus, `状态: ${msg}`, listening ? 'ok' : undefined);
        } else {
            setPill(recordingStatus, `状态: ${msg}`);
        }
    });

    socket.on('new_frequency_data', (payload) => {
        if (typeof payload?.time !== 'number' || typeof payload?.frequency !== 'number') return;
        updateFrequencyChart({ time: payload.time, frequency: payload.frequency });
        document.title = `${payload.frequency.toFixed(1)} Hz · ${BASE_TITLE}`;
    });

    socket.on('work_finished', (payload) => {
        startButton && (startButton.disabled = false);
        stopButton && (stopButton.disabled = true);
        const success = Boolean(payload?.success);
        const duration = typeof payload?.duration === 'number' ? payload.duration.toFixed(1) : null;
        if (success) {
            const suffix = duration ? ` (${duration} 秒)` : '';
            setPill(recordingStatus, `状态: 工作结束，文件已保存${suffix}`);
        } else {
            setPill(recordingStatus, '状态: 工作结束，未生成数据', 'warn');
        }
        document.title = BASE_TITLE;
    });

    socket.on('connect', () => {
        document.title = BASE_TITLE;
    });

    socket.on('disconnect', () => {
        document.title = `${BASE_TITLE} (未连接)`;
    });

    if (cameraStatus) {
        setPill(cameraStatus, '待命: 点击开启视频', 'warn');
    }

    refreshDriverHealth();
    fetchSliderStatus();
    setInterval(() => fetchSliderStatus(), 5000);
});
