import { INTERVALS, COLORS } from '../core/index.js';
import { calculateAllIndicatorSignals, calculateSummarySignal } from './signals-calculator.js';
import { calculateSignalMarkers } from './signal-markers.js';
import { updateIndicatorCandles } from './indicators-panel-new.js';
import { TimezoneConfig } from '../config/timezone.js';
import { DrawingManager } from './drawing-tools.js';

class MarkersRenderer {
    constructor(source) {
        this._source = source;
    }
    
    draw(target) {
        if (!this._source._chart || !this._source._series) return;
        
        target.useBitmapCoordinateSpace((scope) => {
            const ctx = scope.context;
            const series = this._source._series;
            const chart = this._source._chart;
            const markers = this._source._markers;
            
            const ratio = scope.horizontalPixelRatio;
            
            ctx.save();
            
            for (const marker of markers) {
                const timeCoordinate = chart.timeScale().timeToCoordinate(marker.time);
                if (timeCoordinate === null) continue;
                
                let price = marker.price || marker.value;
                
                if (!price && window.dashboard && window.dashboard.allData) {
                    const data = window.dashboard.allData.get(window.dashboard.currentInterval);
                    if (data) {
                        const candle = data.find(d => d.time === marker.time);
                        if (candle) {
                            price = marker.position === 'aboveBar' ? candle.high : candle.low;
                        }
                    }
                }
                
                if (!price) continue;
                
                const priceCoordinate = series.priceToCoordinate(price);
                if (priceCoordinate === null) continue;
                
                const x = timeCoordinate * ratio;
                const size = 5 * ratio;
                const margin = 15 * ratio;
                const isAbove = marker.position === 'aboveBar';
                const y = (isAbove ? priceCoordinate * ratio - margin : priceCoordinate * ratio + margin);
                
                ctx.fillStyle = marker.color || '#26a69a';
                ctx.beginPath();
                
                const shape = marker.shape || (isAbove ? 'arrowDown' : 'arrowUp');
                
                if (shape === 'arrowUp' || shape === 'triangleUp') {
                    ctx.moveTo(x, y - size);
                    ctx.lineTo(x - size, y + size);
                    ctx.lineTo(x + size, y + size);
                } else if (shape === 'arrowDown' || shape === 'triangleDown') {
                    ctx.moveTo(x, y + size);
                    ctx.lineTo(x - size, y - size);
                    ctx.lineTo(x + size, y - size);
                } else if (shape === 'circle') {
                    ctx.arc(x, y, size, 0, Math.PI * 2);
                } else if (shape === 'square') {
                    ctx.rect(x - size, y - size, size * 2, size * 2);
                } else if (shape === 'custom' && marker.text) {
                    ctx.font = `${Math.round(14 * ratio)}px Arial`;
                    ctx.textAlign = 'center';
                    ctx.textBaseline = 'middle';
                    ctx.fillText(marker.text, x, y);
                    continue;
                }
                ctx.fill();
            }
            ctx.restore();
        });
    }
}

class MarkersPaneView {
    constructor(source) {
        this._source = source;
    }
    
    renderer() {
        return new MarkersRenderer(this._source);
    }
    
    zOrder() {
        return 'top';
    }
}

export class SeriesMarkersPrimitive {
    constructor(markers) {
        this._markers = markers || [];
        this._paneViews = [new MarkersPaneView(this)];
    }
    
    setMarkers(markers) {
        this._markers = markers;
        if (this._requestUpdate) {
            this._requestUpdate();
        }
    }
    
    attached(param) {
        this._chart = param.chart;
        this._series = param.series;
        this._requestUpdate = param.requestUpdate;
        this._requestUpdate();
    }
    
    detached() {
        this._chart = undefined;
        this._series = undefined;
        this._requestUpdate = undefined;
    }
    
    updateAllViews() {
        this._requestUpdate?.();
    }
    
    paneViews() {
        return this._paneViews;
    }
}

function formatDate(timestamp) {
    return TimezoneConfig.formatDate(timestamp);
}

function throttle(func, limit) {
    let inThrottle;
    return function() {
        const args = arguments;
        const context = this;
        if (!inThrottle) {
            func.apply(context, args);
            inThrottle = true;
            setTimeout(() => inThrottle = false, limit);
        }
    }
}

export class TradingDashboard {
    constructor() {
        this.chart = null;
        this.candleSeries = null;
        this.currentChartType = localStorage.getItem('winterfail_chart_type') || 'candlestick';
        
        this.symbol = localStorage.getItem('winterfail_symbol') || 'BTC';
        this.currentInterval = localStorage.getItem('winterfail_interval') || '1d';

        this.intervals = INTERVALS;
        this.allData = new Map();
        this.isLoading = false;
        this.hasInitialLoad = false;
        this.taData = null;
        this.indicatorSignals = [];
        this.summarySignal = null;
        this.lastCandleTimestamp = null;
        this.simulationMarkers = [];
        this.avgPriceSeries = null;
        this.dailyMAData = new Map();
        this.currentMouseTime = null;
        this.drawingManager = null;
        this.seriesMap = {};

        this.throttledOnVisibleRangeChange = throttle(this.onVisibleRangeChange.bind(this), 150);

        this.init();
    }
    async loadDailyMAData() {
        try {
            const interval = '1d';
            let candles = this.allData.get(interval);
            
            if (!candles || candles.length < 125) {
                const response = await fetch(`${window.APP_CONFIG.API_BASE_URL}/candles?symbol=${this.symbol}&interval=${interval}&limit=1000`);
                const data = await response.json();
                if (data.candles && data.candles.length > 0) {
                    candles = data.candles.reverse().map(c => ({
                        time: Math.floor(new Date(c.time).getTime() / 1000),
                        open: parseFloat(c.open),
                        high: parseFloat(c.high),
                        low: parseFloat(c.low),
                        close: parseFloat(c.close)
                    }));
                    this.allData.set(interval, candles);
                }
            }

            if (candles && candles.length >= 44) {
                const ma44 = this.calculateSimpleSMA(candles, 44);
                const ma125 = this.calculateSimpleSMA(candles, 125);
                
                this.dailyMAData.clear();
                candles.forEach((c, i) => {
                    this.dailyMAData.set(c.time, {
                        price: c.close,
                        ma44: ma44[i],
                        ma125: ma125[i]
                    });
                });
            }
        } catch (error) {
            console.error('[DailyMA] Error:', error);
        }
    }

    calculateSimpleSMA(candles, period) {
        const results = new Array(candles.length).fill(null);
        let sum = 0;
        for (let i = 0; i < candles.length; i++) {
            sum += candles[i].close;
            if (i >= period) sum -= candles[i - period].close;
            if (i >= period - 1) results[i] = sum / period;
        }
        return results;
    }

    setSimulationMarkers(markers) {
        this.simulationMarkers = markers || [];
        this.updateSignalMarkers();
    }

    clearSimulationMarkers() {
        this.simulationMarkers = [];
        this.updateSignalMarkers();
    }

    setAvgPriceData(data) {
        if (this.avgPriceSeries) {
            this.chart.removeSeries(this.avgPriceSeries);
        }
        
        this.avgPriceSeries = this.chart.addSeries(LightweightCharts.LineSeries, {
            lineWidth: 2,
            lineStyle: LightweightCharts.LineStyle.Solid,
            lastValueVisible: true,
            priceLineVisible: false,
            crosshairMarkerVisible: false,
            title: 'Avg Price',
        });
        
        this.avgPriceSeries.setData(data || []);
    }

    clearAvgPriceData() {
        if (this.avgPriceSeries) {
            this.avgPriceSeries.setData([]);
        }
    }
    
    init() {
        this.createTimeframeButtons();
        this.createChartTypeButtons();
        this.initChart();
        this.initEventListeners();
        this.loadInitialData();
        
        setInterval(() => {
            this.loadNewData();
            this.loadStats();
            if (new Date().getSeconds() < 15) this.loadTA();
        }, 10000);
    }

    isAtRightEdge() {
        const timeScale = this.chart.timeScale();
        const visibleRange = timeScale.getVisibleLogicalRange();
        if (!visibleRange) return true;
        
        const data = this.candleSeries.data();
        if (!data || data.length === 0) return true;
        
        return visibleRange.to >= data.length - 5;
    }
    
    createTimeframeButtons() {
        const container = document.getElementById('timeframeContainer');
        container.innerHTML = '';
        this.intervals.forEach(interval => {
            const btn = document.createElement('button');
            btn.className = 'timeframe-btn';
            btn.dataset.interval = interval;
            btn.textContent = interval;
            if (interval === this.currentInterval) {
                btn.classList.add('active');
            }
            btn.addEventListener('click', () => this.switchTimeframe(interval));
            container.appendChild(btn);
        });
    }
    
      createChartTypeButtons() {
            const container = document.querySelector('.flex.space-x-1:not(#timeframeContainer)');
            if (!container) return;
            
            const chartTypes = [
                { 
                    type: 'candlestick', 
                    icon: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M7 5v3M7 16v3M17 3v2M17 11v4"/><rect x="5" y="8" width="4" height="8" rx="0.5"/><rect x="15" y="5" width="4" height="6" rx="0.5"/></svg>`, 
                    name: 'Candlestick' 
                },
                { 
                    type: 'line', 
                    icon: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 17l6-6 4 4 8-8"/></svg>`, 
                    name: 'Line' 
                },
                { 
                    type: 'bar', 
                    icon: `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M7 5v14M7 10H5M7 15h2M17 5v14M17 7h-2M17 12h2"/></svg>`, 
                    name: 'Bar' 
                }
            ];
            
            container.innerHTML = '';
            chartTypes.forEach(chartType => {
                const btn = document.createElement('button');
                btn.className = 'chart-type-btn w-10 h-10 flex items-center justify-center text-gray-400 hover:text-white hover:bg-[#2d3a4f] rounded transition-colors';
                btn.dataset.chartType = chartType.type;
                btn.innerHTML = chartType.icon;
                btn.title = chartType.name;
                if (chartType.type === this.currentChartType) {
                    btn.classList.add('active');
                }
                btn.addEventListener('click', () => this.switchChartType(chartType.type));
                container.appendChild(btn);
            });
        }
    
    initChart() {
        const chartContainer = document.getElementById('chart');
        
        this.chart = LightweightCharts.createChart(chartContainer, {
            layout: {
                background: { color: COLORS.tvBg },
                textColor: COLORS.tvText,
                panes: {
                    background: { color: COLORS.tvPanelBg },
                    separatorColor: COLORS.tvBorder,
                    separatorHoverColor: COLORS.tvHover,
                    enableResize: true
                }
            },
            grid: {
                vertLines: { color: '#1e293b' },
                horzLines: { color: '#1e293b' },
            },
            rightPriceScale: {
                borderColor: COLORS.tvBorder,
                autoScale: true,
                mode: 0,
                scaleMargins: {
                    top: 0.1,
                    bottom: 0.1,
                },
            },
            timeScale: {
                borderColor: COLORS.tvBorder,
                timeVisible: true,
                secondsVisible: false,
                rightOffset: 12,
                barSpacing: 10,
                tickMarkFormatter: (time, tickMarkType, locale) => {
                    return TimezoneConfig.formatTickMark(time);
                },
            },
            localization: {
                timeFormatter: (timestamp) => {
                    return TimezoneConfig.formatDate(timestamp * 1000);
                },
            },
            handleScroll: {
                 mouseWheel: true,
                 pressedMouseMove: true,
                 horzTouchDrag: true,
                 vertTouchDrag: true,
            },
            handleScale: {
                  axisPressedMouseMove: true,
                  mouseWheel: true,
                  pinch: true,
              },
            crosshair: {
                mode: LightweightCharts.CrosshairMode.Normal,
            },
            });
         const priceInput = document.getElementById("priceFormatInput");
         
         let savedPrecision = parseInt(localStorage.getItem('winterfail_price_precision'));
         if (isNaN(savedPrecision)) savedPrecision = 2;
         
         if (priceInput) priceInput.value = savedPrecision;
         
         if (priceInput) {
             priceInput.addEventListener("input", (e) => {
                 let precision = parseInt(e.target.value);
                 if (isNaN(precision)) precision = 2;
                 if (precision < 0) precision = 0;
                 if (precision > 8) precision = 8;
                 
                 localStorage.setItem('winterfail_price_precision', precision);
                 
                 const minMove = precision === 0 ? 1 : Number((1 / Math.pow(10, precision)).toFixed(precision));
                 
                 this.candleSeries.applyOptions({
                     priceFormat: { type: "price", precision: precision, minMove: minMove }
                 });
             });
         }
         
         const savedUpColor = localStorage.getItem('winterfail_candle_up') || '#ff9800';
         const savedDownColor = localStorage.getItem('winterfail_candle_down') || '#ff9800';
         
         const candleUpInput = document.getElementById('candleUpColor');
         const candleDownInput = document.getElementById('candleDownColor');
         
         if (candleUpInput && this.currentChartType === 'candlestick') candleUpInput.value = savedUpColor;
          if (candleDownInput && this.currentChartType === 'candlestick') candleDownInput.value = savedDownColor;
         
         const initialMinMove = savedPrecision === 0 ? 1 : Number((1 / Math.pow(10, savedPrecision)).toFixed(savedPrecision));

          this.candleSeries = this.addSeriesByType(this.currentChartType);
          
          if (this.currentChartType === 'line') {
              this.candleSeries.setData([]);
          }
         
         if (this.currentChartType === 'candlestick' || this.currentChartType === 'bar') {
             if (candleUpInput) {
                 candleUpInput.addEventListener('input', (e) => {
                     const color = e.target.value;
                     localStorage.setItem('winterfail_candle_up', color);
                     this.applyColorToChartType(color, 'up');
                 });
             }
             
             if (candleDownInput) {
                 candleDownInput.addEventListener('input', (e) => {
                     const color = e.target.value;
                     localStorage.setItem('winterfail_candle_down', color);
                     this.applyColorToChartType(color, 'down');
                 });
             }
             
             if (this.candleSeries) {
                 this.currentPriceLine = this.candleSeries.createPriceLine({
                     price: 0,
                     color: '#26a69a',
                     lineWidth: 1,
                     lineStyle: LightweightCharts.LineStyle.Dotted,
                     axisLabelVisible: true,
                     title: '',
                 });
             }
         }
         
         this.addAvgPriceSeries();
    
        this.initPriceScaleControls();
        this.initNavigationControls();

        this.drawingManager = new DrawingManager(this, chartContainer);
        window.activateDrawingTool = (tool, event) => {
            const e = event || window.event;
            this.drawingManager.setTool(tool, e);
        };

        document.addEventListener("DOMContentLoaded", () => {
            const priceSelect = document.getElementById("priceFormatSelect");
            if (priceSelect) {
                priceSelect.addEventListener("change", (e) => {
                    const precision = parseInt(e.target.value);
                    this.chart.priceScale().applyOptions({
                        priceFormat: { type: "price", precision: precision, minMove: precision===0 ? 1 : 0.0001 }
                    });
                });
            }
        });
        
        this.chart.timeScale().subscribeVisibleLogicalRangeChange(this.onVisibleRangeChange.bind(this));
        
        this.chart.subscribeCrosshairMove(param => {
            if (param.time) {
                this.currentMouseTime = param.time;
                this.renderTA();
            } else {
                this.currentMouseTime = null;
                this.renderTA();
            }
        });
        
        this.chart.subscribeClick(param => {
            window.hideAllPanels?.();
        });

        window.addEventListener('resize', () => {
            this.chart.applyOptions({
                width: chartContainer.clientWidth,
                height: chartContainer.clientHeight,
            });
        });

        document.addEventListener('visibilitychange', () => {
            if (document.visibilityState === 'visible') {
                this.loadNewData();
                this.loadTA();
            }
        });
        window.addEventListener('focus', () => {
            this.loadNewData();
            this.loadTA();
        });
    }
    
    initPriceScaleControls() {
        const btnSettings = document.getElementById('btnSettings');
        const settingsPopup = document.getElementById('settingsPopup');
        
        if (btnSettings && settingsPopup) {
            btnSettings.addEventListener('click', (e) => {
                e.stopPropagation();
                settingsPopup.classList.toggle('hidden');
            });
            
            document.addEventListener('click', closeSettingsPopup);
            document.addEventListener('touchstart', closeSettingsPopup, { passive: true });
            
            function closeSettingsPopup(e) {
                const isInside = settingsPopup.contains(e.target) || e.target === btnSettings;
                const isSettingsButton = e.target.closest('#btnSettings');
                
                if (!isInside && !isSettingsButton) {
                    settingsPopup.classList.add('hidden');
                }
            }
        }
        
        this.scaleState = {
            autoScale: localStorage.getItem('winterfail_scale_auto') !== 'false',
            invertScale: localStorage.getItem('winterfail_scale_invert') === 'true',
            scaleMode: parseInt(localStorage.getItem('winterfail_scale_mode')) || 0
        };

        const updateCheckmark = (id, active) => {
            const el = document.getElementById(id);
            if (el) el.textContent = active ? '✓' : '';
        };

        const updateUI = () => {
            updateCheckmark('autoScaleCheck', this.scaleState.autoScale);
            updateCheckmark('invertScaleCheck', this.scaleState.invertScale);
            updateCheckmark('modeNormalCheck', this.scaleState.scaleMode === 0);
            updateCheckmark('modeLogCheck', this.scaleState.scaleMode === 1);
            updateCheckmark('modePercentCheck', this.scaleState.scaleMode === 2);
            updateCheckmark('modeIndexedCheck', this.scaleState.scaleMode === 3);
            
            this.candleSeries.priceScale().applyOptions({
                autoScale: this.scaleState.autoScale,
                invertScale: this.scaleState.invertScale,
                mode: this.scaleState.scaleMode
            });
        };

        updateUI();

        window.toggleScaleOption = (option) => {
            this.scaleState[option] = !this.scaleState[option];
            localStorage.setItem(`winterfail_scale_${option}`, this.scaleState[option]);
            updateUI();
        };

        window.setScaleMode = (mode) => {
            this.scaleState.scaleMode = mode;
            localStorage.setItem('winterfail_scale_mode', mode);
            updateUI();
        };

        document.addEventListener('keydown', (e) => {
            if (e.target.tagName === 'INPUT' || e.target.tagName === 'BUTTON') return;
            
            if (e.key.toLowerCase() === 'a') {
                window.toggleScaleOption('autoScale');
            } else if (e.key.toLowerCase() === 'l') {
                const newMode = this.scaleState.scaleMode === 1 ? 0 : 1;
                window.setScaleMode(newMode);
            }
        });
    }
    
    initNavigationControls() {
        const chartWrapper = document.getElementById('chartWrapper');
        const navLeft = document.getElementById('navLeft');
        const navRight = document.getElementById('navRight');
        const navRecent = document.getElementById('navRecent');
        
        if (!chartWrapper || !navLeft || !navRight || !navRecent) return;
        
        chartWrapper.addEventListener('mousemove', (e) => {
            const rect = chartWrapper.getBoundingClientRect();
            const distanceFromBottom = rect.bottom - e.clientY;
            chartWrapper.classList.toggle('show-nav', distanceFromBottom < 30);
        });
        
        chartWrapper.addEventListener('mouseleave', () => {
            chartWrapper.classList.remove('show-nav');
        });
        
        navLeft.addEventListener('click', () => this.navigateLeft());
        navRight.addEventListener('click', () => this.navigateRight());
        navRecent.addEventListener('click', () => this.navigateToRecent());
    }
    
    navigateLeft() {
        const visibleRange = this.chart.timeScale().getVisibleLogicalRange();
        if (!visibleRange) return;
        
        const visibleBars = visibleRange.to - visibleRange.from;
        const shift = visibleBars * 0.8;
        const newFrom = visibleRange.from - shift;
        const newTo = visibleRange.to - shift;
        
        this.chart.timeScale().setVisibleLogicalRange({ from: newFrom, to: newTo });
    }
    
    navigateRight() {
        const visibleRange = this.chart.timeScale().getVisibleLogicalRange();
        if (!visibleRange) return;
        
        const visibleBars = visibleRange.to - visibleRange.from;
        const shift = visibleBars * 0.8;
        const newFrom = visibleRange.from + shift;
        const newTo = visibleRange.to + shift;
        
        this.chart.timeScale().setVisibleLogicalRange({ from: newFrom, to: newTo });
    }
    
    navigateToRecent() {
        this.chart.timeScale().scrollToRealTime();
    }
    
    initEventListeners() {
        this.initChartTypeListeners();
        
        document.addEventListener('keydown', (e) => {
            if (e.target.tagName === 'INPUT' || e.target.tagName === 'BUTTON') return;
            
            const shortcuts = {
                '1': '1m', '2': '3m', '3': '5m', '4': '15m', '5': '30m', '7': '37m',
                '6': '1h', '8': '4h', '9': '8h', '0': '12h',
                'd': '1d', 'D': '1d', 'w': '1w', 'W': '1w', 'm': '1M', 'M': '1M'
            };
            
            if (shortcuts[e.key]) {
                this.switchTimeframe(shortcuts[e.key]);
            }
            
            if (e.key === 'ArrowLeft') {
                this.navigateLeft();
            } else if (e.key === 'ArrowRight') {
                this.navigateRight();
            } else if (e.key === 'ArrowUp') {
                this.navigateToRecent();
            }
        });
    }
    
    initChartTypeListeners() {
        document.addEventListener('click', (e) => {
            const btn = e.target.closest('.chart-type-btn');
            if (!btn) return;
            
            const chartType = btn.dataset.chartType;
            if (chartType) {
                this.switchChartType(chartType);
            }
        });
    }
    
    clearIndicatorCaches(clearSignalState = false) {
        const activeIndicators = window.getActiveIndicators?.() || [];
        activeIndicators.forEach(indicator => {
            indicator.cachedResults = null;
            indicator.cachedMeta = null;
            
            if (clearSignalState) {
                indicator.lastSignalTimestamp = null;
                indicator.lastSignalType = null;
            }
        });
        console.log(`[Dashboard] Cleared caches for ${activeIndicators.length} indicators (signals: ${clearSignalState})`);
    }
    
    async loadInitialData() {
        await Promise.all([
            this.loadData(2000, true),
            this.loadStats(),
            this.loadDailyMAData()
        ]);
        this.hasInitialLoad = true;
        this.loadTA();
    }
    
    async loadData(limit = 1000, fitToContent = false) {
        if (this.isLoading) return;
        this.isLoading = true;
        
        try {
            const visibleRange = this.chart.timeScale().getVisibleLogicalRange();
            
            const response = await fetch(`${window.APP_CONFIG.API_BASE_URL}/candles?symbol=BTC&interval=${this.currentInterval}&limit=${limit}`);
            const data = await response.json();
            
            if (data.candles && data.candles.length > 0) {
                const chartData = data.candles.reverse().map(c => ({
                    time: Math.floor(new Date(c.time).getTime() / 1000),
                    open: parseFloat(c.open),
                    high: parseFloat(c.high),
                    low: parseFloat(c.low),
                    close: parseFloat(c.close),
                    volume: parseFloat(c.volume || 0)
                }));
                
                const existingData = this.allData.get(this.currentInterval) || [];
                const mergedData = this.mergeData(existingData, chartData);
                this.allData.set(this.currentInterval, mergedData);
                
                if (!this.candleSeries) {
                    console.error('[Chart] Candle series not initialized');
                    return;
                }
                
                if (fitToContent) {
                    this.chart.timeScale().scrollToRealTime();
                } else if (visibleRange) {
                    this.chart.timeScale().setVisibleLogicalRange(visibleRange);
                }
                
                if ((this.currentChartType === 'candlestick' || this.currentChartType === 'bar') && 
                    mergedData.length > 0 && 
                    mergedData[0].hasOwnProperty('open')) {
                    this.candleSeries.setData(mergedData);
                } else if (this.currentChartType === 'line' && 
                            mergedData.length > 0 && 
                            mergedData[0].hasOwnProperty('close')) {
                     const closePrices = mergedData.map(c => ({
                         time: c.time,
                         value: c.close
                     }));
                     this.candleSeries.setData(closePrices);
                } else if (mergedData.length > 0 && mergedData[0].hasOwnProperty('value')) {
                    this.candleSeries.setData(mergedData);
                } else if (mergedData.length > 0) {
                    const closePrices = mergedData.map(c => ({
                        time: c.time,
                        value: c.close || c.value
                    }));
                    this.candleSeries.setData(closePrices);
                }
                
                const latest = mergedData[mergedData.length - 1];
                this.updateStats(latest);
            }
            
            window.drawIndicatorsOnChart?.();
        } catch (error) {
            console.error('Error loading data:', error);
        } finally {
            this.isLoading = false;
        }
    }
    
    async loadNewData() {
        if (!this.hasInitialLoad || this.isLoading) return;
        
        try {
            const response = await fetch(`${window.APP_CONFIG.API_BASE_URL}/candles?symbol=BTC&interval=${this.currentInterval}&limit=50`);
            const data = await response.json();
            
            if (!this.candleSeries) {
                console.error('[Chart] Candle series not initialized');
                return;
            }
            
            if (data.candles && data.candles.length > 0) {
                const atEdge = this.isAtRightEdge();
                
                const currentSeriesData = this.candleSeries.data();
                const lastTimestamp = currentSeriesData.length > 0 
                    ? currentSeriesData[currentSeriesData.length - 1].time 
                    : 0;

                const chartData = data.candles.reverse().map(c => ({
                    time: Math.floor(new Date(c.time).getTime() / 1000),
                    open: parseFloat(c.open),
                    high: parseFloat(c.high),
                    low: parseFloat(c.low),
                    close: parseFloat(c.close),
                    volume: parseFloat(c.volume || 0)
                }));
                
                const latest = chartData[chartData.length - 1];
                
                const isNewCandle = this.lastCandleTimestamp !== null && latest.time > this.lastCandleTimestamp;
                
                if (isNewCandle) {
                    console.log(`[NewData Load] New candle detected: ${this.lastCandleTimestamp} -> ${latest.time}`);
                    this.clearIndicatorCaches(false);
                }
                
                this.lastCandleTimestamp = latest.time;
                
                if (this.currentChartType === 'candlestick' || this.currentChartType === 'bar') {
                    chartData.forEach(candle => {
                        if (candle.time >= lastTimestamp && 
                            !Number.isNaN(candle.time) && 
                            !Number.isNaN(candle.open) && 
                            !Number.isNaN(candle.high) && 
                            !Number.isNaN(candle.low) && 
                            !Number.isNaN(candle.close)) {
                            this.candleSeries.update(candle);
                        }
                    });
                } else if (this.currentChartType === 'line') {
                     const closePrices = chartData.map(c => ({
                         time: c.time,
                         value: c.close
                     }));
                     
                     const existingData = this.candleSeries.data();
                     const existingTimeSet = new Set(existingData.map(d => d.time));
                     
                     const newDataToAppend = closePrices.filter(c => !existingTimeSet.has(c.time));
                     
                     if (newDataToAppend.length > 0) {
                         if (existingData.length === 0) {
                             this.candleSeries.setData(closePrices);
                         } else {
                             newDataToAppend.forEach(point => {
                                 this.candleSeries.update(point);
                             });
                         }
                     }
                 }
                
                const existingData = this.allData.get(this.currentInterval) || [];
                this.allData.set(this.currentInterval, this.mergeData(existingData, chartData));
                
                this.updateStats(latest);
                
                window.drawIndicatorsOnChart?.();
                window.updateIndicatorCandles?.();
                
                this.loadDailyMAData();
                await this.loadSignals();
            }
        } catch (error) {
            console.error('Error loading new data:', error);
        }
    }
    
    mergeData(existing, newData) {
        const dataMap = new Map();
        existing.forEach(c => dataMap.set(c.time, c));
        newData.forEach(c => dataMap.set(c.time, c));
        return Array.from(dataMap.values()).sort((a, b) => a.time - b.time);
    }
    
    onVisibleRangeChange() {
        if (!this.hasInitialLoad || this.isLoading) {
            return;
        }
        
        const visibleRange = this.chart.timeScale().getVisibleLogicalRange();
        if (!visibleRange) {
            return;
        }
        
        const data = this.candleSeries.data();
        const allData = this.allData.get(this.currentInterval);
        
        if (!data || data.length === 0) {
            return;
        }
        
        const visibleBars = Math.ceil(visibleRange.to - visibleRange.from);
        const bufferSize = visibleBars * 2;
        const refillThreshold = bufferSize * 0.8;
        const barsFromLeft = Math.floor(visibleRange.from);
        const visibleOldestTime = data[Math.floor(visibleRange.from)]?.time;
        const visibleNewestTime = data[Math.ceil(visibleRange.to)]?.time;
        
        console.log(`[VisibleRange] Visible: ${visibleBars} bars (${data.length} in chart, ${allData?.length || 0} in dataset)`);
        console.log(`[VisibleRange] Time range: ${new Date((visibleOldestTime || 0) * 1000).toLocaleDateString()} to ${new Date((visibleNewestTime || 0) * 1000).toLocaleDateString()}`);
        
        if (barsFromLeft < refillThreshold) {
            console.log(`Buffer low (${barsFromLeft} < ${refillThreshold.toFixed(0)}), prefetching ${bufferSize} candles...`);
            const oldestCandle = data[0];
            if (oldestCandle) {
                this.loadHistoricalData(oldestCandle.time, bufferSize);
            }
        }
        
        if (data.length !== allData?.length) {
            console.log(`[VisibleRange] Chart data (${data.length}) vs dataset (${allData?.length || 0}) differ, redrawing indicators...`);
        }
        
        this.loadSignals().catch(e => console.error('Error loading signals:', e));
    }
    
    async loadHistoricalData(beforeTime, limit = 1000) {
        if (this.isLoading) {
            return;
        }
        this.isLoading = true;
        
        console.log(`[Historical] Loading historical data before ${new Date(beforeTime * 1000).toLocaleDateString()}, limit=${limit}`);
        
        try {
            const endTime = new Date((beforeTime - 1) * 1000);
            
            const response = await fetch(
                `${window.APP_CONFIG.API_BASE_URL}/candles?symbol=BTC&interval=${this.currentInterval}&end=${endTime.toISOString()}&limit=${limit}`
            );
            
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            
            const data = await response.json();
            
            if (data.candles && data.candles.length > 0) {
                const chartData = data.candles.reverse().map(c => ({
                    time: Math.floor(new Date(c.time).getTime() / 1000),
                    open: parseFloat(c.open),
                    high: parseFloat(c.high),
                    low: parseFloat(c.low),
                    close: parseFloat(c.close),
                    volume: parseFloat(c.volume || 0)
                }));
                
                const existingData = this.allData.get(this.currentInterval) || [];
                 const mergedData = this.mergeData(existingData, chartData);
                 this.allData.set(this.currentInterval, mergedData);
                 
                 console.log(`[Historical] SUCCESS: Added ${chartData.length} candles`);
                 console.log(`[Historical] Total candles in dataset: ${mergedData.length}`);
                 console.log(`[Historical] Oldest: ${new Date(mergedData[0]?.time * 1000).toLocaleDateString()}`);
                 console.log(`[Historical] Newest: ${new Date(mergedData[mergedData.length - 1]?.time * 1000).toLocaleDateString()}`);
                 
                 if (this.currentChartType === 'candlestick' || this.currentChartType === 'bar') {
                     if (mergedData.length > 0 && mergedData[0].hasOwnProperty('open')) {
                         this.candleSeries.setData(mergedData);
                     } else {
                         const ohlcData = mergedData.map(c => ({
                             time: c.time,
                             open: c.value,
                             high: c.value,
                             low: c.value,
                             close: c.value
                         }));
                         this.candleSeries.setData(ohlcData);
                     }
                 } else {
                     if (mergedData.length > 0 && mergedData[0].hasOwnProperty('close')) {
                         const closePrices = mergedData.map(c => ({
                             time: c.time,
                             value: c.close
                         }));
                         this.candleSeries.setData(closePrices);
                     } else if (mergedData.length > 0) {
                         this.candleSeries.setData(mergedData);
                     }
                 }
                
                console.log(`[Historical] Recalculating indicators...`);
                window.drawIndicatorsOnChart?.();
                await this.loadSignals();
                
                console.log(`[Historical] Indicators recalculated for ${mergedData.length} candles`);
            } else {
                console.log('[Historical] No more historical data available from database');
            }
        } catch (error) {
            console.error('[Historical] Error loading historical data:', error);
        } finally {
            this.isLoading = false;
        }
    }
    
    async loadTA() {
        if (!this.hasInitialLoad) {
            const time = new Date().toLocaleTimeString();
            document.getElementById('taContent').innerHTML = `<div class="ta-loading">Loading technical analysis... ${time}</div>`;
            return;
        }
        
        try {
            const response = await fetch(`${window.APP_CONFIG.API_BASE_URL}/ta?symbol=BTC&interval=${this.currentInterval}`);
            const data = await response.json();
            
            if (data.error) {
                document.getElementById('taContent').innerHTML = `<div class="ta-error">${data.error}</div>`;
                return;
            }
            
            this.taData = data;
            await this.loadSignals();
            this.renderTA();
        } catch (error) {
            console.error('Error loading TA:', error);
            document.getElementById('taContent').innerHTML = '<div class="ta-error">Failed to load technical analysis. Please check if the database has candle data.</div>';
        }
    }
    
    async loadSignals() {
        try {
            this.indicatorSignals = calculateAllIndicatorSignals();
            this.summarySignal = calculateSummarySignal(this.indicatorSignals);
            this.updateSignalMarkers();
        } catch (error) {
            console.error('Error loading signals:', error);
            this.indicatorSignals = [];
            this.summarySignal = null;
        }
    }
    
    updateSignalMarkers() {
        const candles = this.allData.get(this.currentInterval);
        if (!candles || candles.length === 0) return;
        
        let markers = calculateSignalMarkers(candles);
        
        if (this.simulationMarkers && this.simulationMarkers.length > 0) {
            markers = [...markers, ...this.simulationMarkers];
        }
        
        markers = markers.filter(m => m && m.time !== null && m.time !== undefined && !isNaN(m.time));
        
        markers.sort((a, b) => a.time - b.time);
        
        try {
            if (!this.markerPrimitive) {
                this.markerPrimitive = new SeriesMarkersPrimitive();
                this.candleSeries.attachPrimitive(this.markerPrimitive);
            }
            this.markerPrimitive.setMarkers(markers);
        } catch (e) {
            console.warn('[SignalMarkers] setMarkers primitive error:', e.message);
        }
    }
    
    renderTA() {
        if (!this.taData || this.taData.error) {
            document.getElementById('taContent').innerHTML = `<div class="ta-error">${this.taData?.error || 'No data available'}</div>`;
            return;
        }
        
        const data = this.taData;
        const trendClass = data.trend.direction.toLowerCase();
        const signalClass = data.trend.signal.toLowerCase();
        
        document.getElementById('taInterval').textContent = this.currentInterval.toUpperCase();
        document.getElementById('taLastUpdate').textContent = new Date().toLocaleTimeString();
        
        const summary = this.summarySignal || {};
        const summarySignalClass = summary.signal || 'hold';
        
        const signalsHtml = this.indicatorSignals?.length > 0 ? this.indicatorSignals.map(indSignal => {
            const signalIcon = indSignal.signal === 'buy' ? '🟢' : indSignal.signal === 'sell' ? '🔴' : '⚪';
            const signalColor = indSignal.signal === 'buy' ? '#26a69a' : indSignal.signal === 'sell' ? '#ef5350' : '#787b86';
            const lastSignalDate = indSignal.lastSignalDate ? formatDate(indSignal.lastSignalDate * 1000) : '-';
            
            let paramsStr = '';
            if (indSignal.params !== null && indSignal.params !== undefined) {
                paramsStr = `(${indSignal.params})`;
            }
            
            return `
                <div class="ta-ma-row" style="border-bottom: none; padding: 6px 0; align-items: center;">
                    <span class="ta-ma-label">${indSignal.name}${paramsStr}</span>
                    <span class="ta-ma-value" style="display: flex; align-items: center; gap: 8px;">
                        <span style="font-size: 11px; padding: 2px 8px; min-width: 60px; text-align: center; background: ${signalColor}; color: white; border-radius: 3px;">${signalIcon} ${indSignal.signal.toUpperCase()}</span>
                        <span style="font-size: 10px; color: var(--tv-text-secondary);">${lastSignalDate}</span>
                    </span>
                </div>
            `;
        }).join('') : '';
        
        const summaryBadge = '';
        
        let displayMA = { ma44: null, ma125: null, price: null, time: null };
        
        if (this.currentMouseTime && this.dailyMAData.size > 0) {
            const dayTimestamp = Math.floor(this.currentMouseTime / 86400) * 86400;
            if (this.dailyMAData.has(dayTimestamp)) {
                displayMA = { ...this.dailyMAData.get(dayTimestamp), time: dayTimestamp };
            } else {
                const keys = Array.from(this.dailyMAData.keys()).sort((a, b) => b - a);
                const latestKey = keys[0];
                displayMA = { ...this.dailyMAData.get(latestKey), time: latestKey };
            }
        } else if (this.dailyMAData.size > 0) {
            const keys = Array.from(this.dailyMAData.keys()).sort((a, b) => b - a);
            const latestKey = keys[0];
            displayMA = { ...this.dailyMAData.get(latestKey), time: latestKey };
        }

        const ma44Value = displayMA.ma44;
        const ma125Value = displayMA.ma125;
        const currentPrice = displayMA.price;
        
        const ma44Change = (ma44Value && currentPrice) ? ((currentPrice - ma44Value) / ma44Value * 100) : null;
        const ma125Change = (ma125Value && currentPrice) ? ((currentPrice - ma125Value) / ma125Value * 100) : null;
        const maDateStr = displayMA.time ? TimezoneConfig.formatDate(displayMA.time * 1000).split(' ')[0] : 'Latest';

        document.getElementById('taContent').innerHTML = `
            <div class="ta-section">
                <div class="ta-section-title">
                    Indicator Analysis
                    ${summaryBadge}
                </div>
                ${signalsHtml ? signalsHtml : `<div style="padding: 8px 0; color: var(--tv-text-secondary); font-size: 12px;">No indicators selected. Add indicators from the sidebar panel to view signals.</div>`}
            </div>
            
            <div class="ta-section">
                <div class="ta-section-title" style="display: flex; justify-content: space-between;">
                    <span>Best Moving Averages</span>
                    <span style="font-size: 10px; font-weight: normal; color: var(--tv-blue);">${maDateStr} (1D)</span>
                </div>
                <div class="ta-ma-row">
                    <span class="ta-ma-label">MA 44</span>
                    <span class="ta-ma-value">
                        ${ma44Value ? ma44Value.toFixed(2) : 'N/A'}
                        ${ma44Change !== null ? `<span class="ta-ma-change ${ma44Change >= 0 ? 'positive' : 'negative'}">${ma44Change >= 0 ? '+' : ''}${ma44Change.toFixed(1)}%</span>` : ''}
                    </span>
                </div>
                <div class="ta-ma-row">
                    <span class="ta-ma-label">MA 125</span>
                    <span class="ta-ma-value">
                        ${ma125Value ? ma125Value.toFixed(2) : 'N/A'}
                        ${ma125Change !== null ? `<span class="ta-ma-change ${ma125Change >= 0 ? 'positive' : 'negative'}">${ma125Change >= 0 ? '+' : ''}${ma125Change.toFixed(1)}%</span>` : ''}
                    </span>
                </div>
            </div>

    <div class="ta-section">
                 <div class="ta-section-title">Support / Resistance</div>
                 <div class="ta-level">
                     <span class="ta-level-label">Resistance</span>
                     <span class="ta-level-value">${data.levels ? data.levels.resistance.toFixed(2) : 'N/A'}</span>
                 </div>
                 <div class="ta-level">
                     <span class="ta-level-label">Support</span>
                     <span class="ta-level-value">${data.levels ? data.levels.support.toFixed(2) : 'N/A'}</span>
                 </div>
             </div>

             <div class="ta-section">
                 <div class="ta-section-title">Price Position</div>
                 <div class="ta-position-bar">
                     <div class="ta-position-marker" style="left: ${data.levels ? Math.min(Math.max(data.levels.position_in_range, 5), 95) : 50}%"></div>
                 </div>
                 <div class="ta-strength" style="margin-top: 8px; font-size: 11px;">
                     ${data.levels ? data.levels.position_in_range.toFixed(0) : '--'}% in range
                 </div>
             </div>
        `;
    }
    
    renderSignalsSection() {
        return '';
    }
    
    async loadStats() {
        try {
            const response = await fetch(`${window.APP_CONFIG.API_BASE_URL}/stats?symbol=BTC`);
            this.statsData = await response.json();
        } catch (error) {
            console.error('Error loading stats:', error);
        }
    }
    
    updateStats(candle) {
        const price = candle.close;
        const isUp = candle.close >= candle.open;
        
        if (this.currentPriceLine) {
            this.currentPriceLine.applyOptions({
                price: price,
                color: isUp ? '#26a69a' : '#ef5350',
            });
        }
        
        const savedPrecision = parseInt(localStorage.getItem('winterfail_price_precision')) || 2;
        document.getElementById('currentPrice').textContent = price.toFixed(savedPrecision);
        
        if (this.statsData) {
            const change = this.statsData.change_24h;
            document.getElementById('currentPrice').className = 'stat-value ' + (change >= 0 ? 'positive' : 'negative');
            document.getElementById('priceChange').textContent = (change >= 0 ? '+' : '') + change.toFixed(2) + '%';
            document.getElementById('priceChange').className = 'stat-value ' + (change >= 0 ? 'positive' : 'negative');
            document.getElementById('dailyHigh').textContent = this.statsData.high_24h.toFixed(savedPrecision);
            document.getElementById('dailyLow').textContent = this.statsData.low_24h.toFixed(savedPrecision);
        }
    }
    
    switchTimeframe(interval) {
        if (!this.intervals.includes(interval) || interval === this.currentInterval) return;
        
        const oldInterval = this.currentInterval;
        this.currentInterval = interval;
        localStorage.setItem('winterfail_interval', interval);
        this.hasInitialLoad = false;
        
        document.querySelectorAll('.timeframe-btn').forEach(btn => {
            btn.classList.toggle('active', btn.dataset.interval === interval);
        });
        
        this.clearIndicatorCaches(true);
        
        this.allData.delete(oldInterval);
        this.lastCandleTimestamp = null;
        
        this.loadInitialData();
        
        window.clearSimulationResults?.();
        window.updateTimeframeDisplay?.();
        
        window.onTimeframeChange?.(interval);
    }
    
    switchChartType(chartType) {
        if (chartType === this.currentChartType) return;
        
        this.currentChartType = chartType;
        localStorage.setItem('winterfail_chart_type', chartType);
        
        const allData = this.allData.get(this.currentInterval) || [];
       const currentData = this.candleSeries ? this.candleSeries.data() : allData;
        
        this.chart.removeSeries(this.candleSeries);
        delete this.seriesMap.candlestick;
        
        if (this.avgPriceSeries) {
            this.chart.removeSeries(this.avgPriceSeries);
            this.avgPriceSeries = null;
        }
        
        if (this.currentPriceLine) {
            this.currentPriceLine.applyOptions({
                visible: false
            });
        }
        
        const newSeries = this.addSeriesByType(chartType);
        if (!newSeries) {
            console.error('[Chart] Failed to create series for type:', chartType);
            return;
        }
        this.candleSeries = newSeries;
        
        this.updateChartTypeButtons();
         
         if (currentData && currentData.length > 0) {
             const chartData = this.allData.get(this.currentInterval) || currentData;
             const hasOHLC = chartData.length > 0 && chartData[0].hasOwnProperty('open');
             
             if (chartType === 'candlestick' || chartType === 'bar') {
                 if (hasOHLC) {
                     this.candleSeries.setData(chartData);
                 } else {
                     const ohlcData = chartData.map(c => ({
                         time: c.time,
                         open: c.value,
                         high: c.value,
                         low: c.value,
                         close: c.value
                     }));
                     this.candleSeries.setData(ohlcData);
                 }
             } else if (chartType === 'line') {
                 const closePrices = chartData.length > 0 && chartData[0].hasOwnProperty('close')
                     ? chartData.map(c => ({
                         time: c.time,
                         value: c.close
                     }))
                     : chartData;
                 this.candleSeries.setData(closePrices);
             }
         }
        
        window.drawIndicatorsOnChart?.();
    }
    
    addSeriesByType(chartType) {
        let series;
        const savedPrecision = parseInt(localStorage.getItem('winterfail_price_precision')) || 2;
        const initialMinMove = savedPrecision === 0 ? 1 : Number((1 / Math.pow(10, savedPrecision)).toFixed(savedPrecision));
        
        switch (chartType) {
            case 'candlestick':
                const candleUpColor = localStorage.getItem('winterfail_candle_up') || '#ff9800';
                const candleDownColor = localStorage.getItem('winterfail_candle_down') || '#ff9800';
                series = this.chart.addSeries(LightweightCharts.CandlestickSeries, {
                    upColor: candleUpColor,
                    downColor: candleDownColor,
                    borderUpColor: candleUpColor,
                    borderDownColor: candleDownColor,
                    wickUpColor: candleUpColor,
                    wickDownColor: candleDownColor,
                    lastValueVisible: false,
                    priceLineVisible: false,
                    priceFormat: { type: 'price', precision: savedPrecision, minMove: initialMinMove }
                });
                break;
            case 'line':
                series = this.chart.addSeries(LightweightCharts.LineSeries, {
                    color: '#2196f3',
                    lineWidth: 2,
                    lineStyle: LightweightCharts.LineStyle.Solid,
                    lastValueVisible: true,
                    priceLineVisible: false,
                    crosshairMarkerVisible: true,
                    priceFormat: { type: 'price', precision: savedPrecision, minMove: initialMinMove }
                });
                break;
            case 'bar':
                const barUpColor = localStorage.getItem('winterfail_candle_up') || '#ff9800';
                const barDownColor = localStorage.getItem('winterfail_candle_down') || '#ff9800';
                series = this.chart.addSeries(LightweightCharts.BarSeries, {
                    upColor: barUpColor,
                    downColor: barDownColor,
                    barColors: {
                        up: barUpColor,
                        down: barDownColor
                    },
                    lastValueVisible: false,
                    priceLineVisible: false,
                    priceFormat: { type: 'price', precision: savedPrecision, minMove: initialMinMove }
                });
                break;
        }
        
        this.seriesMap[chartType] = series;
        return series;
    }
    
    addAvgPriceSeries() {
        const savedPrecision = parseInt(localStorage.getItem('winterfail_price_precision')) || 2;
        const initialMinMove = savedPrecision === 0 ? 1 : Number((1 / Math.pow(10, savedPrecision)).toFixed(savedPrecision));
        
        this.avgPriceSeries = this.chart.addSeries(LightweightCharts.LineSeries, {
            color: '#00bcd4',
            lineWidth: 1,
            lineStyle: LightweightCharts.LineStyle.Solid,
            lastValueVisible: true,
            priceLineVisible: false,
            crosshairMarkerVisible: false,
            title: '',
            priceFormat: { type: 'price', precision: savedPrecision, minMove: initialMinMove }
        });
    }
    
    updateChartTypeButtons() {
        const buttons = document.querySelectorAll('.chart-type-btn');
        buttons.forEach(btn => {
            btn.classList.remove('active');
            if (btn.dataset.chartType === this.currentChartType) {
                btn.classList.add('active');
            }
        });
    }
    
    getChartTypeData() {
        if (!this.candleSeries) return [];
        return this.candleSeries.data();
    }
    
    applyColorToChartType(color, direction) {
        if (!this.candleSeries) return;
        
        if (this.currentChartType === 'candlestick') {
            const options = {};
            if (direction === 'up') {
                options.upColor = color;
                options.borderUpColor = color;
                options.wickUpColor = color;
            } else {
                options.downColor = color;
                options.borderDownColor = color;
                options.wickDownColor = color;
            }
            this.candleSeries.applyOptions(options);
        } else if (this.currentChartType === 'bar') {
            const options = {
                barColors: {}
            };
            if (direction === 'up') {
                options.upColor = color;
                options.barColors.up = color;
            } else {
                options.downColor = color;
                options.barColors.down = color;
            }
            this.candleSeries.applyOptions(options);
        }
    }
}

export function refreshTA() {
    if (window.dashboard) {
        const time = new Date().toLocaleTimeString();
        document.getElementById('taContent').innerHTML = `<div class="ta-loading">Refreshing... ${time}</div>`;
        window.dashboard.loadTA();
    }
}

export function openAIAnalysis() {
    const symbol = 'BTC';
    const interval = window.dashboard?.currentInterval || '1d';
    const prompt = `Analyze Bitcoin (${symbol}) ${interval} chart. Current trend, support/resistance levels, and trading recommendation. Technical indicators: MA44, MA125.`;
    
    const geminiUrl = `https://gemini.google.com/app?prompt=${encodeURIComponent(prompt)}`;
    window.open(geminiUrl, '_blank');
}
