Plotly.setPlotConfig({
    staticPlot: false,
    displayModeBar: false,
    scrollZoom: true,
    showTips: false,
    doubleClick: 'reset+autosize',
    modeBarButtonsToRemove: ['toImage', 'sendDataToCloud', 'editInChartStudio']
});

// Add this at the top of the file
function debounce(func, wait) {
    let timeout;
    return function(...args) {
        clearTimeout(timeout);
        timeout = setTimeout(() => func.apply(this, args), wait);
    };
}

// Constants
const TIMEFRAME_SECONDS = {
    "1S": 1, "5S": 5, "15S": 15, "30S": 30,
    "1": 60, "3": 180, "5": 300, "15": 900,
    "30": 1800, "45": 2700, "60": 3600, "120": 7200,
    "180": 10800, "240": 14400, "1D": 86400,
    "1W": 604800, "1M": 2592000
};

const DEFAULT_RSI_LINES = [
    { value: 30, color: '#FF69B4' },
    { value: 70, color: '#FF69B4' }
];

const DEFAULT_DATA_LENGTH = 1000;
const DEFAULT_TIMEFRAME = "15";

let lastFetchTime = 0;
const FETCH_COOLDOWN = 500; // 500ms cooldown between fetches

let dataCache = {};
let currentViewport = { start: null, end: null };

const baseLayout = {
    dragmode: 'pan',
    showlegend: false,
    plot_bgcolor: '#131722',
    paper_bgcolor: '#131722',
    font: { color: '#d1d4dc' },
    margin: { t: 30, r: 50, b: 30, l: 50 },
    xaxis: {
        rangeslider: { visible: false },
        showgrid: true,
        gridcolor: '#1f2937',
        color: '#d1d4dc',
        linecolor: '#2a2e39',
        tickcolor: '#2a2e39',
        showline: true,
        linewidth: 2,
        mirror: true,
        showspikes: true,
        spikemode: 'across',
        spikesnap: 'cursor',
        spikecolor: '#919191',
        spikethickness: 1,
        rangeselector: {
            buttons: [
                {count: 1, label: '1d', step: 'day', stepmode: 'backward'},
                {count: 7, label: '1w', step: 'day', stepmode: 'backward'},
                {count: 1, label: '1m', step: 'month', stepmode: 'backward'},
                {step: 'all'}
            ],
            bgcolor: '#131722',
            activecolor: '#2962ff'
        }
    },
    yaxis: {
        fixedrange: false,
        autorange: true,
        showgrid: true,
        gridcolor: '#1f2937',
        color: '#d1d4dc',
        linecolor: '#2a2e39',
        tickcolor: '#2a2e39',
        showline: true,
        linewidth: 2,
        mirror: true,
        showspikes: true,
        spikemode: 'across',
        spikesnap: 'cursor',
        spikecolor: '#919191',
        spikethickness: 1
    },
    hovermode: 'x unified'
};

const config = {
    responsive: true,
    scrollZoom: true,
    displayModeBar: false,
    modeBarButtonsToAdd: ['pan2d', 'zoomIn2d', 'zoomOut2d', 'resetScale2d'],
};

document.addEventListener('DOMContentLoaded', function() {
    console.log("DOMContentLoaded event fired");
    fetchOptions();
    setupTimeframeButtons();
    setupCheckboxes();
    loadUserProfile();
    
    // Set up event listeners for toggle switches
    document.getElementById('autoScaleToggle').addEventListener('change', updateChartLayout);
    document.getElementById('floatingBubbleToggle').addEventListener('change', updateChartLayout);

    document.getElementById('addRSILine').addEventListener('click', addRSILine);
    document.getElementById('resetRSILines').addEventListener('click', resetRSILines);

    // Set the default active timeframe
    const defaultTimeframe = "15"; // Set this to your default timeframe
    updateActiveTimeframeButton(defaultTimeframe);

    // Fetch and render initial data
    fetchAndRenderData();
});

document.getElementById('autoScaleToggle').addEventListener('change', () => {
    updateChartLayout();
});

// Modify the "Add RSI Line" button event listener
document.getElementById('addRSILine').addEventListener('click', () => {
    const value = prompt("Enter RSI line value (0-100):", "50");
    if (value !== null && !isNaN(value) && value >= 0 && value <= 100) {
        const color = prompt("Enter line color (e.g., #FF0000 for red):", "#FF69B4");
        if (color) {
            const rsiLines = loadRSILines();
            rsiLines.push({ value: parseFloat(value), color });
            saveRSILines(rsiLines);
            // Force an immediate update of the RSI chart
            Plotly.relayout('rsi-chart', {
                shapes: rsiLines.map(line => ({
                    type: 'line',
                    x0: 0,
                    x1: 1,
                    xref: 'paper',
                    y0: line.value,
                    y1: line.value,
                    line: {
                        color: line.color,
                        width: 1,
                        dash: 'dash',
                    }
                }))
            });
        }
    }
});

// Add this to your DOMContentLoaded event listener
document.getElementById('resetRSILines').addEventListener('click', resetRSILines);

// Functions
function fetchOptions() {
    console.log("Fetching options");
    fetch('/api/options')
        .then(response => response.json())
        .then(data => {
            console.log("Options received:", data);
            const coinSelect = document.getElementById('coin');
            
            // Populate coin options
            data.coins.forEach(coin => {
                const option = document.createElement('option');
                option.value = coin;
                option.text = coin;
                coinSelect.appendChild(option);
            });

            // Set default coin value
            coinSelect.value = data.default_coin;

            // Set the active timeframe button
            const defaultTimeframe = "15"; // Make sure this matches the one in DOMContentLoaded
            const defaultTimeframeButton = document.querySelector(`.timeframe-btn[data-timeframe="${defaultTimeframe}"]`);
            if (defaultTimeframeButton) {
                document.querySelectorAll('.timeframe-btn').forEach(btn => btn.classList.remove('active'));
                defaultTimeframeButton.classList.add('active');
            }

            // Set the default active timeframe
            updateActiveTimeframeButton(data.default_timeframe);

            // Fetch and render data with default values
            fetchAndRenderData();
        })
        .catch(error => console.error('Error fetching options:', error));
}

function setupTimeframeButtons() {
    const buttons = document.querySelectorAll('.timeframe-btn');
    buttons.forEach(btn => {
        btn.addEventListener('click', function() {
            buttons.forEach(b => b.classList.remove('active'));
            this.classList.add('active');
            fetchAndRenderData();
        });
    });
}

function updateActiveTimeframeButton(timeframe) {
    const buttons = document.querySelectorAll('.timeframe-btn');
    buttons.forEach(btn => {
        if (btn.dataset.timeframe === timeframe) {
            btn.classList.add('active');
        } else {
            btn.classList.remove('active');
        }
    });
}

// Add an event listener for the coin dropdown
document.getElementById('coin').addEventListener('change', debounce(fetchAndRenderData, 300));

function setupCheckboxes() {
    // Only setup checkboxes that exist in your HTML
    document.getElementById('autoScaleToggle').checked = true;
    document.getElementById('floatingBubbleToggle').checked = false;
}


function getSelectedTimeframe() {
    const selectedButton = document.querySelector('.timeframe-btn.active');
    return selectedButton ? selectedButton.dataset.timeframe : DEFAULT_TIMEFRAME;
}

function fetchAndRenderData() {
    const coin = document.getElementById('coin').value || 'BTC';
    const timeframe = getSelectedTimeframe();

    console.log(`Fetching data for coin: ${coin}, timeframe: ${timeframe}, data length: ${DEFAULT_DATA_LENGTH}`);

    showSpinner();
    const url = `/api/data?coin=${coin}&timeframe=${timeframe}&limit=${DEFAULT_DATA_LENGTH}`;
    
    fetch(url)
        .then(response => {
            console.log(`api/data response status: ${response.status}`);
            if (!response.ok) {
                return response.json().then(err => { throw new Error(err.error || `HTTP error! status: ${response.status}`); });
            }
            return response.json();
        })
        .then(responseData => {
            if (responseData.error) {
                throw new Error(responseData.error);
            }
            console.log(`Received ${responseData.data.length} data points`);
            if (responseData.data.length === 0) {
                throw new Error('No data available for the selected range.');
            }
            window.bufferedData = cleanData(responseData.data);
            
            // Store the data range
            window.dataRange = {
                start: responseData.min_time,
                end: responseData.max_time
            };
            
            // Set the initial view to the latest data
            const latestTime = responseData.max_time;
            const initialStartTime = latestTime - (DEFAULT_DATA_LENGTH * TIMEFRAME_SECONDS[timeframe]);
            
            const containerHeight = document.getElementById('chart-container').offsetHeight;
            createCombinedChart(window.bufferedData, containerHeight);
        })
        .catch(error => {
            console.error('Error fetching data:', error);
            document.getElementById('combined-chart').innerHTML = `<p>Error: ${error.message}</p>`;
        })
        .finally(() => {
            hideSpinner();
        });
}

function renderCharts(data, startTime, endTime) {
    console.log("Starting to render charts");
    if (!data || data.length === 0) {
        console.warn('No data to render');
        showErrorMessage('No data available for the selected range.');
        return;
    }

    const cleanedData = cleanData(data);
    console.log("Cleaned data length:", cleanedData.length);

    if (cleanedData.length === 0) {
        console.warn('All data points are invalid after cleaning.');
        showErrorMessage('No valid data points available.');
        return;
    }

    const containerHeight = document.getElementById('chart-container').offsetHeight;
    const mainChartHeight = containerHeight * 0.75;
    const rsiChartHeight = containerHeight * 0.25;

    createCandlestickChart(cleanedData, mainChartHeight, startTime, endTime);
    createRSIChart(cleanedData, rsiChartHeight, startTime, endTime);
    
    // Link chart ranges
    const mainChart = document.getElementById('chart');
    const rsiChart = document.getElementById('rsi-chart');

    mainChart.on('plotly_relayout', function(eventdata) {
        console.log("Main chart relayout event:", eventdata);
        if (eventdata['xaxis.range[0]'] && eventdata['xaxis.range[1]']) {
            const newStart = new Date(eventdata['xaxis.range[0]']);
            const newEnd = new Date(eventdata['xaxis.range[1]']);
            console.log("New range:", newStart, "to", newEnd);

            Plotly.relayout('rsi-chart', {
                'xaxis.range': [eventdata['xaxis.range[0]'], eventdata['xaxis.range[1]']]
            });
            updateCandlestickChart(window.bufferedData);
            updateRSIChart(window.bufferedData);
        }
    });

    rsiChart.on('plotly_relayout', function(eventdata) {
        if (eventdata['xaxis.range[0]'] && eventdata['xaxis.range[1]']) {
            Plotly.relayout('chart', {
                'xaxis.range': [eventdata['xaxis.range[0]'], eventdata['xaxis.range[1]']]
            });
            updateCandlestickChart(window.bufferedData);
            updateRSIChart(window.bufferedData);
        }
    });
    console.log("Exiting renderCharts");
}

function createCandlestickChart(data, height, startTime, endTime) {
    const trace = createCandlestickTrace(data);
    const autoScale = document.getElementById('autoScaleToggle').checked;
    const candlestickLayout = { 
        ...baseLayout, 
        height: height,
        margin: { t: 20, r: 50, b: 20, l: 50 },
        yaxis: {
            ...baseLayout.yaxis,
            fixedrange: !autoScale,
            autorange: autoScale
        },
        xaxis: {
            ...baseLayout.xaxis,
            range: [new Date(startTime * 1000), new Date(endTime * 1000)]
        }
    };
    
    Plotly.newPlot('chart', [trace], candlestickLayout, config)
        .then(() => {
            console.log("Candlestick chart plotted successfully");
            const chartDiv = document.getElementById('chart');
            chartDiv.on('plotly_relayout', debounce(updateDataOnPan, 250));
        })
        .catch(err => console.error("Error plotting candlestick chart:", err));
}

function createRSIChart(data, height, startTime, endTime) {
    const trace = {
        x: data.map(d => new Date(d.time * 1000)),
        y: data.map(d => d.RSI),
        type: 'scatter',
        line: { color: '#8A2BE2' },
        name: 'RSI'
    };

    const rsiLines = loadRSILines();
    const autoScale = document.getElementById('autoScaleToggle').checked;

    const layout = {
        ...baseLayout,
        height: height,
        margin: { t: 20, r: 50, b: 20, l: 50 },
        yaxis: { 
            ...baseLayout.yaxis, 
            range: autoScale ? null : [0, 100],
            fixedrange: !autoScale,
            autorange: autoScale
        },
        xaxis: {
            ...baseLayout.xaxis,
            range: [new Date(startTime * 1000), new Date(endTime * 1000)]
        },
        shapes: rsiLines.map(line => ({
            type: 'line',
            x0: 0,
            x1: 1,
            xref: 'paper',
            y0: line.value,
            y1: line.value,
            line: {
                color: line.color,
                width: 1,
                dash: 'dash',
            }
        }))
    };

    Plotly.newPlot('rsi-chart', [trace], layout, config)
        .then(() => {
            console.log("RSI chart plotted successfully");
            const rsiChartDiv = document.getElementById('rsi-chart');
            rsiChartDiv.on('plotly_relayout', debounce(updateDataOnPan, 250));
            rsiChartDiv.on('plotly_click', handleRSILineClick);
        })
        .catch(err => console.error("Error plotting RSI chart:", err));
}

function loadRSILines() {
    const savedLines = localStorage.getItem('rsiLines');
    return savedLines ? JSON.parse(savedLines) : DEFAULT_RSI_LINES;
}

function saveRSILines(lines) {
    localStorage.setItem('rsiLines', JSON.stringify(lines));
}

function resetRSILines() {
    saveRSILines(DEFAULT_RSI_LINES);
    Plotly.relayout('rsi-chart', {
        shapes: DEFAULT_RSI_LINES.map(line => ({
            type: 'line',
            x0: 0,
            x1: 1,
            xref: 'paper',
            y0: line.value,
            y1: line.value,
            line: {
                color: line.color,
                width: 1,
                dash: 'dash',
            }
        }))
    });
}

function handleRSILineClick(event) {
    if (event.points[0].y >= 0 && event.points[0].y <= 100) {
        const value = Math.round(event.points[0].y);
        const color = prompt("Enter line color (e.g., #FF0000 for red):", "#FF69B4");
        if (color) {
            const rsiLines = loadRSILines();
            rsiLines.push({ value, color });
            saveRSILines(rsiLines);
            // Force an immediate update of the RSI chart
            Plotly.relayout('rsi-chart', {
                shapes: rsiLines.map(line => ({
                    type: 'line',
                    x0: 0,
                    x1: 1,
                    xref: 'paper',
                    y0: line.value,
                    y1: line.value,
                    line: {
                        color: line.color,
                        width: 1,
                        dash: 'dash',
                    }
                }))
            });
        }
    }
}

function cleanData(data) {
    return data.filter(d => 
        d.time && 
        !isNaN(parseFloat(d.close)) && 
        !isNaN(parseFloat(d.high)) && 
        !isNaN(parseFloat(d.low)) && 
        !isNaN(parseFloat(d.open)) &&
        !isNaN(parseFloat(d.RSI))
    ).map(d => ({
        time: d.time,
        open: parseFloat(d.open),
        high: parseFloat(d.high),
        low: parseFloat(d.low),
        close: parseFloat(d.close),
        Volume: parseFloat(d.Volume),
        RSI: parseFloat(d.RSI)
    }));
}

function updateActiveTimeframeButton(timeframe) {
    const buttons = document.querySelectorAll('.timeframe-btn');
    buttons.forEach(btn => {
        if (btn.dataset.timeframe === timeframe) {
            btn.classList.add('active');
        } else {
            btn.classList.remove('active');
        }
    });
}

function createCandlestickTrace(data) {
    return {
        x: data.map(d => new Date(d.time * 1000)),
        close: data.map(d => d.close),
        high: data.map(d => d.high),
        low: data.map(d => d.low),
        open: data.map(d => d.open),
        type: 'candlestick',
        xaxis: 'x',
        yaxis: 'y',
        increasing: { line: { color: '#53b987' }, fillcolor: '#53b987' },
        decreasing: { line: { color: '#eb4d5c' }, fillcolor: '#eb4d5c' },
        line: { width: 1 }  // Add this line to ensure wick visibility
    };
}

function updateChartLayout() {
    const showCrosshair = document.getElementById('crosshairToggle').checked;
    const showFloatingBubble = document.getElementById('floatingBubble2Toggle').checked;
    const autoScale = document.getElementById('autoScaleToggle').checked;

    const updatedLayout = {
        xaxis: {
            showspikes: showCrosshair,
            showline: true,
            linecolor: '#2a2e39',
            linewidth: 2,
            mirror: true
        },
        yaxis: {
            showspikes: showCrosshair,
            fixedrange: !autoScale,
            autorange: autoScale,
            showline: true,
            linecolor: '#2a2e39',
            linewidth: 2,
            mirror: true
        },
        hovermode: showFloatingBubble ? 'closest' : 'x unified'
    };

    Plotly.relayout('chart', updatedLayout);
    Plotly.relayout('rsi-chart', {
        ...updatedLayout,
        yaxis: {
            ...updatedLayout.yaxis,
            range: autoScale ? null : [0, 100]
        }
    });

    if (window.bufferedData) {
        updateCandlestickChart(window.bufferedData);
        updateRSIChart(window.bufferedData);
    }
}

function updateDataOnPan(event) {
    if (event['xaxis.range[0]'] && event['xaxis.range[1]']) {
        const newStart = new Date(event['xaxis.range[0]']).getTime() / 1000;
        const newEnd = new Date(event['xaxis.range[1]']).getTime() / 1000;
        
        console.log(`Panning to new range: ${newStart} to ${newEnd}`);
        
        fetchDataForRange(newStart, newEnd);
    }
}

function updateAllSubplots(data, startTime, endTime) {
    const update = {
        'x': [
            data.map(d => new Date(d.time * 1000)),
            data.map(d => new Date(d.time * 1000)),
            data.map(d => new Date(d.time * 1000))
        ],
        'open': [data.map(d => d.open)],
        'high': [data.map(d => d.high)],
        'low': [data.map(d => d.low)],
        'close': [data.map(d => d.close)],
        'y': [
            null,
            data.map(d => d.RSI),
            data.map(d => d.Volume)
        ]
    };

    const layout = {
        xaxis: {range: [new Date(startTime * 1000), new Date(endTime * 1000)]},
        xaxis2: {range: [new Date(startTime * 1000), new Date(endTime * 1000)]},
        xaxis3: {range: [new Date(startTime * 1000), new Date(endTime * 1000)]},
        yaxis: {domain: [0.6, 1], title: 'Price'},
        yaxis2: {domain: [0.3, 0.55], title: 'RSI'},
        yaxis3: {domain: [0, 0.25], title: 'Volume'}
    };

    Plotly.update('combined-chart', update, layout);
}

function fetchDataForRange(startTime, endTime) {
    showSpinner();
    const coin = document.getElementById('coin').value;
    const timeframe = getSelectedTimeframe();
    const url = `/api/data?coin=${coin}&timeframe=${timeframe}&start_time=${Math.floor(startTime)}&end_time=${Math.floor(endTime)}&limit=${DEFAULT_DATA_LENGTH}`;
    
    fetch(url)
        .then(response => response.json())
        .then(responseData => {
            if (responseData.error) {
                throw new Error(responseData.error);
            }
            const newData = cleanData(responseData.data);
            
            // Merge new data with existing buffered data
            window.bufferedData = mergeAndSortData(window.bufferedData || [], newData);
            
            // Update the data range
            window.dataRange = {
                start: Math.min(window.dataRange?.start || Infinity, responseData.min_time),
                end: Math.max(window.dataRange?.end || -Infinity, responseData.max_time)
            };
            
            console.log(`Updated buffer: ${window.bufferedData.length} data points`);
            console.log(`New data range: ${new Date(window.dataRange.start * 1000)} to ${new Date(window.dataRange.end * 1000)}`);
            
            // Update the chart with all buffered data
            updateCombinedChart(window.bufferedData);
        })
        .catch(error => {
            console.error('Error fetching data:', error);
            showErrorMessage('Failed to update data. Please try again.');
        })
        .finally(() => {
            hideSpinner();
        });
}

function addToCache(startTime, endTime, data) {
    const cacheKey = `${startTime}-${endTime}`;
    dataCache[cacheKey] = data;
}

function getFromCache(startTime, endTime) {
    const cacheKey = `${startTime}-${endTime}`;
    return dataCache[cacheKey];
}

function preloadData(coin, timeframe, startTime, endTime) {
    const chunks = [];
    const chunkSize = 86400; // 1 day in seconds
    for (let i = startTime; i < endTime; i += chunkSize) {
        const chunkEnd = Math.min(i + chunkSize, endTime);
        chunks.push(fetchDataChunkForRange(coin, timeframe, i, chunkEnd));
    }
    return Promise.all(chunks).then(results => {
        return results.flat();
    });
}

function fetchDataChunkForRange(startTime, endTime) {
    showSpinner();
    const coin = document.getElementById('coin').value;
    const timeframe = getSelectedTimeframe();
    
    const url = `/api/data?coin=${coin}&timeframe=${timeframe}&start_time=${startTime}&end_time=${endTime}`;
    
    fetch(url)
        .then(response => {
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            return response.json();
        })
        .then(data => {
            if (data.error) {
                throw new Error(data.error);
            }
            const newData = cleanData(data);
            window.bufferedData = mergeAndSortData(window.bufferedData, newData);
            updateCharts(window.bufferedData, startTime, endTime);
        })
        .catch(error => {
            console.error('Error fetching data chunk:', error);
        })
        .finally(() => {
            hideSpinner();
        });
}

function mergeAndSortData(oldData, newData) {
    const mergedData = [...oldData, ...newData];
    const uniqueData = Array.from(new Map(mergedData.map(item => [item.time, item])).values());
    return uniqueData.sort((a, b) => a.time - b.time);
}

function updateCharts(data, startTime, endTime) {
    updateCombinedChart(data, startTime, endTime);
}

function updateCombinedChart(data) {
    console.log(`Updating combined chart with ${data.length} data points`);
    const autoScale = document.getElementById('autoScaleToggle').checked;
    
    const traces = [
        // Candlestick trace
        {
            x: data.map(d => new Date(d.time * 1000)),
            close: data.map(d => d.close),
            high: data.map(d => d.high),
            low: data.map(d => d.low),
            open: data.map(d => d.open),
            type: 'candlestick',
            yaxis: 'y',
            name: 'Price'
        },
        // RSI trace
        {
            x: data.map(d => new Date(d.time * 1000)),
            y: data.map(d => d.RSI),
            type: 'scatter',
            line: { color: '#8A2BE2' },
            name: 'RSI',
            yaxis: 'y2'
        },
        // Volume trace
        {
            x: data.map(d => new Date(d.time * 1000)),
            y: data.map(d => d.Volume),
            type: 'bar',
            name: 'Volume',
            yaxis: 'y3'
        }
    ];

    const layout = {
        dragmode: 'pan',
        showlegend: false,
        grid: {rows: 3, columns: 1, pattern: 'independent', roworder: 'top to bottom'},
        yaxis: {domain: [0.6, 1], title: 'Price', autorange: autoScale},
        yaxis2: {domain: [0.3, 0.55], title: 'RSI', range: autoScale ? null : [0, 100]},
        yaxis3: {domain: [0, 0.25], title: 'Volume'},
        xaxis: {rangeslider: {visible: false}},
        plot_bgcolor: '#131722',
        paper_bgcolor: '#131722',
        font: { color: '#d1d4dc' },
    };

    Plotly.react('combined-chart', traces, layout, {responsive: true});
}

function updateCandlestickChart(data) {
    console.log("Entering updateCandlestickChart");
    const autoScale = document.getElementById('autoScaleToggle').checked;
    const chart = document.getElementById('chart');
    
    console.log("Auto Scale:", autoScale);
    console.log("Total data points:", data.length);

    let layout = {
        yaxis: {
            autorange: false,  // We'll manually set the range
            showline: true,
            linecolor: '#2a2e39',
            linewidth: 2,
            mirror: true
        }
    };

    if (autoScale && chart.layout.xaxis.range) {
        const [startTime, endTime] = chart.layout.xaxis.range.map(date => new Date(date).getTime() / 1000);
        console.log("Visible range:", new Date(startTime * 1000), "to", new Date(endTime * 1000));
        
        const visibleData = filterVisibleData(data, startTime, endTime);
        console.log("Visible data points:", visibleData.length);
        
        const yRange = calculateYRange(visibleData);
        console.log("Calculated Y range:", yRange);
        
        layout.yaxis.range = yRange;
    } else {
        // If auto-scale is off, use the current Y-axis range
        layout.yaxis.range = chart.layout.yaxis.range;
    }

    console.log("Setting Y-axis range:", layout.yaxis.range);

    Plotly.update('chart', {
        x: [data.map(d => new Date(d.time * 1000))],
        open: [data.map(d => d.open)],
        high: [data.map(d => d.high)],
        low: [data.map(d => d.low)],
        close: [data.map(d => d.close)]
    }, layout).then(() => {
        // Check if the update was applied correctly
        const updatedRange = chart.layout.yaxis.range;
        console.log("Updated Y-axis range:", updatedRange);
        if (JSON.stringify(updatedRange) !== JSON.stringify(layout.yaxis.range)) {
            console.warn("Y-axis range was not updated as expected");
            // Force the update if it wasn't applied
            Plotly.relayout('chart', {'yaxis.range': layout.yaxis.range});
        }
    });

    console.log("Exiting updateCandlestickChart");
}

function updateRSIChart(data) {
    const autoScale = document.getElementById('autoScaleToggle').checked;
    const chart = document.getElementById('rsi-chart');
    
    const layout = {
        yaxis: {
            autorange: autoScale,
            range: autoScale ? null : [0, 100],
            showline: true,
            linecolor: '#2a2e39',
            linewidth: 2,
            mirror: true
        }
    };

    if (autoScale && chart.layout.xaxis.range) {
        const [startTime, endTime] = chart.layout.xaxis.range.map(date => new Date(date).getTime() / 1000);
        const visibleData = filterVisibleData(data, startTime, endTime);
        const yRange = calculateRSIRange(visibleData);
        layout.yaxis.range = yRange;
    }

    Plotly.update('rsi-chart', {
        x: [data.map(d => new Date(d.time * 1000))],
        y: [data.map(d => d.RSI)]
    }, layout);
}

function getVisibleRange(chartId) {
    const chart = document.getElementById(chartId);
    const xaxis = chart.layout.xaxis;
    if (xaxis && xaxis.range) {
        return {
            start: new Date(xaxis.range[0]).getTime() / 1000,
            end: new Date(xaxis.range[1]).getTime() / 1000
        };
    }
    return null;
}

function filterVisibleData(data, start, end) {
    console.log("Filtering visible data");
    console.log("Start time:", new Date(start * 1000));
    console.log("End time:", new Date(end * 1000));
    const filteredData = data.filter(d => d.time >= start && d.time <= end);
    console.log("Filtered data points:", filteredData.length);
    return filteredData;
}

function calculateYRange(data) {
    const values = data.flatMap(d => [d.low, d.high]);
    const min = Math.min(...values);
    const max = Math.max(...values);
    const padding = (max - min) * 0.1;  // 10% padding
    return [min - padding, max + padding];
}

function calculateRSIRange(data) {
    const values = data.map(d => d.RSI);
    const min = Math.min(...values);
    const max = Math.max(...values);
    const padding = (max - min) * 0.1;
    return [Math.max(0, min - padding), Math.min(100, max + padding)];
}

function showSpinner() {
    document.getElementById('spinner').style.display = 'flex';
}

function hideSpinner() {
    document.getElementById('spinner').style.display = 'none';
}

function handleMissingData(coin, timeframe, startTime, endTime) {
    showErrorMessage(`No data available for ${coin} in ${timeframe} timeframe between ${new Date(startTime * 1000)} and ${new Date(endTime * 1000)}`);
    // Optionally, you could fetch data for a different timeframe or show placeholder data
}

function setupResizeHandle() {
    let isResizing = false;
    let startY;

    const container = document.getElementById('chart-container');
    const chart = document.getElementById('chart');
    const rsiChart = document.getElementById('rsi-chart');
    const handle = document.getElementById('resize-handle');

    handle.addEventListener('mousedown', startResize);

    function startResize(e) {
        isResizing = true;
        startY = e.clientY;
        document.addEventListener('mousemove', resize);
        document.addEventListener('mouseup', stopResize);
    }

    function resize(e) {
        if (!isResizing) return;
        
        const deltaY = e.clientY - startY;
        const containerHeight = container.offsetHeight;
        
        let newMainHeight = chart.offsetHeight + deltaY;
        let newRsiHeight = rsiChart.offsetHeight - deltaY;
        
        // Ensure minimum heights
        const minHeight = containerHeight * 0.1; // 10% of container height
        newMainHeight = Math.max(newMainHeight, minHeight);
        newRsiHeight = Math.max(newRsiHeight, minHeight);
        
        const mainRatio = newMainHeight / containerHeight;
        const rsiRatio = newRsiHeight / containerHeight;
        
        chart.style.flex = mainRatio;
        rsiChart.style.flex = rsiRatio;
        
        Plotly.Plots.resize('chart');
        Plotly.Plots.resize('rsi-chart');
        
        startY = e.clientY;
    }

    function stopResize() {
        isResizing = false;
        document.removeEventListener('mousemove', resize);
        document.removeEventListener('mouseup', stopResize);
    }
}

function saveUserProfile(settings) {
    localStorage.setItem('userProfile', JSON.stringify(settings));
}

function loadUserProfile() {
    const profile = JSON.parse(localStorage.getItem('userProfile'));
    if (profile) {
        document.getElementById('chart').style.height = `${profile.mainChartHeight}px`;
        document.getElementById('rsi-chart').style.height = `${profile.rsiChartHeight}px`;
    }
}

function showErrorMessage(message) {
    const errorDiv = document.createElement('div');
    errorDiv.className = 'error-message';
    errorDiv.textContent = `Error: ${message}`;
    document.body.appendChild(errorDiv);
    setTimeout(() => errorDiv.remove(), 5000);  // Remove after 5 seconds
}

function createCombinedChart(data, height) {
    const traces = [
        // Candlestick trace
        {
            x: data.map(d => new Date(d.time * 1000)),
            close: data.map(d => d.close),
            high: data.map(d => d.high),
            low: data.map(d => d.low),
            open: data.map(d => d.open),
            type: 'candlestick',
            yaxis: 'y',
            name: 'Price'
        },
        // RSI trace
        {
            x: data.map(d => new Date(d.time * 1000)),
            y: data.map(d => d.RSI),
            type: 'scatter',
            line: { color: '#8A2BE2' },
            name: 'RSI',
            yaxis: 'y2'
        },
        // Volume trace
        {
            x: data.map(d => new Date(d.time * 1000)),
            y: data.map(d => d.Volume),
            type: 'bar',
            name: 'Volume',
            yaxis: 'y3'
        }
    ];

    const layout = {
        height: height,
        dragmode: 'pan',
        showlegend: false,
        grid: {rows: 3, columns: 1, pattern: 'independent', roworder: 'top to bottom'},
        yaxis: {domain: [0.6, 1], title: 'Price'},
        yaxis2: {domain: [0.3, 0.55], title: 'RSI'},
        yaxis3: {domain: [0, 0.25], title: 'Volume'},
        xaxis: {rangeslider: {visible: false}},
        plot_bgcolor: '#131722',
        paper_bgcolor: '#131722',
        font: { color: '#d1d4dc' },
    };

    const config = {
        responsive: true,
        scrollZoom: true,
        displayModeBar: false,
    };

    Plotly.newPlot('combined-chart', traces, layout, config)
        .then(() => {
            console.log("Combined chart plotted successfully");
            const chartDiv = document.getElementById('combined-chart');
            chartDiv.on('plotly_relayout', debounce((event) => updateDataOnPan(event), 250));
        })
        .catch(err => console.error("Error plotting combined chart:", err));
}Why does my chart reset its zoom level every time I try to zoom in or out?
How can I fix a chart that returns to its original view whenever I attempt to pan across it?
What might be causing my interactive chart to snap back to the start when I'm trying to explore data?
Is there a common issue with charting libraries where the zoom or pan doesn't stick? How do I solve it?
When I use my chart's zoom feature, it reverts back immediately. What could be wrong?
How do I prevent my data visualization chart from resetting its range after user interaction?
Can you help me troubleshoot why my chart isn't maintaining its state after zooming or panning?
What are the steps to ensure that a chart maintains its zoom level or pan position in a web application?
I'm experiencing an auto-reset problem with my chart's zoom. How should I approach fixing this?
Why doesn't my chart library retain the new view settings after I pan or zoom, and what can I do about it?