import * as common from '/pages/src/common.mjs';
import * as o101Common from './o101/common.mjs'; 

let userOpacity = 90;
let userZoom = 100;

// Historique pour l'ETA
const history10s = [];

// Cache Course
const courseInfo = {
    event: { activeEvent: null, eventSubgroupId: 0 },
    totalDistance: 0,
    totalElevation: 0, 
    progress: 0,
    distanceCompleted: 0,
    lapInfo: { laps: 0, lapDistance: 0 },
    leadInDistance: 0,
    distanceToFinish: 0
};

// Cerveau Prédictif Segments (V8 EXACT)
let sm = {
    phase: 'IDLE', 
    id: null,
    name: '',
    totalDist: 1000,
    startOdo: 0, 
    finishOdo: 0,
    startTime: 0,
    lastZDist: 99999,
    lastOdo: 0,
    athleteId: null,
    lastValidOdo: 0
};

async function getSafeRouteData(routeId) {
    if (!routeId) return null;
    try { return await common.rpc.getRoute(routeId); } catch(e) { return null; }
}

function get10sAverages(power, speed) {
    const now = Date.now();
    history10s.push({ time: now, power, speed });
    while (history10s.length > 0 && now - history10s[0].time > 10000) history10s.shift();
    if (history10s.length === 0) return { avgPower: power, avgSpeed: speed };
    
    let sumP = 0; let sumS = 0;
    for (let i = 0; i < history10s.length; i++) { sumP += history10s[i].power; sumS += history10s[i].speed; }
    return { avgPower: sumP / history10s.length, avgSpeed: sumS / history10s.length };
}

function loadSettings() {
    const sOp = localStorage.getItem('myMod_Infos_Op');
    const sZoom = localStorage.getItem('myMod_Infos_Zoom');
    if(sOp) userOpacity = parseInt(sOp);
    if(sZoom) userZoom = parseInt(sZoom);
    if (document.getElementById('in-opacity')) document.getElementById('in-opacity').value = userOpacity;
    if (document.getElementById('in-zoom')) document.getElementById('in-zoom').value = userZoom;
    applyVisuals();
}

function saveSettings() {
    if (document.getElementById('in-opacity')) userOpacity = parseInt(document.getElementById('in-opacity').value);
    if (document.getElementById('in-zoom')) userZoom = parseInt(document.getElementById('in-zoom').value);
    localStorage.setItem('myMod_Infos_Op', userOpacity);
    localStorage.setItem('myMod_Infos_Zoom', userZoom);
    applyVisuals();
    if (document.getElementById('settings-panel')) document.getElementById('settings-panel').style.display = 'none';
}

function applyVisuals() {
    if (document.getElementById('op-label')) document.getElementById('op-label').innerText = userOpacity;
    if (document.getElementById('dash')) document.getElementById('dash').style.backgroundColor = `rgba(0, 0, 0, ${userOpacity/100})`;
    if (document.getElementById('zoom-label')) document.getElementById('zoom-label').innerText = (userZoom/100).toFixed(1);
    if (document.getElementById('wrapper')) document.getElementById('wrapper').style.transform = `scale(${userZoom/100})`;
}

function formatTime(seconds) {
    if (seconds === Infinity || isNaN(seconds) || seconds < 0) return '00:00';
    const h = Math.floor(seconds / 3600);
    const m = Math.floor((seconds % 3600) / 60);
    const s = Math.floor(seconds % 60);
    const mStr = m.toString().padStart(2, '0');
    const sStr = s.toString().padStart(2, '0');
    if (h > 0) return `${h}:${mStr}:${sStr}`;
    return `${mStr}:${sStr}`;
}

const getEventSubgroupId = (athlete) => {
    let eventSubgroupId;
    if (Object.hasOwn(athlete, 'o101')) eventSubgroupId = athlete.o101.eventSubgroupId;
    return eventSubgroupId ?? athlete.state.eventSubgroupId;
}

// --- BOUCLE PRINCIPALE ---
async function updateDisplay(athlete) {
    if (!athlete || !athlete.state) return;
    const state = athlete.state;

    // 1. DONNÉES GLOBALES
    const speedKmh = (state.speed || 0).toFixed(1); 
    const distKm = ((state.distance || 0) / 1000).toFixed(1);
    const elev = Math.round(state.climbing || 0); 
    const time = formatTime(state.time || 0);

    if (document.getElementById('val-speed')) document.getElementById('val-speed').innerText = speedKmh;
    if (document.getElementById('val-dist')) document.getElementById('val-dist').innerText = distKm;
    if (document.getElementById('val-elev')) document.getElementById('val-elev').innerText = elev;
    if (document.getElementById('val-time')) document.getElementById('val-time').innerText = time;

    // 2. PROGRESSION COURSE
    const event = courseInfo.event;
    const eventSubgroupId = getEventSubgroupId(athlete);
   
    if (event.activeEvent == null || eventSubgroupId != event.eventSubgroupId) {
        event.eventSubgroupId = eventSubgroupId;
        event.activeEvent = await o101Common.lazyGetSubgroup(eventSubgroupId);
    }

    if (event.activeEvent == null) {
        let route = await o101Common.lazyGetRoute(state.routeId);
        if (route) {
            const routeDistance = route.distanceInMeters;
            let routeElevation = 0;
            if (route.elevationInMeters > 0 || route.elevation > 0 || route.climbing > 0 || route.routeClimbing > 0) {
                routeElevation = route.elevationInMeters || route.elevationGainInMeters || route.elevation || route.climbing || route.routeClimbing;
            }
            if (routeElevation === 0) {
                let sauceRoute = await getSafeRouteData(state.routeId);
                if (sauceRoute) routeElevation = sauceRoute.elevation || sauceRoute.climbing || sauceRoute.elevationInMeters || sauceRoute.routeClimbing || 0;
            }
            courseInfo.totalDistance = routeDistance;
            courseInfo.totalElevation = routeElevation;
            let progDist = state.eventDistance || (state.distance % routeDistance);
            courseInfo.distanceToFinish = Math.max(0, routeDistance - progDist);
            courseInfo.progress = routeDistance > 0 ? (progDist / routeDistance) * 100 : 0;
        }
    } else {
        let rId = event.activeEvent.routeId || state.routeId;
        let zwiftRoute = await o101Common.lazyGetRoute(rId);
        if (zwiftRoute) {
            const routeDistance = event.activeEvent.distanceInMeters ?? event.activeEvent.routeDistance;
            let routeElevation = event.activeEvent.elevationInMeters || event.activeEvent.totalElevation || event.activeEvent.routeClimbing || event.activeEvent.elevation || 0;

            if (routeElevation === 0) {
                let sauceRoute = await getSafeRouteData(rId) || await getSafeRouteData(state.routeId);
                let elevPerLap = zwiftRoute.elevationInMeters || zwiftRoute.elevationGainInMeters || zwiftRoute.climbing || zwiftRoute.routeClimbing || 0;
                let leadInElev = zwiftRoute.leadinElevationInMeters || zwiftRoute.leadInElevation || 0;
                let rDist = zwiftRoute.distanceInMeters || zwiftRoute.distance || 1;
                let leadInDist = zwiftRoute.leadinDistanceInMeters || zwiftRoute.leadInDistance || 0;
                
                if (sauceRoute) {
                    elevPerLap = sauceRoute.elevation || sauceRoute.climbing || sauceRoute.routeClimbing || elevPerLap;
                    leadInElev = sauceRoute.leadInElevation || sauceRoute.leadinElevation || leadInElev;
                    rDist = sauceRoute.distance || sauceRoute.distanceInMeters || rDist;
                    leadInDist = sauceRoute.leadInDistance || sauceRoute.leadinDistance || leadInDist;
                }
                let laps = event.activeEvent.laps || 0;
                if (laps === 0 && routeDistance > 0 && rDist > 1) laps = Math.max(0, routeDistance - leadInDist) / rDist; 
                else if (laps === 0) laps = 1;
                routeElevation = (elevPerLap * laps) + leadInElev;
            }
            courseInfo.totalDistance = routeDistance;
            courseInfo.totalElevation = routeElevation;
            courseInfo.distanceToFinish = Math.max(0, routeDistance - state.eventDistance);
            courseInfo.progress = routeDistance > 0 ? (state.eventDistance / routeDistance) * 100 : 0;
        }
    }

    const progBarDist = document.getElementById('prog-bar-dist') || document.getElementById('prog-bar-fill');
    const progTextDist = document.getElementById('prog-text-dist') || document.getElementById('prog-text');

    if (courseInfo.totalDistance > 0) {
        let pct = Math.min(100, Math.max(0, courseInfo.progress));
        let remainKm = (courseInfo.distanceToFinish / 1000).toFixed(1);
        if (progBarDist) progBarDist.style.width = `${pct}%`;
        if (progTextDist) progTextDist.innerHTML = `ARRIVÉE : <b>${remainKm} KM</b> (${pct.toFixed(1)}%)`;
    } else {
        if (progBarDist) progBarDist.style.width = '0%';
        if (progTextDist) progTextDist.innerHTML = '<span style="opacity:0.5">DIST LIBRE</span>';
    }

    const progBarElev = document.getElementById('prog-bar-elev');
    const progTextElev = document.getElementById('prog-text-elev');
    if (progBarElev && progTextElev) {
        let totalElev = courseInfo.totalElevation; 
        if (totalElev > 0) {
            let currentElevForCalc = event.activeEvent ? elev : (elev % totalElev);
            let pctElev = (currentElevForCalc / totalElev) * 100;
            if (pctElev > 100) pctElev = 100;
            let remainElev = Math.max(0, Math.round(totalElev - currentElevForCalc));
            progBarElev.style.width = `${pctElev}%`;
            progTextElev.innerHTML = `ARRIVÉE : <b>${remainElev} M</b> (${pctElev.toFixed(1)}%)`;
        } else {
            progBarElev.style.width = '0%';
            progTextElev.innerHTML = '<span style="opacity:0.5">D+ INCONNU</span>';
        }
    }

    // 3. MOTEUR DE SEGMENTS INTELLIGENT (V8 EXACT)
    if (sm.athleteId !== athlete.athleteId) {
        sm.athleteId = athlete.athleteId;
        sm.phase = 'IDLE';
        sm.id = null;
        sm.lastValidOdo = parseFloat(state.distance || state.eventDistance || 0);
    }

    let rawDist = parseFloat(state.distance || state.eventDistance || 0);
    if (rawDist >= sm.lastValidOdo) {
        sm.lastValidOdo = rawDist;
    } else if (rawDist > 0 && (sm.lastValidOdo - rawDist > 500)) {
        sm.lastValidOdo = rawDist;
        sm.phase = 'IDLE';
        sm.id = null;
    }
    const currentOdo = sm.lastValidOdo;

    const { avgSpeed } = get10sAverages(state.power || 0, state.speed || 0);

    const dataSource = athlete.segmentData || (common.athlete ? common.athlete.segmentData : null);
    let entries = [];
    if (dataSource) {
        if (typeof dataSource.values === 'function') entries = Array.from(dataSource.values());
        else if (Array.isArray(dataSource)) entries = dataSource;
        else entries = Object.values(dataSource);
    }

    let activeTarget = entries.find(e => e && typeof e === 'object' && e.distanceToGo !== undefined);
    let segList = entries.find(e => Array.isArray(e) && e.length > 0 && e[0].segLength !== undefined);

    if (activeTarget) {
        let zDist = parseFloat(activeTarget.distanceToGo);
        if (activeTarget.distanceToGoUnits === 'km') zDist *= 1000;

        let totalDist = 1000; 
        if (segList) {
            let match = segList.find(s => s.id === activeTarget.id);
            if (match && match.segLength) totalDist = parseFloat(match.segLength);
        }

        if (sm.id !== activeTarget.id) {
            sm.id = activeTarget.id;
            sm.name = activeTarget.name || 'Segment';
            sm.totalDist = totalDist;
            sm.phase = 'APPROACH';
            sm.lastZDist = zDist;
            sm.lastOdo = currentOdo;
            sm.startOdo = currentOdo + zDist;
            sm.finishOdo = currentOdo + zDist + totalDist;
        } else {
            let deltaOdo = currentOdo - sm.lastOdo;

            if (sm.phase === 'APPROACH') {
                let predApproach = sm.lastZDist - deltaOdo;
                let predFlipped = sm.totalDist - (deltaOdo - sm.lastZDist);

                if (Math.abs(zDist - predFlipped) < Math.abs(zDist - predApproach)) {
                    sm.phase = 'ACTIVE';
                    sm.startTime = Date.now();
                    sm.finishOdo = currentOdo + zDist;
                    sm.startOdo = sm.finishOdo - sm.totalDist;
                } else {
                    if (Math.abs(zDist - sm.lastZDist) > 0.5) {
                        sm.startOdo = currentOdo + zDist;
                        sm.finishOdo = sm.startOdo + sm.totalDist;
                    }
                }
            } else if (sm.phase === 'ACTIVE') {
                if (Math.abs(zDist - sm.lastZDist) > 0.5) {
                    sm.finishOdo = currentOdo + zDist;
                }
            }

            sm.lastZDist = zDist;
            sm.lastOdo = currentOdo;
        }
    } else if (sm.phase === 'APPROACH') {
        let remainToStart = sm.startOdo - currentOdo;
        if (remainToStart > 150) {
            sm.phase = 'IDLE';
            sm.id = null;
        }
    }

    // MISE À JOUR VISUELLE DU SEGMENT
    const segContainer = document.getElementById('seg-container');
    const segBar = document.getElementById('prog-bar-seg');
    const segText = document.getElementById('prog-text-seg');

    if (sm.id && segContainer && segBar && segText) {
        segContainer.style.display = 'block';
        let remainToStart = sm.startOdo - currentOdo;
        let remainToFinish = sm.finishOdo - currentOdo;

        if (sm.phase === 'APPROACH') {
            if (remainToStart < 0) remainToStart = 0;
            segBar.style.width = '0%';
            segText.innerHTML = `<span style="color:#ffcc33; margin-right:6px;">${sm.name}</span> : dans ${remainToStart.toFixed(0)}m / ${remainToFinish.toFixed(0)}m`;
        } 
        else if (sm.phase === 'ACTIVE') {
            if (remainToFinish <= 0) {
                sm.phase = 'IDLE';
                sm.id = null;
                segContainer.style.display = 'none';
            } else {
                let progressDist = currentOdo - sm.startOdo;
                let pct = (progressDist / sm.totalDist) * 100;
                if (pct > 100) pct = 100;
                if (pct < 0) pct = 0;
                let elapsedSec = (Date.now() - sm.startTime) / 1000;

                const speedMs = Math.max(0.1, avgSpeed / 3.6); 
                const remainSec = remainToFinish / speedMs;
                const finalEtaSec = elapsedSec + remainSec;

                segBar.style.width = `${pct}%`;
                segText.innerHTML = `⏱️ ${formatTime(elapsedSec)} &nbsp;|&nbsp; ETA : ${formatTime(finalEtaSec)} &nbsp;<span style="font-size:11px; color:#ddd; font-weight:normal;">(${remainToFinish.toFixed(0)}m)</span>`;
            }
        }
    } else if (segContainer) {
        segContainer.style.display = 'none';
    }
}

// --- INIT ---
export async function main() {
    loadSettings();

    const btnS = document.getElementById('btn-settings');
    if(btnS) btnS.addEventListener('click', () => {
        const p = document.getElementById('settings-panel');
        if (p) p.style.display = p.style.display === 'block' ? 'none' : 'block';
    });
    
    const btnV = document.getElementById('btn-save');
    if(btnV) btnV.addEventListener('click', saveSettings);
    
    const iOp = document.getElementById('in-opacity');
    if(iOp) iOp.addEventListener('input', (e) => { userOpacity = e.target.value; applyVisuals(); });
    
    const iZm = document.getElementById('in-zoom');
    if(iZm) iZm.addEventListener('input', (e) => { userZoom = e.target.value; applyVisuals(); });

    if (common && common.initInteractionListeners) {
        common.initInteractionListeners();
        common.subscribe('athlete/watching', (packet) => {
            if(packet) updateDisplay(packet); 
        });
    }
}