/*
 * 一起看模块：admin 发起播放、同步控制，并在切回会话时拉取 chat 端进度。
 * 作者: @ccfork
 */
import { apiGet, apiPost } from './api.js';
import { els, state } from './state.js';

function setStatus(text) {
    if (els.adminWatchStatus) els.adminWatchStatus.textContent = text;
}

function showPanel(show) {
    els.adminWatchPanel.hidden = !show;
}

function markLocalControl() {
    state.watch.localControlUntil = Date.now() + 900;
}

function markRemoteLock() {
    state.watch.remoteLockUntil = Date.now() + 600;
}

function currentVideoState(event = 'sync') {
    return {
        action: 'admin_update_watch',
        session_id: state.currentSessionId,
        url: state.watch.currentUrl,
        event,
        current_time: els.adminWatchVideo.currentTime || 0,
        duration: Number.isFinite(els.adminWatchVideo.duration) ? els.adminWatchVideo.duration : 0,
        paused: els.adminWatchVideo.paused
    };
}

async function pushWatchState(event = 'sync') {
    if (!state.currentSessionId || !state.watch.currentUrl || state.watch.applyingRemote) return;
    markLocalControl();
    const data = await apiPost(currentVideoState(event));
    if (data.success && data.state) {
        state.watch.controlSeq = Number(data.state.control_seq || state.watch.controlSeq);
    }
}

function scheduleSync(event = 'sync') {
    clearTimeout(state.watch.syncTimer);
    state.watch.syncTimer = setTimeout(() => pushWatchState(event), 160);
}

async function applyWatchState(watchState, preferChatProgress = false) {
    if (!watchState || !watchState.active || !watchState.url) {
        els.adminWatchVideo.pause();
        window.WatchPlayer.destroyHls(els.adminWatchVideo);
        els.adminWatchVideo.removeAttribute('src');
        els.adminWatchVideo.load();
        showPanel(false);
        state.watch.currentUrl = '';
        state.watch.controlSeq = Number(watchState?.control_seq || 0);
        state.watch.localControlUntil = 0;
        state.watch.remoteLockUntil = 0;
        return;
    }

    showPanel(true);
    setStatus(preferChatProgress && Number(watchState.chat_reported_at || 0) > 0 ? '已接回 chat 端进度～' : '正在同步一起看～');
    state.watch.applyingRemote = true;
    try {
        if (state.watch.currentUrl !== watchState.url) {
            state.watch.currentUrl = watchState.url;
            const result = await window.WatchPlayer.setVideoSource(els.adminWatchVideo, watchState.url);
            if (!result.ok) setStatus(result.error || '播放链接暂时打不开');
        }

        const chatReportedAt = Number(watchState.chat_reported_at || 0);
        const targetTime = preferChatProgress && chatReportedAt > 0
            ? Number(watchState.chat_current_time || 0)
            : Number(watchState.current_time || 0);
        if (Number.isFinite(targetTime) && Math.abs((els.adminWatchVideo.currentTime || 0) - targetTime) > 0.8) {
            els.adminWatchVideo.currentTime = targetTime;
        }

        if (watchState.paused) {
            els.adminWatchVideo.pause();
        } else {
            els.adminWatchVideo.play().catch(() => {});
        }
        state.watch.controlSeq = Number(watchState.control_seq || 0);
        markRemoteLock();
        setStatus(preferChatProgress && chatReportedAt > 0 ? '已按 chat 端进度接回～' : '一起看同步中～');
    } finally {
        state.watch.applyingRemote = false;
    }
}

export async function loadWatchState(options = {}) {
    if (!state.currentSessionId) {
        showPanel(false);
        return;
    }
    const data = await apiGet('get_watch_state', { session_id: state.currentSessionId });
    if (!data.success) return;
    await applyWatchState(data.state, !!options.preferChatProgress);
}

async function pollWatchState() {
    if (!state.currentSessionId) return;
    const data = await apiGet('get_watch_state', { session_id: state.currentSessionId });
    if (!data.success || !data.state) return;
    const incomingSeq = Number(data.state.control_seq || 0);
    const now = Date.now();
    if (data.state.last_controller === 'admin' && now <= state.watch.localControlUntil) return;
    if (incomingSeq > state.watch.controlSeq && data.state.last_controller !== 'admin') {
        await applyWatchState(data.state, false);
    } else if (data.state.last_controller === 'admin' && incomingSeq > state.watch.controlSeq && now > state.watch.remoteLockUntil) {
        await applyWatchState(data.state, false);
    }
}

export function startWatchPolling() {
    if (state.watchPollInterval) clearInterval(state.watchPollInterval);
    state.watchPollInterval = setInterval(pollWatchState, 1000);
}

async function startWatch() {
    if (!state.currentSessionId) {
        alert('先选择一个用户哦');
        return;
    }
    const url = prompt('粘贴一起看的播放链接（mp4 / m3u8 等）');
    if (!url) return;
    const data = await apiPost({
        action: 'admin_update_watch',
        session_id: state.currentSessionId,
        url: url.trim(),
        event: 'load',
        current_time: 0,
        duration: 0,
        paused: true
    });
    if (!data.success) {
        alert(data.error || '播放链接不可用');
        return;
    }
    await applyWatchState(data.state, false);
}

async function closeWatch() {
    if (!state.currentSessionId) return;
    const data = await apiPost({
        action: 'admin_update_watch',
        session_id: state.currentSessionId,
        event: 'close'
    });
    if (data.success) await applyWatchState(data.state, false);
}

export function bindWatchPanel() {
    els.adminWatchToggle.addEventListener('click', startWatch);
    els.adminWatchCloseBtn.addEventListener('click', closeWatch);
    els.adminWatchVideo.addEventListener('play', () => scheduleSync('play'));
    els.adminWatchVideo.addEventListener('pause', () => scheduleSync('pause'));
    els.adminWatchVideo.addEventListener('seeked', () => scheduleSync('seek'));
    els.adminWatchVideo.addEventListener('timeupdate', () => {
        if (!els.adminWatchVideo.paused) scheduleSync('progress');
    });
}

export function clearWatchTimers() {
    clearTimeout(state.watch.syncTimer);
    if (state.watchPollInterval) clearInterval(state.watchPollInterval);
    state.watchPollInterval = null;
    state.watch.localControlUntil = 0;
    state.watch.remoteLockUntil = 0;
}
