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

let currentRouteId = null;
let userOpacity = 90;
let userZoom = 100;
let ttAllowed = false;

// Le Garage de l'utilisateur (34 items)
let garage = {
    proj74: false, r4000: false, tron: false, aeroad: false, venge: false, 
    sl8: false, dogma: false, supersix: false, aethos: false, anchor: false, emonda: false,
    dtdisc: false, zippdisc: false, enve89: false, zipp858: false, dt65: false, 
    enve78: false, enve45: false, zipp353: false, alpinist: false, meilenstein: false,
    cadex: false, speedmax: false, feltia2: false, plasma: false, feltia: false,
    g_aspero: false, g_crux: false, g_grail: false, g_devote: false,
    wg_enve: false, wg_reserve: false, wg_cadex: false, wg_roval: false
};

// Dictionnaire pour l'affichage propre
const itemName = {
    proj74: "Spec. PROJECT 74", r4000: "Cannondale R4000 RB", tron: "Zwift Concept Z1 (TRON)",
    aeroad: "Canyon Aeroad 2024", venge: "Spec. Venge S-Works", sl8: "Spec. S-Works Tarmac SL8",
    dogma: "Pinarello Dogma F (2024)", supersix: "C'dale SuperSix Evo LAB71",
    aethos: "Spec. Aethos S-Works", anchor: "Bridgestone Anchor RS9s", emonda: "Trek Emonda",
    dtdisc: "DT Swiss ARC110 85/Disc", zippdisc: "Zipp 858/Super9", enve89: "ENVE SES 8.9",
    zipp858: "ZIPP 858", dt65: "DT SWISS ARC 110 65", enve78: "ENVE SES 7.8",
    enve45: "ENVE SES 4.5 PRO", zipp353: "Zipp 353 NSW", alpinist: "Roval Alpinist CLX", meilenstein: "Lightweight Meilenstein",
    cadex: "CADEX Tri", speedmax: "Canyon Speedmax CF SLX", feltia2: "Felt IA 2.0",
    plasma: "Scott Plasma RC Ultimate", feltia: "Felt IA",
    g_aspero: "Cervelo Aspero", g_crux: "Specialized Crux", g_grail: "Canyon Grail", g_devote: "Liv Devote Advanced Pro",
    wg_enve: "ENVE G23", wg_reserve: "Reserve 25 GR", wg_cadex: "Cadex AR 35", wg_roval: "Roval Terra CLX"
};

// --- ORDRE DE PRIORITÉ DEMANDÉ ---
const prioClimbFrames = ['aethos', 'anchor', 'emonda', 'sl8'];
const prioClimbWheels = ['meilenstein', 'zipp353', 'alpinist', 'enve45'];
const prioRollingFrames = ['sl8', 'supersix', 'dogma', 'aethos'];
const prioRollingWheels = ['enve45', 'dt65', 'enve78', 'zipp858'];
const prioFlatFrames = ['proj74', 'r4000', 'tron', 'aeroad', 'venge', 'sl8', 'dogma'];
const prioFlatWheels = ['dtdisc', 'zippdisc', 'dt65', 'enve89'];
const prioTTFrames = ['cadex', 'speedmax', 'feltia2', 'plasma', 'feltia'];
const prioGravelFrames = ['g_aspero', 'g_crux', 'g_grail', 'g_devote'];
const prioGravelWheels = ['wg_enve', 'wg_reserve', 'wg_cadex', 'wg_roval'];

function getBestItem(priorityList, defaultName) {
    for (let key of priorityList) {
        if (garage[key]) return itemName[key];
    }
    return defaultName;
}

function loadSettings() {
    const sOp = localStorage.getItem('myMod_Bike_Op');
    const sZoom = localStorage.getItem('myMod_Bike_Zoom');
    const sGarage = localStorage.getItem('myMod_Bike_Garage');
    const sTT = localStorage.getItem('myMod_Bike_TT');

    if(sOp) userOpacity = parseInt(sOp);
    if(sZoom) userZoom = parseInt(sZoom);
    if(sGarage) garage = { ...garage, ...JSON.parse(sGarage) };
    if(sTT !== null) ttAllowed = (sTT === 'true');

    document.getElementById('in-opacity').value = userOpacity;
    document.getElementById('in-zoom').value = userZoom;
    document.getElementById('chk-tt-allowed').checked = ttAllowed;

    Object.keys(garage).forEach(key => {
        const el = document.getElementById(`chk-${key}`);
        if(el) el.checked = garage[key];
    });

    applyVisuals();
}

function saveSettings() {
    userOpacity = parseInt(document.getElementById('in-opacity').value);
    userZoom = parseInt(document.getElementById('in-zoom').value);
    ttAllowed = document.getElementById('chk-tt-allowed').checked;
    
    Object.keys(garage).forEach(key => {
        const el = document.getElementById(`chk-${key}`);
        if(el) garage[key] = el.checked;
    });

    localStorage.setItem('myMod_Bike_Op', userOpacity);
    localStorage.setItem('myMod_Bike_Zoom', userZoom);
    localStorage.setItem('myMod_Bike_Garage', JSON.stringify(garage));
    localStorage.setItem('myMod_Bike_TT', ttAllowed);

    applyVisuals();
    document.getElementById('settings-panel').style.display = 'none';
    
    if(courseInfo.totalDistance > 0) calculateRecommendation();
}

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

// =========================================================================
// --- COPIE EXACTE DU MOTEUR V8 INFOS COURSE POUR LECTURE DISTANCE / D+ ---
// =========================================================================
const courseInfo = {
    event: { activeEvent: null, eventSubgroupId: 0 },
    totalDistance: 0,
    totalElevation: 0,
    routeName: "Route Inconnue"
};

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

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

async function updateRoute(athlete) {
    if (!athlete || !athlete.state) return;
    const state = athlete.state;

    const event = courseInfo.event;
    const eventSubgroupId = getEventSubgroupId(athlete);

    let routeChanged = false;
   
    if (event.activeEvent == null || eventSubgroupId != event.eventSubgroupId) {
        event.eventSubgroupId = eventSubgroupId;
        event.activeEvent = await o101Common.lazyGetSubgroup(eventSubgroupId);
        routeChanged = true;
    }

    if (currentRouteId !== state.routeId) {
        currentRouteId = state.routeId;
        routeChanged = true;
    }

    // On ne recalcule que si la route/l'event a changé pour ne pas spammer
    if (!routeChanged && courseInfo.totalDistance > 0) return;

    if (event.activeEvent == null) {
        let route = await o101Common.lazyGetRoute(state.routeId);
        if (route) {
            if (route.name) courseInfo.routeName = route.name;
            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;
                    if (sauceRoute.name) courseInfo.routeName = sauceRoute.name;
                }
            }
            courseInfo.totalDistance = routeDistance;
            courseInfo.totalElevation = routeElevation;
        }
    } else {
        let rId = event.activeEvent.routeId || state.routeId;
        let zwiftRoute = await o101Common.lazyGetRoute(rId);
        if (zwiftRoute) {
            if (zwiftRoute.name) courseInfo.routeName = zwiftRoute.name;
            else if (event.activeEvent.name) courseInfo.routeName = event.activeEvent.name;

            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;
        }
    }

    // Affichage des stats (Dist en km et D+ en m)
    const distKm = (courseInfo.totalDistance / 1000).toFixed(1);
    const elevM = Math.round(courseInfo.totalElevation);

    document.getElementById('route-name').innerText = courseInfo.routeName;
    document.getElementById('route-stats').innerText = `${distKm} km | ${elevM} m D+`;

    calculateRecommendation();
}
// =========================================================================

function calculateRecommendation() {
    const dist = courseInfo.totalDistance / 1000;
    const elev = courseInfo.totalElevation;
    const name = courseInfo.routeName.toLowerCase();

    // Ratio : Mètres de D+ par Kilomètre
    const ratio = (dist > 0) ? (elev / dist) : 0;

    let typeStr = "PLAT";
    let typeClass = "type-flat";
    let rFrame = "";
    let rWheels = "";

    const isGravel = name.includes('jungle') || name.includes('temple') || name.includes('gravel') || name.includes('repak');

    if (isGravel) {
        typeStr = "GRAVEL / DIRT";
        typeClass = "type-gravel";
        rFrame = getBestItem(prioGravelFrames, "Cadre de base (débloqué et lvl5)");
        rWheels = getBestItem(prioGravelWheels, "Roues de base (débloquées et lvl5)");
    } 
    else if (ratio > 18) {
        typeStr = "MONTAGNE";
        typeClass = "type-climb";
        rFrame = getBestItem(prioClimbFrames, "Cadre de base (débloqué et lvl5)");
        
        if (rFrame === itemName.tron) rWheels = "Intégrées (TRON)";
        else if (rFrame === itemName.proj74) rWheels = "Intégrées (PROJECT 74)";
        else if (rFrame === itemName.r4000) rWheels = "Intégrées (R4000 RB)";
        else rWheels = getBestItem(prioClimbWheels, "Roues de base (débloquées et lvl5)");
    } 
    else if (ttAllowed) {
        typeStr = ratio >= 8 ? "CHRONO VALLONNÉ" : "CHRONO PLAT";
        typeClass = "type-tt";
        rFrame = getBestItem(prioTTFrames, "Vélo TT de base (débloqué et lvl5)");
        rWheels = getBestItem(prioFlatWheels, "Roues de base (débloquées et lvl5)");
    }
    else if (ratio >= 8 && ratio <= 18) {
        typeStr = "VALLONNÉ / MIXTE";
        typeClass = "type-rolling";
        rFrame = getBestItem(prioRollingFrames, "Cadre de base (débloqué et lvl5)");
        
        if (rFrame === itemName.tron) rWheels = "Intégrées (TRON)";
        else if (rFrame === itemName.proj74) rWheels = "Intégrées (PROJECT 74)";
        else if (rFrame === itemName.r4000) rWheels = "Intégrées (R4000 RB)";
        else rWheels = getBestItem(prioRollingWheels, "Roues de base (débloquées et lvl5)");
    } 
    else {
        typeStr = "PLAT AÉRO";
        typeClass = "type-flat";
        rFrame = getBestItem(prioFlatFrames, "Cadre de base (débloqué et lvl5)");
        
        if (rFrame === itemName.tron) rWheels = "Intégrées (TRON)";
        else if (rFrame === itemName.proj74) rWheels = "Intégrées (PROJECT 74)";
        else if (rFrame === itemName.r4000) rWheels = "Intégrées (R4000 RB)";
        else rWheels = getBestItem(prioFlatWheels, "Roues de base (débloquées et lvl5)");
    }

    const elType = document.getElementById('route-type');
    elType.innerText = typeStr;
    elType.className = `route-type ${typeClass}`;
    elType.style.display = 'inline-block';

    document.getElementById('rec-frame').innerText = rFrame;
    document.getElementById('rec-wheels').innerText = rWheels;
}

export async function main() {
    loadSettings();

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

    if (common && common.initInteractionListeners) {
        common.initInteractionListeners();
        
        // On écoute le packet complet (comme dans infos_course) pour extraire state et eventSubgroupId
        common.subscribe('athlete/watching', (packet) => {
            if(packet) updateRoute(packet);
        });
    }
}