/**
 * Drawing Tools for Lightweight Charts
 * Implements professional trading chart drawing primitives
 */

export class DrawingManager {
    constructor(dashboard, container) {
        this.dashboard = dashboard;
        this.chart = dashboard.chart;
        this.series = dashboard.candleSeries;
        this.container = container;
        this.drawings = [];
        this.activeTool = null;
        this.currentDrawing = null;
        this.selectedDrawing = null;
        this.dragMode = null; 
        this.isMouseDown = false;
        
        // Default Settings
        this.defaults = {
            trend_line: {
                color: '#2962ff',
                width: 2,
                style: 0, // 0: Solid, 1: Dashed, 2: Dotted
                opacity: 100,
                text: '',
                textColor: '#2962ff',
                fontSize: 14,
                bold: false,
                italic: false,
                alignVert: 'top',
                alignHorz: 'left'
            },
            horizontal_line: {
                color: '#2962ff',
                width: 2,
                style: 0,
                opacity: 100,
                text: '',
                textColor: '#2962ff',
                fontSize: 14,
                bold: false,
                italic: false,
                alignVert: 'top',
                alignHorz: 'left'
            },
            vertical_line: {
                color: '#2962ff',
                width: 2,
                style: 0,
                opacity: 100,
                text: '',
                textColor: '#2962ff',
                fontSize: 14,
                bold: false,
                italic: false,
                alignVert: 'top',
                alignHorz: 'left'
            },
            arrow: {
                color: '#2962ff',
                width: 2,
                style: 0,
                opacity: 100,
                text: '',
                textColor: '#2962ff',
                fontSize: 14,
                bold: false,
                italic: false,
                alignVert: 'top',
                alignHorz: 'left'
            }
        };

        // Dragging offsets
        this.dragStartPos = null;
        this.startP1 = null;
        this.startP2 = null;
        this.startPrice = null;
        this.startTime = null;
        
        this.init();
        this.initSettingsPanel();
    }

    init() {
        const container = this.container;
        
        // Mouse Events
        container.addEventListener('mousedown', (e) => this.handleMouseDown(e));
        container.addEventListener('dblclick', (e) => {
            const pos = this.getMousePos(e);
            const hit = this.findHit(pos.x, pos.y);
            if (hit) {
                this.selectedDrawing = hit.drawing;
                // Only open panel for supported types
                if (['trend_line', 'ray', 'rectangle', 'horizontal_line', 'vertical_line', 'arrow', 'arrow_pointer'].includes(hit.drawing.type)) {
                    this.toggleSettingsPanel(true);
                }
                this.update();
            }
        });
        window.addEventListener('mousemove', (e) => this.handleMouseMove(e));
        window.addEventListener('mouseup', (e) => this.handleMouseUp(e));

        // Touch Events
        container.addEventListener('touchstart', (e) => {
            if (this.activeTool || this.selectedDrawing) e.preventDefault();
            this.handleMouseDown(this.touchToMouseEvent(e));
        }, { passive: false });
        
        window.addEventListener('touchmove', (e) => {
            if (this.activeTool || (this.selectedDrawing && this.isMouseDown)) e.preventDefault();
            this.handleMouseMove(this.touchToMouseEvent(e));
        }, { passive: false });
        
        window.addEventListener('touchend', (e) => {
            this.handleMouseUp();
        });
        
        window.addEventListener('keydown', (e) => {
            if ((e.key === 'Delete' || e.key === 'Backspace') && this.selectedDrawing) {
                this.drawings = this.drawings.filter(d => d !== this.selectedDrawing);
                this.selectedDrawing = null;
                this.update();
            }
        });
        
        this.drawingPrimitive = {
            attached: (param) => {
                this.requestUpdate = param.requestUpdate;
            },
            detached: () => {
                this.requestUpdate = undefined;
            },
            updateAllViews: () => {},
            paneViews: () => [{
                renderer: () => ({
                    draw: (target) => this.render(target)
                })
            }],
            priceAxisViews: () => this.getPriceAxisViews(),
            timeAxisViews: () => this.getTimeAxisViews()
        };
        
        this.series.attachPrimitive(this.drawingPrimitive);
    }

    getPriceAxisViews() {
        const views = [];
        const drawingsToShow = [];
        if (this.currentDrawing && this.currentDrawing.type === 'measure') drawingsToShow.push(this.currentDrawing);
        if (this.selectedDrawing && this.selectedDrawing.type === 'measure') drawingsToShow.push(this.selectedDrawing);

        drawingsToShow.forEach(d => {
            const isUp = d.p2.price >= d.p1.price;
            const color = isUp ? '#26a69a' : '#ef5350';
            [d.p1.price, d.p2.price].forEach(price => {
                const coord = this.series.priceToCoordinate(price);
                if (coord !== null) {
                    views.push({
                        coordinate: () => coord,
                        text: () => price.toFixed(2),
                        textColor: () => '#ffffff',
                        backColor: () => color,
                        visible: () => true,
                    });
                }
            });
        });
        return views;
    }

    getTimeAxisViews() {
        const views = [];
        const drawingsToShow = [];
        if (this.currentDrawing && this.currentDrawing.type === 'measure') drawingsToShow.push(this.currentDrawing);
        if (this.selectedDrawing && this.selectedDrawing.type === 'measure') drawingsToShow.push(this.selectedDrawing);

        drawingsToShow.forEach(d => {
            const isUp = d.p2.price >= d.p1.price;
            const color = isUp ? '#26a69a' : '#ef5350';
            [d.p1.time, d.p2.time].forEach(time => {
                const coord = this.timeToX(time);
                if (coord !== null) {
                    views.push({
                        coordinate: () => coord,
                        text: () => {
                            const date = new Date(time * 1000);
                            const day = date.getDate().toString().padStart(2, '0');
                            const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
                            const month = months[date.getMonth()];
                            const year = date.getFullYear().toString().slice(-2);
                            const hours = date.getHours().toString().padStart(2, '0');
                            const mins = date.getMinutes().toString().padStart(2, '0');
                            return `${day} ${month} '${year}  ${hours}:${mins}`;
                        },
                        textColor: () => '#ffffff',
                        backColor: () => color,
                        visible: () => true,
                    });
                }
            });
        });
        return views;
    }

    touchToMouseEvent(e) {
        const touch = e.touches[0] || e.changedTouches[0];
        return {
            clientX: touch.clientX,
            clientY: touch.clientY,
            shiftKey: e.shiftKey,
            preventDefault: () => e.preventDefault()
        };
    }

    updateChartInteractions() {
        const isInteracting = this.activeTool !== null || this.currentDrawing !== null || (this.selectedDrawing !== null && this.isMouseDown);
        
        this.chart.applyOptions({
            handleScroll: {
                mouseWheel: !isInteracting,
                pressedMouseMove: !isInteracting,
                horzTouchDrag: !isInteracting,
                vertTouchDrag: !isInteracting,
            },
            handleScale: {
                axisPressedMouseMove: !isInteracting,
                mouseWheel: !isInteracting,
                pinch: !isInteracting,
            }
        });
    }

    setTool(tool, event) {
        // Shift + Click on trend_line button opens settings
        if (tool === 'trend_line' && event && event.shiftKey) {
            this.toggleSettingsPanel(true);
            return;
        }

        this.activeTool = tool;
        
        // Update UI Button states
        document.querySelectorAll('#drawingToolbar button[data-tool]').forEach(btn => {
            if (btn.dataset.tool === tool) {
                btn.classList.add('bg-blue-600/30', 'text-blue-400');
                btn.classList.remove('text-gray-400', 'hover:bg-[#2d3a4f]');
            } else {
                btn.classList.remove('bg-blue-600/30', 'text-blue-400');
                btn.classList.add('text-gray-400', 'hover:bg-[#2d3a4f]');
            }
        });

        if (tool === 'cursor' || !tool) {
            this.activeTool = null;
            document.body.style.cursor = 'default';
        } else if (tool === 'clear') {
            this.drawings = [];
            this.selectedDrawing = null;
            this.activeTool = null;
            this.update();
            // Instantly clear the 'clear' button state
            setTimeout(() => this.setTool(null), 100);
        } else {
            document.body.style.cursor = 'crosshair';
            this.selectedDrawing = null;
        }
        
        this.updateChartInteractions();
        this.update();
    }

    getIntervalSeconds() {
        const interval = this.dashboard.currentInterval;
        const unit = interval.slice(-1); // Keep case to distinguish 'm' and 'M'
        const value = parseInt(interval.slice(0, -1));
        
        switch (unit) {
            case 'm': return value * 60;
            case 'h': return value * 3600;
            case 'd': return value * 86400;
            case 'w': return value * 604800;
            case 'M': return value * 2592000;
            default: return 60;
        }
    }

    getMousePos(e) {
        const rect = this.container.getBoundingClientRect();
        const x = e.clientX - rect.left;
        const y = e.clientY - rect.top;
        
        const timeScale = this.chart.timeScale();
        const candleData = this.dashboard.allData.get(this.dashboard.currentInterval) || [];
        let time = timeScale.coordinateToTime(x);
        
        // Handle whitespace / future drawing
        if (candleData.length > 0) {
            const logical = timeScale.coordinateToLogical(x);
            const lastIdx = candleData.length - 1;
            
            // If coordinateToTime returns null OR logical index > last index (future)
            if (logical !== null && (time === null || logical > lastIdx)) {
                const lastCandle = candleData[lastIdx];
                const intervalSec = this.getIntervalSeconds();
                const offset = logical - lastIdx;
                
                // Calculate time based on logical offset from the last candle
                time = lastCandle.time + Math.round(offset * intervalSec);
            } else if (logical !== null && logical < 0) {
                // Handle past whitespace (if any)
                const firstCandle = candleData[0];
                const intervalSec = this.getIntervalSeconds();
                time = firstCandle.time + Math.round(logical * intervalSec);
            }
        }
        
        const price = this.series.coordinateToPrice(y);
        return { x, y, time, price };
    }

    handleMouseDown(e) {
        const pos = this.getMousePos(e);
        this.isMouseDown = true;
        this.dragStartPos = pos;

        // Shift + Click shortcut for Measurement Tool
        if (e.shiftKey && !this.activeTool) {
            this.setTool('measure');
            this.currentDrawing = { 
                type: 'measure', 
                p1: { time: pos.time, price: pos.price }, 
                p2: { time: pos.time, price: pos.price }, 
                color: '#26a69a' 
            };
            this.update();
            return;
        }

        // Click-Move-Click logic for Measurement Tool
        if (this.activeTool === 'measure') {
            if (this.currentDrawing) {
                // 2nd Click: Finish
                this.drawings.push(this.currentDrawing);
                this.currentDrawing = null;
                this.setTool(null);
                this.isMouseDown = false;
                this.update();
                return;
            } else {
                // 1st Click: Start
                this.currentDrawing = { 
                    type: 'measure', 
                    p1: { time: pos.time, price: pos.price }, 
                    p2: { time: pos.time, price: pos.price }, 
                    color: '#26a69a',
                    labelOffset: { x: 0, y: 0 }
                };
                this.update();
                return;
            }
        }

        if (!this.activeTool) {
            const hit = this.findHit(pos.x, pos.y);
            if (hit) {
                this.selectedDrawing = hit.drawing;
                this.dragMode = hit.part;
                
                const d = this.selectedDrawing;
                if (d.p1) this.startP1 = { ...d.p1 };
                if (d.p2) this.startP2 = { ...d.p2 };
                if (d.price !== undefined) this.startPrice = d.price;
                if (d.time !== undefined) this.startTime = d.time;
                
                this.updateChartInteractions();
                this.update();
                return;
            } else {
                this.selectedDrawing = null;
                this.dragMode = null;
            }
        }

        if (!this.activeTool || pos.time === null || pos.price === null) {
            this.update();
            return;
        }
        
        const color = this.defaults.trend_line.color;
        const p1 = { time: pos.time, price: pos.price };
        const p2 = { time: pos.time, price: pos.price };

        const defs = this.defaults.trend_line;
        if (this.activeTool === 'trend_line' || this.activeTool === 'ray' || this.activeTool === 'rectangle') {
            this.currentDrawing = { 
                type: this.activeTool, p1, p2, 
                color: defs.color,
                width: defs.width,
                style: defs.style,
                opacity: defs.opacity,
                text: defs.text,
                textColor: defs.textColor,
                fontSize: defs.fontSize,
                bold: defs.bold,
                italic: defs.italic,
                alignVert: defs.alignVert,
                alignHorz: defs.alignHorz
            };
        } else if (this.activeTool === 'horizontal_line') {
            const defs = this.defaults.horizontal_line;
            this.drawings.push({ 
                type: 'horizontal_line', 
                price: pos.price, 
                color: defs.color,
                width: defs.width,
                style: defs.style,
                opacity: defs.opacity,
                text: defs.text,
                textColor: defs.textColor,
                fontSize: defs.fontSize,
                bold: defs.bold,
                italic: defs.italic,
                alignVert: defs.alignVert,
                alignHorz: defs.alignHorz
            });
            this.setTool(null);
        } else if (this.activeTool === 'vertical_line') {
            const defs = this.defaults.vertical_line;
            this.drawings.push({ 
                type: 'vertical_line', 
                time: pos.time, 
                color: defs.color,
                width: defs.width,
                style: defs.style,
                opacity: defs.opacity,
                text: defs.text,
                textColor: defs.textColor,
                fontSize: defs.fontSize,
                bold: defs.bold,
                italic: defs.italic,
                alignVert: defs.alignVert,
                alignHorz: defs.alignHorz
            });
            this.setTool(null);
        } else if (this.activeTool === 'fib_retracement') {
            this.currentDrawing = { type: 'fib_retracement', p1, p2, color: '#fb8c00' };
        } else if (this.activeTool === 'arrow_pointer') {
            const defs = this.defaults.arrow;
            this.currentDrawing = { 
                type: 'arrow_pointer', p1, p2, 
                color: defs.color,
                width: defs.width,
                style: defs.style,
                opacity: defs.opacity,
                text: defs.text,
                textColor: defs.textColor,
                fontSize: defs.fontSize,
                bold: defs.bold,
                italic: defs.italic,
                alignVert: defs.alignVert,
                alignHorz: defs.alignHorz
            };
        } else if (this.activeTool === 'arrow_up' || this.activeTool === 'arrow_down' || this.activeTool === 'arrow_left' || this.activeTool === 'arrow_right') {
            let color = '#2962ff'; // Default blue for left/right
            if (this.activeTool === 'arrow_up') color = '#26a69a'; // Green
            if (this.activeTool === 'arrow_down') color = '#ef5350'; // Red
            
            const defs = this.defaults.arrow;
            this.drawings.push({
                type: 'arrow', time: pos.time, price: pos.price,
                direction: this.activeTool.replace('arrow_', ''),
                color: color,
                width: 2, // default thickness for solid arrows
                style: defs.style,
                opacity: defs.opacity,
                text: defs.text,
                textColor: defs.textColor,
                fontSize: defs.fontSize,
                bold: defs.bold,
                italic: defs.italic,
                alignVert: defs.alignVert,
                alignHorz: defs.alignHorz
            });
            this.setTool(null);
        } else if (this.activeTool === 'text') {
            const text = prompt('Enter text:');
            if (text) this.drawings.push({ type: 'text', time: pos.time, price: pos.price, text, color: '#ffffff' });
            this.setTool(null);
        }
        this.update();
    }

    handleMouseMove(e) {
        const pos = this.getMousePos(e);
        
        // Hover cursor logic
        if (!this.isMouseDown && !this.activeTool) {
            const hit = this.findHit(pos.x, pos.y);
            if (hit) {
                this.container.style.cursor = hit.part === 'label' ? 'move' : 'pointer';
            } else {
                this.container.style.cursor = 'default';
            }
        }

        // Track measurement even if mouse is up (Click-Move-Click)
        if (this.currentDrawing && this.currentDrawing.type === 'measure') {
            if (pos.time !== null) {
                this.currentDrawing.p2 = { time: pos.time, price: pos.price };
                this.update();
            }
            return;
        }

        if (!this.isMouseDown) return;

        if (this.selectedDrawing && this.dragMode) {
            if (pos.time === null || pos.price === null) return;
            const d = this.selectedDrawing;
            
            // Safety check for dragStartPos
            if (!this.dragStartPos) {
                this.dragStartPos = pos;
                return;
            }
            
            if (this.dragMode === 'label') {
                // Free movement of ONLY the label field
                const dx = pos.x - this.dragStartPos.x;
                const dy = pos.y - this.dragStartPos.y;
                if (!d.labelOffset) d.labelOffset = { x: 0, y: 0 };
                d.labelOffset.x += dx;
                d.labelOffset.y += dy;
                this.dragStartPos = pos; 
                this.update();
                return; // Critical: exit here so we don't move measurement points
            }
            
            if (this.dragMode === 'label') {
                const dx = pos.x - this.dragStartPos.x;
                const dy = pos.y - this.dragStartPos.y;
                if (!d.labelOffset) d.labelOffset = { x: 0, y: 0 };
                d.labelOffset.x += dx;
                d.labelOffset.y += dy;
                this.dragStartPos = pos; 
                this.update();
                return;
            }
            if (this.dragMode === 'p1') {
                d.p1 = { time: pos.time, price: pos.price };
            } else if (this.dragMode === 'p2') {
                d.p2 = { time: pos.time, price: pos.price };
            } else if (this.dragMode === 'all') {
                let timeDiff = pos.time - this.dragStartPos.time;
                const priceDiff = pos.price - this.dragStartPos.price;
                
                // If timeDiff is NaN (e.g., dragged into whitespace on high TF), estimate it
                if (isNaN(timeDiff) || pos.time === null) {
                     const timeScale = this.chart.timeScale();
                     const startLogical = timeScale.coordinateToLogical(this.dragStartPos.x);
                     const currentLogical = timeScale.coordinateToLogical(pos.x);
                     if (startLogical !== null && currentLogical !== null) {
                         const logicalDiff = currentLogical - startLogical;
                         timeDiff = logicalDiff * this.getIntervalSeconds();
                     }
                }

                if (!isNaN(timeDiff) && !isNaN(priceDiff)) {
                    if (d.p1 && d.p2) {
                        d.p1.time = this.startP1.time + timeDiff;
                        d.p1.price = this.startP1.price + priceDiff;
                        d.p2.time = this.startP2.time + timeDiff;
                        d.p2.price = this.startP2.price + priceDiff;
                    } else if (d.time !== undefined && d.price !== undefined) {
                        d.time = this.startTime + timeDiff;
                        d.price = this.startPrice + priceDiff;
                    } else if (d.price !== undefined) {
                        d.price = this.startPrice + priceDiff;
                    } else if (d.time !== undefined) {
                        d.time = this.startTime + timeDiff;
                    }
                }
            } else if (this.dragMode === 'price') {
                d.price = pos.price;
            } else if (this.dragMode === 'time') {
                d.time = pos.time;
            }
            this.update();
            return;
        }

        if (this.currentDrawing && pos.time !== null) {
            this.currentDrawing.p2 = { time: pos.time, price: pos.price };
            this.update();
        }
    }

    handleMouseUp() {
        if (this.currentDrawing && this.currentDrawing.type === 'measure') {
            this.isMouseDown = false;
            this.updateChartInteractions();
            this.update();
            return; 
        }

        if (this.currentDrawing) {
            this.drawings.push(this.currentDrawing);
            this.currentDrawing = null;
            this.setTool(null);
        }
        this.dragMode = null;
        this.isMouseDown = false;
        this.updateChartInteractions();
        this.update();
    }

    findHit(x, y) {
        const threshold = 10;
        for (let i = this.drawings.length - 1; i >= 0; i--) {
            const d = this.drawings[i];
            
            // Check for label hit first (highest z-order)
            if (d.type === 'measure' && d.labelPos) {
                if (x >= d.labelPos.x && x <= d.labelPos.x + d.labelPos.width &&
                    y >= d.labelPos.y && y <= d.labelPos.y + d.labelPos.height) {
                    return { drawing: d, part: 'label' };
                }
            }

            if (d.p1 && d.p2) {
                const x1 = this.timeToX(d.p1.time);
                const y1 = this.series.priceToCoordinate(d.p1.price);
                const x2 = this.timeToX(d.p2.time);
                const y2 = this.series.priceToCoordinate(d.p2.price);
                
                if (x1 === null || y1 === null || x2 === null || y2 === null) continue;
                
                if (Math.hypot(x - x1, y - y1) < threshold) return { drawing: d, part: 'p1' };
                if (Math.hypot(x - x2, y - y2) < threshold) return { drawing: d, part: 'p2' };
                
                if (d.type === 'rectangle' || d.type === 'measure') {
                    if (x >= Math.min(x1, x2) && x <= Math.max(x1, x2) && y >= Math.min(y1, y2) && y <= Math.max(y1, y2)) return { drawing: d, part: 'all' };
                } else {
                    const dist = this.distToSegment({ x, y }, { x: x1, y: y1 }, { x: x2, y: y2 });
                    if (dist < threshold) return { drawing: d, part: 'all' };
                }
            } else if (d.price !== undefined && d.type === 'horizontal_line') {
                const dy = this.series.priceToCoordinate(d.price);
                if (dy !== null && Math.abs(y - dy) < threshold) {
                    if (d.text && d.labelPos) {
                        if (x >= d.labelPos.x && x <= d.labelPos.x + d.labelPos.width &&
                            y >= d.labelPos.y && y <= d.labelPos.y + d.labelPos.height) {
                            return { drawing: d, part: 'label' };
                        }
                    }
                    return { drawing: d, part: 'all' };
                }
            } else if (d.time !== undefined && d.type === 'vertical_line') {
                const dx = this.timeToX(d.time);
                if (dx !== null && Math.abs(x - dx) < threshold) {
                    if (d.text && d.labelPos) {
                        if (x >= d.labelPos.x && x <= d.labelPos.x + d.labelPos.width &&
                            y >= d.labelPos.y && y <= d.labelPos.y + d.labelPos.height) {
                            return { drawing: d, part: 'label' };
                        }
                    }
                    return { drawing: d, part: 'all' };
                }
            } else if (d.time !== undefined && d.price !== undefined) {
                const dx = this.timeToX(d.time);
                const dy = this.series.priceToCoordinate(d.price);
                if (dx !== null && dy !== null && Math.hypot(x - dx, y - dy) < threshold) return { drawing: d, part: 'all' };
            }
        }
        return null;
    }

    distToSegment(p, v, w) {
        const l2 = Math.pow(v.x - w.x, 2) + Math.pow(v.y - w.y, 2);
        if (l2 === 0) return Math.hypot(p.x - v.x, p.y - v.y);
        let t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2;
        t = Math.max(0, Math.min(1, t));
        return Math.hypot(p.x - (v.x + t * (w.x - v.x)), p.y - (v.y + t * (w.y - v.y)));
    }

    update() {
        if (this.requestUpdate) this.requestUpdate();
    }

    snapToNearestTime(time) {
        if (time === null) return null;
        const candleData = this.dashboard.allData.get(this.dashboard.currentInterval) || [];
        if (candleData.length === 0) return time;

        const firstCandle = candleData[0];
        const lastCandle = candleData[candleData.length - 1];

        // Handle future whitespace
        if (time > lastCandle.time) {
            const intervalSec = this.getIntervalSeconds();
            const offset = Math.round((time - lastCandle.time) / intervalSec);
            return lastCandle.time + (offset * intervalSec);
        }
        
        // Handle past whitespace
        if (time < firstCandle.time) {
            const intervalSec = this.getIntervalSeconds();
            const offset = Math.round((firstCandle.time - time) / intervalSec);
            return firstCandle.time - (offset * intervalSec);
        }

        // Find nearest timestamp in current data
        // Since data is sorted, we can be efficient
        let nearest = candleData[0].time;
        let minDiff = Math.abs(time - nearest);

        // Optimization: check if it's already a match
        if (candleData.find(c => c.time === time)) return time;

        for (let i = 1; i < candleData.length; i++) {
            const diff = Math.abs(time - candleData[i].time);
            if (diff < minDiff) {
                minDiff = diff;
                nearest = candleData[i].time;
            } else if (diff > minDiff) {
                // Since it's sorted, once diff starts increasing, we've found the closest
                break;
            }
        }
        return nearest;
    }

    timeToX(time) {
        if (time === null) return null;
        const timeScale = this.chart.timeScale();
        const candleData = this.dashboard.allData.get(this.dashboard.currentInterval) || [];
        if (candleData.length === 0) return timeScale.timeToCoordinate(time);

        // Native check (exact match)
        const nativeCoord = timeScale.timeToCoordinate(time);
        if (nativeCoord !== null) return nativeCoord;

        const firstCandle = candleData[0];
        const lastCandle = candleData[candleData.length - 1];
        const intervalSec = this.getIntervalSeconds();

        // 1. Whitespace: Future
        if (time > lastCandle.time) {
            const lastIdx = candleData.length - 1;
            const offset = (time - lastCandle.time) / intervalSec;
            return timeScale.logicalToCoordinate(lastIdx + offset);
        }
        
        // 2. Whitespace: Past
        if (time < firstCandle.time) {
            const offset = (time - firstCandle.time) / intervalSec;
            return timeScale.logicalToCoordinate(offset);
        }

        // 3. Inside Data Range: Find the two candles it falls between
        // Binary search for efficiency
        let left = 0;
        let right = candleData.length - 1;
        while (left <= right) {
            const mid = Math.floor((left + right) / 2);
            if (candleData[mid].time === time) return timeScale.timeToCoordinate(time); // Should have been caught by nativeCoord
            if (candleData[mid].time < time) left = mid + 1;
            else right = mid - 1;
        }

        // It falls between candleData[right] and candleData[left]
        const c1 = candleData[right];
        const c2 = candleData[left];
        
        if (!c1 || !c2) return null; // Should not happen given bounds check above

        const x1 = timeScale.timeToCoordinate(c1.time);
        const x2 = timeScale.timeToCoordinate(c2.time);
        
        if (x1 === null || x2 === null) {
            // If native coordinates fail (e.g. off-screen), fallback to logical interpolation
            const logical1 = right;
            const logical2 = left;
            const ratio = (time - c1.time) / (c2.time - c1.time);
            return timeScale.logicalToCoordinate(logical1 + ratio * (logical2 - logical1));
        }

        // Linear interpolation between the two candle coordinates
        const ratio = (time - c1.time) / (c2.time - c1.time);
        return x1 + ratio * (x2 - x1);
    }

    hexToRgba(hex, opacity) {
        let r = 0, g = 0, b = 0;
        if (hex.length === 4) {
            r = parseInt(hex[1] + hex[1], 16);
            g = parseInt(hex[2] + hex[2], 16);
            b = parseInt(hex[3] + hex[3], 16);
        } else if (hex.length === 7) {
            r = parseInt(hex.slice(1, 3), 16);
            g = parseInt(hex.slice(3, 5), 16);
            b = parseInt(hex.slice(5, 7), 16);
        }
        return `rgba(${r}, ${g}, ${b}, ${opacity / 100})`;
    }

    render(target) {
        target.useMediaCoordinateSpace((scope) => {
            const ctx = scope.context;
            const chart = this.chart;
            const series = this.series;
            const allDrawings = [...this.drawings];
            if (this.currentDrawing) allDrawings.push(this.currentDrawing);

            allDrawings.forEach(d => {
                const isSelected = d === this.selectedDrawing;
                ctx.save();
                
                // Base Style
                const color = d.opacity !== undefined ? this.hexToRgba(d.color, d.opacity) : d.color;
                ctx.strokeStyle = color;
                ctx.lineWidth = d.width || (isSelected ? 3 : 2);
                
                if (d.style === 1) ctx.setLineDash([10, 5]); // Dashed
                else if (d.style === 2) ctx.setLineDash([2, 2]); // Dotted
                else ctx.setLineDash([]); // Solid

                if (isSelected) { ctx.shadowBlur = 5; ctx.shadowColor = d.color; }

                if (d.type === 'trend_line' || d.type === 'ray' || d.type === 'arrow_pointer') {
                    const x1 = this.timeToX(d.p1.time);
                    const y1 = series.priceToCoordinate(d.p1.price);
                    const x2 = this.timeToX(d.p2.time);
                    const y2 = series.priceToCoordinate(d.p2.price);
                    if (x1 !== null && y1 !== null && x2 !== null && y2 !== null) {
                        
                        if (d.type === 'arrow_pointer') {
                            const angle = Math.atan2(y2 - y1, x2 - x1);
                            const dist = Math.hypot(x2 - x1, y2 - y1);
                            
                            ctx.save();
                            ctx.translate(x1, y1);
                            ctx.rotate(angle);
                            
                            // Fat arrow dimensions
                            const headLen = Math.min(dist * 0.5, 30 + (d.width || 2) * 5); 
                            const headWidth = headLen * 1.2;
                            const tailStartW = (d.width || 2) * 2;
                            const tailEndW = headLen * 0.5;
                            const indent = headLen * 0.2; // Head indentation
                            
                            ctx.beginPath();
                            // Top edge of tail
                            ctx.moveTo(0, -tailStartW/2);
                            ctx.lineTo(dist - headLen + indent, -tailEndW/2);
                            // Top edge of head
                            ctx.lineTo(dist - headLen, -headWidth/2);
                            // Tip
                            ctx.lineTo(dist, 0);
                            // Bottom edge of head
                            ctx.lineTo(dist - headLen, headWidth/2);
                            // Bottom edge of tail
                            ctx.lineTo(dist - headLen + indent, tailEndW/2);
                            ctx.lineTo(0, tailStartW/2);
                            ctx.closePath();
                            
                            ctx.fillStyle = color;
                            ctx.fill();
                            ctx.restore();
                        } else {
                            ctx.beginPath();
                            ctx.moveTo(x1, y1);
                            if (d.type === 'ray') {
                                const angle = Math.atan2(y2 - y1, x2 - x1);
                                ctx.lineTo(x1 + Math.cos(angle) * 10000, y1 + Math.sin(angle) * 10000);
                            } else {
                                ctx.lineTo(x2, y2);
                            }
                            ctx.stroke();
                        }

                        // Render Text if present
                        if (d.text) {
                            ctx.save();
                            ctx.setLineDash([]); // Text should not be dashed
                            const fontSize = d.fontSize || 14;
                            const fontStyle = (d.bold ? 'bold ' : '') + (d.italic ? 'italic ' : '');
                            ctx.font = `${fontStyle}${fontSize}px Inter`;
                            ctx.fillStyle = d.textColor || color;
                            
                            let startX = x1, startY = y1, endX = x2, endY = y2;
                            if (x1 > x2 || (x1 === x2 && y1 > y2)) {
                                startX = x2; startY = y2; endX = x1; endY = y1;
                            }
                            
                            const angle = Math.atan2(endY - startY, endX - startX);
                            const length = Math.hypot(endX - startX, endY - startY);
                            
                            ctx.translate(startX, startY);
                            ctx.rotate(angle);
                            
                            ctx.textAlign = d.alignHorz || 'left';
                            ctx.textBaseline = d.alignVert === 'middle' ? 'middle' : (d.alignVert === 'bottom' ? 'top' : 'bottom');
                            
                            let tx = 0;
                            if (d.alignHorz === 'center') tx = length / 2;
                            else if (d.alignHorz === 'right') tx = length;
                            
                            const offset = 10;
                            const finalTy = d.alignVert === 'top' ? -offset : (d.alignVert === 'bottom' ? offset : 0);
                            
                            ctx.fillText(d.text, tx, finalTy);
                            ctx.restore();
                        }

                        if (isSelected) {
                            ctx.setLineDash([]);
                            ctx.fillStyle = d.type === 'arrow_pointer' ? 'transparent' : '#ffffff';
                            ctx.strokeStyle = d.type === 'arrow_pointer' ? color : d.color;
                            ctx.lineWidth = 2;
                            ctx.beginPath(); ctx.arc(x1, y1, 5, 0, Math.PI * 2); if (d.type !== 'arrow_pointer') ctx.fill(); ctx.stroke();
                            ctx.beginPath(); ctx.arc(x2, y2, 5, 0, Math.PI * 2); if (d.type !== 'arrow_pointer') ctx.fill(); ctx.stroke();
                        }
                    }
                } else if (d.type === 'rectangle') {
                    const x1 = this.timeToX(d.p1.time);
                    const y1 = series.priceToCoordinate(d.p1.price);
                    const x2 = this.timeToX(d.p2.time);
                    const y2 = series.priceToCoordinate(d.p2.price);
                    if (x1 !== null && y1 !== null && x2 !== null && y2 !== null) {
                        ctx.fillStyle = d.color + '22';
                        ctx.fillRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1));
                        ctx.strokeRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1));
                        if (isSelected) {
                            ctx.fillStyle = '#ffffff';
                            ctx.beginPath(); ctx.arc(x1, y1, 5, 0, Math.PI * 2); ctx.fill(); ctx.stroke();
                            ctx.beginPath(); ctx.arc(x2, y2, 5, 0, Math.PI * 2); ctx.fill(); ctx.stroke();
                        }
                    }
                } else if (d.type === 'horizontal_line') {
                    const y = series.priceToCoordinate(d.price);
                    if (y !== null && y >= 0 && y <= scope.mediaSize.height) {
                        ctx.save();
                        ctx.strokeStyle = d.opacity !== undefined ? this.hexToRgba(d.color, d.opacity) : d.color;
                        ctx.lineWidth = d.width || 2;
                        if (d.style === 1) ctx.setLineDash([10, 5]);
                        else if (d.style === 2) ctx.setLineDash([2, 2]);
                        else ctx.setLineDash([]);
                        if (isSelected) { ctx.shadowBlur = 5; ctx.shadowColor = d.color; }
                        ctx.beginPath();
                        ctx.moveTo(-1000, y);
                        ctx.lineTo(scope.mediaSize.width + 1000, y);
                        ctx.stroke();
                        if (isSelected) {
                            ctx.setLineDash([]);
                            ctx.fillStyle = '#ffffff';
                            ctx.beginPath(); ctx.arc(0, y, 5, 0, Math.PI * 2); ctx.fill(); ctx.stroke();
                        }
                        
                        // Render Text and store label position
                        let labelPos = null;
                        if (d.text) {
                            ctx.save();
                            ctx.setLineDash([]);
                            const fontSize = d.fontSize || 14;
                            const fontStyle = (d.bold ? 'bold ' : '') + (d.italic ? 'italic ' : '');
                            const font = `${fontStyle}${fontSize}px Inter`;
                            ctx.font = font;
                            ctx.fillStyle = d.textColor || d.color;
                            
                            const alignHorz = d.alignHorz || 'center';
                            ctx.textAlign = alignHorz;
                            ctx.textBaseline = d.alignVert === 'middle' ? 'middle' : (d.alignVert === 'bottom' ? 'top' : 'bottom');
                            
                            let textX = scope.mediaSize.width / 2;
                            if (alignHorz === 'left') textX = 10;
                            else if (alignHorz === 'right') textX = scope.mediaSize.width - 10;
                            
                            const offset = 10;
                            let textY = d.alignVert === 'top' ? y - offset : (d.alignVert === 'bottom' ? y + offset : y);
                            
                            ctx.fillText(d.text, textX, textY);
                            
                            const metrics = ctx.measureText(d.text);
                            const labelWidth = metrics.width + 16;
                            const labelHeight = 24;
                            
                            let defaultLabelX = scope.mediaSize.width / 2 - labelWidth / 2;
                            if (alignHorz === 'left') defaultLabelX = 10;
                            else if (alignHorz === 'right') defaultLabelX = scope.mediaSize.width - labelWidth - 10;
                            
                            const defaultLabelY = d.alignVert === 'top' ? y - 40 : (d.alignVert === 'bottom' ? y + 20 : y - 12);
                            
                            labelPos = { 
                                x: defaultLabelX + (d.labelOffset?.x || 0), 
                                y: defaultLabelY + (d.labelOffset?.y || 0), 
                                width: labelWidth, 
                                height: labelHeight 
                            };
                            ctx.restore();
                        }
                        
                        // Store label position for hit detection
                        if (labelPos) {
                            d.labelPos = labelPos;
                        }
                        
                        ctx.restore();
                    }
                } else if (d.type === 'vertical_line') {
                    const x = this.timeToX(d.time);
                    if (x !== null && x >= 0 && x <= scope.mediaSize.width) {
                        ctx.save();
                        ctx.strokeStyle = d.opacity !== undefined ? this.hexToRgba(d.color, d.opacity) : d.color;
                        ctx.lineWidth = d.width || 2;
                        if (d.style === 1) ctx.setLineDash([10, 5]);
                        else if (d.style === 2) ctx.setLineDash([2, 2]);
                        else ctx.setLineDash([]);
                        if (isSelected) { ctx.shadowBlur = 5; ctx.shadowColor = d.color; }
                        ctx.beginPath();
                        ctx.moveTo(x, -1000);
                        ctx.lineTo(x, scope.mediaSize.height + 1000);
                        ctx.stroke();
                        if (isSelected) {
                            ctx.setLineDash([]);
                            ctx.fillStyle = '#ffffff';
                            ctx.beginPath(); ctx.arc(x, 0, 5, 0, Math.PI * 2); ctx.fill(); ctx.stroke();
                        }
                        
                        // Render Text and store label position
                        let labelPos = null;
                        if (d.text) {
                            ctx.save();
                            ctx.setLineDash([]);
                            const fontSize = d.fontSize || 14;
                            const fontStyle = (d.bold ? 'bold ' : '') + (d.italic ? 'italic ' : '');
                            const font = `${fontStyle}${fontSize}px Inter`;
                            ctx.font = font;
                            ctx.fillStyle = d.textColor || d.color;
                            
                            const alignHorz = d.alignHorz || 'center';
                            ctx.textAlign = alignHorz;
                            ctx.textBaseline = d.alignVert === 'middle' ? 'middle' : (d.alignVert === 'bottom' ? 'bottom' : 'top');
                            
                            let textX = x;
                            const offset = 10;
                            
                            let textY = scope.mediaSize.height / 2; // Middle
                            if (d.alignVert === 'top') textY = offset;
                            else if (d.alignVert === 'bottom') textY = scope.mediaSize.height - offset;
                            
                            ctx.fillText(d.text, textX, textY);
                            
                            const metrics = ctx.measureText(d.text);
                            const labelWidth = metrics.width + 16;
                            const labelHeight = 24;
                            
                            let defaultLabelY = scope.mediaSize.height / 2 - labelHeight / 2; // Middle
                            if (d.alignVert === 'top') defaultLabelY = offset;
                            else if (d.alignVert === 'bottom') defaultLabelY = scope.mediaSize.height - offset - labelHeight;
                            
                            let defaultLabelX = x - labelWidth / 2;
                            if (alignHorz === 'left') defaultLabelX = x - labelWidth;
                            else if (alignHorz === 'right') defaultLabelX = x;
                            
                            labelPos = { 
                                x: defaultLabelX + (d.labelOffset?.x || 0), 
                                y: defaultLabelY + (d.labelOffset?.y || 0), 
                                width: labelWidth, 
                                height: labelHeight 
                            };
                            ctx.restore();
                        }
                        
                        // Store label position for hit detection
                        if (labelPos) {
                            d.labelPos = labelPos;
                        }
                        
                        ctx.restore();
                    }
                } else if (d.type === 'fib_retracement') {
                    const x1 = this.timeToX(d.p1.time);
                    const y1 = series.priceToCoordinate(d.p1.price);
                    const x2 = this.timeToX(d.p2.time);
                    const y2 = series.priceToCoordinate(d.p2.price);
                    if (x1 !== null && y1 !== null && x2 !== null && y2 !== null) {
                        const levels = [0, 0.236, 0.382, 0.5, 0.618, 0.786, 1];
                        const range = d.p2.price - d.p1.price;
                        ctx.setLineDash([5, 5]); ctx.lineWidth = 1;
                        levels.forEach(level => {
                            const price = d.p1.price + (range * level);
                            const y = series.priceToCoordinate(price);
                            if (y !== null) {
                                ctx.beginPath(); ctx.moveTo(Math.min(x1, x2), y); ctx.lineTo(Math.max(x1, x2), y); ctx.stroke();
                                ctx.fillStyle = d.color; ctx.font = '10px Inter';
                                ctx.fillText(`${(level * 100).toFixed(1)}% (${price.toFixed(2)})`, Math.max(x1, x2) + 5, y + 3);
                            }
                        });
                        ctx.setLineDash([]); ctx.strokeStyle = d.color + '44';
                        ctx.beginPath(); ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); ctx.stroke();
                        if (isSelected) {
                            ctx.fillStyle = '#ffffff'; ctx.strokeStyle = d.color; ctx.lineWidth = 2;
                            ctx.beginPath(); ctx.arc(x1, y1, 5, 0, Math.PI * 2); ctx.fill(); ctx.stroke();
                            ctx.beginPath(); ctx.arc(x2, y2, 5, 0, Math.PI * 2); ctx.fill(); ctx.stroke();
                        }
                    }
                } else if (d.type === 'arrow') {
                    const x = this.timeToX(d.time);
                    const y = series.priceToCoordinate(d.price);
                    if (x !== null && y !== null) {
                        ctx.fillStyle = d.color; 
                        ctx.beginPath();
                        const baseSize = isSelected ? 20 : 15;
                        const w = baseSize * 1.5; // width of arrow head
                        const h = baseSize * 1.5; // height of arrow head
                        const tailW = baseSize * 0.8; // width of tail
                        const tailH = baseSize * 1.2; // length of tail

                        ctx.save();
                        ctx.translate(x, y);
                        
                        if (d.direction === 'up') ctx.rotate(0);
                        else if (d.direction === 'right') ctx.rotate(Math.PI / 2);
                        else if (d.direction === 'down') ctx.rotate(Math.PI);
                        else if (d.direction === 'left') ctx.rotate(-Math.PI / 2);

                        // Draw a thick arrow pointing UP from the origin (x,y)
                        ctx.moveTo(0, -h/2 - tailH/2); // Tip of arrow
                        ctx.lineTo(w/2, h/2 - tailH/2); // Right corner of head
                        ctx.lineTo(tailW/2, h/2 - tailH/2); // Inner right corner
                        ctx.lineTo(tailW/2, h/2 + tailH/2); // Bottom right of tail
                        ctx.lineTo(-tailW/2, h/2 + tailH/2); // Bottom left of tail
                        ctx.lineTo(-tailW/2, h/2 - tailH/2); // Inner left corner
                        ctx.lineTo(-w/2, h/2 - tailH/2); // Left corner of head
                        ctx.closePath();
                        
                        ctx.fill();
                        if (isSelected) { ctx.strokeStyle = '#ffffff'; ctx.lineWidth = 2; ctx.stroke(); }
                        ctx.restore();
                        
                        // Render Text and store label position
                        let labelPos = null;
                        if (d.text) {
                            ctx.save();
                            ctx.setLineDash([]);
                            const fontSize = d.fontSize || 14;
                            const fontStyle = (d.bold ? 'bold ' : '') + (d.italic ? 'italic ' : '');
                            const font = `${fontStyle}${fontSize}px Inter`;
                            ctx.font = font;
                            ctx.fillStyle = d.textColor || d.color;
                            
                            const alignHorz = d.alignHorz || 'center';
                            ctx.textAlign = alignHorz;
                            ctx.textBaseline = d.alignVert === 'middle' ? 'middle' : (d.alignVert === 'bottom' ? 'bottom' : 'top');
                            
                            let textX = x;
                            let textY = y;
                            
                            // Default offset logic for arrows if align isn't strictly overriding
                            const offset = 25;
                            if (d.direction === 'up') textY += offset;
                            else if (d.direction === 'down') textY -= offset;
                            else if (d.direction === 'left') textX += offset;
                            else if (d.direction === 'right') textX -= offset;

                            ctx.fillText(d.text, textX, textY);
                            
                            const metrics = ctx.measureText(d.text);
                            const labelWidth = metrics.width + 16;
                            const labelHeight = 24;
                            
                            let defaultLabelX = textX - labelWidth / 2;
                            if (alignHorz === 'left') defaultLabelX = textX - labelWidth;
                            else if (alignHorz === 'right') defaultLabelX = textX;
                            
                            let defaultLabelY = textY;
                            if (d.alignVert === 'top') defaultLabelY = textY;
                            else if (d.alignVert === 'bottom') defaultLabelY = textY - labelHeight;
                            else defaultLabelY = textY - labelHeight / 2;

                            labelPos = { 
                                x: defaultLabelX + (d.labelOffset?.x || 0), 
                                y: defaultLabelY + (d.labelOffset?.y || 0), 
                                width: labelWidth, 
                                height: labelHeight 
                            };
                            ctx.restore();
                        }
                        
                        // Store label position for hit detection
                        if (labelPos) {
                            d.labelPos = labelPos;
                        }
                    }
                } else if (d.type === 'text') {
                    const x = this.timeToX(d.time);
                    const y = series.priceToCoordinate(d.price);
                    if (x !== null && y !== null) {
                        ctx.fillStyle = d.color;
                        ctx.font = isSelected ? 'bold 14px Inter' : '12px Inter';
                        ctx.fillText(d.text, x, y);
                        if (isSelected) {
                            const metrics = ctx.measureText(d.text);
                            ctx.strokeStyle = d.color;
                            ctx.strokeRect(x - 2, y - 12, metrics.width + 4, 16);
                        }
                    }
                } else if (d.type === 'measure') {
                    const x1 = this.timeToX(d.p1.time);
                    const y1 = series.priceToCoordinate(d.p1.price);
                    const x2 = this.timeToX(d.p2.time);
                    const y2 = series.priceToCoordinate(d.p2.price);

                    if (x1 !== null && y1 !== null && x2 !== null && y2 !== null) {

                        const priceDiff = d.p2.price - d.p1.price;
                        const percentChange = (priceDiff / d.p1.price) * 100;
                        const isUp = priceDiff >= 0;
                        const color = isUp ? '#26a69a' : '#ef5350';
                        
                        // 1. Draw Measurement Area
                        ctx.fillStyle = color + '33';
                        ctx.fillRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1));
                        
                        // 2. Draw Crosshairs & Arrows
                        ctx.strokeStyle = color;
                        ctx.lineWidth = 1;
                        
                        // Horizontal line
                        ctx.beginPath();
                        ctx.moveTo(Math.min(x1, x2), (y1 + y2) / 2);
                        ctx.lineTo(Math.max(x1, x2), (y1 + y2) / 2);
                        ctx.stroke();
                        
                        // Vertical line
                        ctx.beginPath();
                        ctx.moveTo((x1 + x2) / 2, Math.min(y1, y2));
                        ctx.lineTo((x1 + x2) / 2, Math.max(y1, y2));
                        ctx.stroke();
                        
                        // Draw Arrows at ends of crosshairs
                        const drawArrow = (x, y, angle) => {
                            ctx.save();
                            ctx.translate(x, y);
                            ctx.rotate(angle);
                            ctx.beginPath();
                            ctx.moveTo(-6, -4);
                            ctx.lineTo(0, 0);
                            ctx.lineTo(-6, 4);
                            ctx.stroke();
                            ctx.restore();
                        };
                        
                        // Time arrow (horizontal)
                        if (x2 > x1) drawArrow(x2, (y1 + y2) / 2, 0);
                        else drawArrow(x2, (y1 + y2) / 2, Math.PI);
                        
                        // Price arrow (vertical)
                        if (y2 < y1) drawArrow((x1 + x2) / 2, y2, -Math.PI/2);
                        else drawArrow((x1 + x2) / 2, y2, Math.PI/2);

                        // 3. Data Calculation
                        // Bar count
                        const candleData = this.dashboard.allData.get(this.dashboard.currentInterval) || [];
                        const startIdx = candleData.findIndex(c => c.time === this.snapToNearestTime(d.p1.time));
                        const endIdx = candleData.findIndex(c => c.time === this.snapToNearestTime(d.p2.time));
                        let barCount = 0;
                        let totalVol = 0;
                        if (startIdx !== -1 && endIdx !== -1) {
                            barCount = endIdx - startIdx;
                            const minIdx = Math.min(startIdx, endIdx);
                            const maxIdx = Math.max(startIdx, endIdx);
                            for (let i = minIdx; i <= maxIdx; i++) {
                                totalVol += candleData[i].volume || 0;
                            }
                        } else {
                            // Rough estimate if not in current data
                            const intervalSec = this.getIntervalSeconds();
                            barCount = Math.round((d.p2.time - d.p1.time) / intervalSec);
                        }
                        
                        // Time duration
                        const diffSec = Math.abs(d.p2.time - d.p1.time);
                        let timeStr = "";
                        if (diffSec >= 86400) {
                            const days = Math.floor(diffSec / 86400);
                            const hours = Math.floor((diffSec % 86400) / 3600);
                            const mins = Math.floor((diffSec % 3600) / 60);
                            timeStr = `${days}d${hours > 0 ? ` ${hours}h` : ''}${mins > 0 ? ` ${mins}m` : ''}`;
                        } else {
                            const hours = Math.floor(diffSec / 3600);
                            const mins = Math.floor((diffSec % 3600) / 60);
                            timeStr = `${hours}h${mins > 0 ? ` ${mins}m` : ''}`;
                        }
                        
                        const volStr = totalVol > 1000 ? `${(totalVol/1000).toFixed(3)}K` : totalVol.toFixed(0);
                        
                        // 4. Draw Label Box
                        const labelLines = [
                            `${priceDiff.toFixed(2)} (${percentChange.toFixed(2)}%) , ${Math.round(priceDiff * 100)}`,
                            `${barCount} bars, ${timeStr}`,
                            `Vol ${volStr}`
                        ];
                        
                        ctx.font = '500 12px Inter';
                        const labelWidth = Math.max(...labelLines.map(l => ctx.measureText(l).width)) + 24;
                        const labelHeight = 65;
                        
                        const midX = (x1 + x2) / 2;
                        const topY = Math.min(y1, y2);
                        const bottomY = Math.max(y1, y2);
                        
                        const defaultLabelX = midX - labelWidth / 2;
                        const defaultLabelY = isUp ? topY - labelHeight - 10 : bottomY + 10;
                        
                        const labelX = defaultLabelX + (d.labelOffset?.x || 0);
                        const labelY = defaultLabelY + (d.labelOffset?.y || 0);

                        // Store label position for hit detection
                        d.labelPos = { x: labelX, y: labelY, width: labelWidth, height: labelHeight };
                        
                        // Solid Box
                        ctx.fillStyle = color;
                        this.roundRect(ctx, labelX, labelY, labelWidth, labelHeight, 4);
                        ctx.fill();
                        
                        // Text
                        ctx.fillStyle = '#ffffff';
                        ctx.textAlign = 'center';
                        labelLines.forEach((line, i) => {
                            ctx.fillText(line, labelX + labelWidth/2, labelY + 20 + (i * 18));
                        });
                        
                        if (isSelected) {
                            ctx.strokeStyle = '#ffffff'; ctx.lineWidth = 2;
                            ctx.beginPath(); ctx.arc(x1, y1, 5, 0, Math.PI * 2); ctx.stroke();
                            ctx.beginPath(); ctx.arc(x2, y2, 5, 0, Math.PI * 2); ctx.stroke();
                        }
                    }
                }
                ctx.restore();
            });
        });
    }

    roundRect(ctx, x, y, width, height, radius) {
        ctx.beginPath();
        ctx.moveTo(x + radius, y);
        ctx.lineTo(x + width - radius, y);
        ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
        ctx.lineTo(x + width, y + height - radius);
        ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
        ctx.lineTo(x + radius, y + height);
        ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
        ctx.lineTo(x, y + radius);
        ctx.quadraticCurveTo(x, y, x + radius, y);
        ctx.closePath();
    }

    initSettingsPanel() {
        const panel = document.getElementById('trendlineSettingsPanel');
        const header = document.getElementById('tlPanelHeader');
        this.activeTLTab = 'style';
        
        // Dragging Logic
        let isDragging = false;
        let startX, startY, initialX, initialY;

        header.addEventListener('mousedown', (e) => {
            if (e.target.closest('button')) return; // Allow clicking the close button
            isDragging = true;
            startX = e.clientX;
            startY = e.clientY;
            
            const rect = panel.getBoundingClientRect();
            initialX = rect.left;
            initialY = rect.top;
            
            panel.classList.remove('left-1/2', '-translate-x-1/2', 'top-14');
            panel.style.left = initialX + 'px';
            panel.style.top = initialY + 'px';
            panel.style.margin = '0';
            
            e.preventDefault();
        });

        window.addEventListener('mousemove', (e) => {
            if (!isDragging) return;
            const dx = e.clientX - startX;
            const dy = e.clientY - startY;
            panel.style.left = (initialX + dx) + 'px';
            panel.style.top = (initialY + dy) + 'px';
        });

        window.addEventListener('mouseup', () => {
            isDragging = false;
        });

        // Global functions for HTML event handlers
        window.toggleTLSettings = (show) => this.toggleSettingsPanel(show);
        
        window.switchTLTab = (tab) => {
            this.activeTLTab = tab;
            const isLineWithText = this.selectedDrawing && ['trend_line', 'ray', 'rectangle', 'horizontal_line', 'vertical_line', 'arrow', 'arrow_pointer'].includes(this.selectedDrawing.type);
            
            document.getElementById('tlTabStyle').className = tab === 'style' ? 'flex-1 py-2 text-center text-blue-500 border-b-2 border-blue-500 font-medium' : 'flex-1 py-2 text-center text-gray-400 hover:text-white';
            
            const textTab = document.getElementById('tlTabText');
            if (isLineWithText) {
                textTab.className = tab === 'text' ? 'flex-1 py-2 text-center text-blue-500 border-b-2 border-blue-500 font-medium' : 'flex-1 py-2 text-center text-gray-400 hover:text-white';
                textTab.style.display = 'block';
                document.getElementById('tlContentText').className = tab === 'text' ? 'block' : 'hidden';
            } else {
                textTab.style.display = 'none';
                document.getElementById('tlContentText').className = 'hidden';
            }
            
            document.getElementById('tlContentStyle').className = tab === 'style' ? 'block' : 'hidden';
            
            const textPicker = document.getElementById('tlTextColorPicker');
            if (textPicker) textPicker.classList.add('hidden');

            this.updateSettingsPanelUI();
        };

        window.setTLThickness = (width) => this.applySettings('width', width);
        window.setTLStyle = (style) => this.applySettings('style', style);
        window.toggleTLBold = () => {
            const current = this.selectedDrawing && ['trend_line', 'ray', 'rectangle', 'horizontal_line', 'vertical_line', 'arrow', 'arrow_pointer'].includes(this.selectedDrawing.type) ? this.selectedDrawing.bold : this.defaults.trend_line.bold;
            this.applySettings('bold', !current);
        };
        window.toggleTLItalic = () => {
            const current = this.selectedDrawing && ['trend_line', 'ray', 'rectangle', 'horizontal_line', 'vertical_line', 'arrow', 'arrow_pointer'].includes(this.selectedDrawing.type) ? this.selectedDrawing.italic : this.defaults.trend_line.italic;
            this.applySettings('italic', !current);
        };

        // Initialize Color Grids
        const colors = [
            '#ffffff', '#e0e0e0', '#bdbdbd', '#9e9e9e', '#757575', '#616161', '#424242', '#212121', '#000000',
            '#ef5350', '#ff9800', '#ffeb3b', '#66bb6a', '#009688', '#00bcd4', '#2962ff', '#673ab7', '#9c27b0', '#e91e63',
            '#ffcdd2', '#ffe0b2', '#fff9c4', '#c8e6c9', '#b2dfdb', '#b2ebf2', '#bbdefb', '#d1c4e9', '#e1bee7', '#f8bbd0',
            '#ef9a9a', '#ffcc80', '#fff59d', '#a5d6a7', '#80cbc4', '#80deea', '#90caf9', '#b39ddb', '#ce93d8', '#f48fb1',
            '#e57373', '#ffb74d', '#fff176', '#81c784', '#4db6ac', '#4dd0e1', '#64b5f6', '#9575cd', '#ba68c8', '#f06292',
            '#f44336', '#fb8c00', '#fdd835', '#4caf50', '#00897b', '#00acc1', '#1e88e5', '#5e35b1', '#8e24aa', '#d81b60',
            '#c62828', '#ef6c00', '#f9a825', '#2e7d32', '#00695c', '#00838f', '#1565c0', '#4527a0', '#6a1b9a', '#ad1457',
            '#b71c1c', '#e65100', '#f57f17', '#1b5e20', '#004d40', '#006064', '#0d47a1', '#311b92', '#4a148c', '#880e4f'
        ];

        const styleGrid = document.getElementById('tlColorGrid');
        const textGrid = document.getElementById('tlTextColorGrid');

        const populateGrid = (gridEl, key, closePopupEl = null) => {
            if (!gridEl) return;
            gridEl.innerHTML = '';
            colors.forEach(color => {
                const btn = document.createElement('div');
                btn.className = 'color-swatch';
                btn.style.backgroundColor = color;
                btn.onclick = (e) => {
                    e.stopPropagation();
                    this.applySettings(key, color);
                    if (closePopupEl) closePopupEl.classList.add('hidden');
                };
                gridEl.appendChild(btn);
            });
        };

        populateGrid(styleGrid, 'color');
        populateGrid(textGrid, 'textColor', document.getElementById('tlTextColorPicker'));
        
        const textColorBtn = document.getElementById('tlTextColorBtn');
        const textPicker = document.getElementById('tlTextColorPicker');
        if (textColorBtn && textPicker) {
            textColorBtn.onclick = (e) => {
                e.stopPropagation();
                textPicker.classList.toggle('hidden');
            };
        }

        // Bind Inputs
        document.getElementById('tlOpacityInput').addEventListener('input', (e) => {
            document.getElementById('tlOpacityValue').textContent = e.target.value + '%';
            this.applySettings('opacity', parseInt(e.target.value));
        });

        document.getElementById('tlFontSize').addEventListener('change', (e) => {
            this.applySettings('fontSize', parseInt(e.target.value));
        });

        document.getElementById('tlTextInput').addEventListener('input', (e) => {
            this.applySettings('text', e.target.value);
        });
        
        document.getElementById('tlTextInput').addEventListener('keydown', (e) => {
            e.stopPropagation();
        });
        
        document.getElementById('tlAlignVert').addEventListener('change', (e) => {
            this.applySettings('alignVert', e.target.value);
        });
        
        document.getElementById('tlAlignHorz').addEventListener('change', (e) => {
            this.applySettings('alignHorz', e.target.value);
        });

        // Close on click outside
        document.addEventListener('mousedown', (e) => {
            const panel = document.getElementById('trendlineSettingsPanel');
            const toolbar = document.getElementById('drawingToolbar');
            const textPicker = document.getElementById('tlTextColorPicker');
            
            if (textPicker && !textPicker.classList.contains('hidden') && !textPicker.contains(e.target) && e.target !== document.getElementById('tlTextColorBtn')) {
                textPicker.classList.add('hidden');
            }

            if (panel && !panel.classList.contains('hidden')) {
                if (!panel.contains(e.target) && !toolbar.contains(e.target)) {
                    panel.classList.add('hidden');
                }
            }
        });
    }

    toggleSettingsPanel(show = true) {
        const panel = document.getElementById('trendlineSettingsPanel');
        if (!panel) return;
        
        if (show) {
            panel.classList.remove('hidden');
            this.updateSettingsPanelUI();
        } else {
            panel.classList.add('hidden');
        }
    }

    updateSettingsPanelUI() {
        const settings = this.selectedDrawing || this.defaults[this.selectedDrawing ? this.selectedDrawing.type : 'trend_line'];
        
        document.querySelectorAll('#tlColorGrid .color-swatch').forEach(el => {
            if (el.style.backgroundColor === settings.color) el.classList.add('active'); 
            else el.classList.remove('active');
        });

        document.getElementById('tlOpacityInput').value = settings.opacity !== undefined ? settings.opacity : 100;
        document.getElementById('tlOpacityValue').textContent = (settings.opacity !== undefined ? settings.opacity : 100) + '%';
        
        document.querySelectorAll('.tl-thickness-btn').forEach(btn => {
            btn.setAttribute('data-active', parseInt(btn.dataset.thickness) === settings.width);
        });

        document.querySelectorAll('.tl-style-btn').forEach(btn => {
            btn.setAttribute('data-active', parseInt(btn.dataset.style) === settings.style);
        });

        const isLineWithText = this.selectedDrawing && ['trend_line', 'ray', 'rectangle', 'horizontal_line', 'vertical_line', 'arrow', 'arrow_pointer'].includes(this.selectedDrawing.type);
        
        const textColorBtn = document.getElementById('tlTextColorBtn');
        const textPicker = document.getElementById('tlTextColorPicker');
        const fontInput = document.getElementById('tlFontSize');
        const textInput = document.getElementById('tlTextInput');
        const alignVert = document.getElementById('tlAlignVert');
        const alignHorz = document.getElementById('tlAlignHorz');
        const boldBtn = document.getElementById('tlBoldBtn');
        const italicBtn = document.getElementById('tlItalicBtn');
        
        if (isLineWithText) {
            if (textColorBtn && textPicker) {
                textColorBtn.style.backgroundColor = settings.textColor || settings.color;
            }
            fontInput.value = settings.fontSize || 14;
            textInput.value = settings.text || '';
            boldBtn.setAttribute('data-active', !!settings.bold);
            italicBtn.setAttribute('data-active', !!settings.italic);
            alignVert.value = settings.alignVert || 'top';
            alignHorz.value = settings.alignHorz || 'left';
        } else {
            if (textPicker) textPicker.classList.add('hidden');
        }
    }

    applySettings(key, value) {
        if (this.selectedDrawing) {
            if (key === 'bold' || key === 'italic' || key === 'fontSize' || key === 'text' || key === 'textColor' || key === 'alignVert' || key === 'alignHorz') {
                const isLineWithText = ['trend_line', 'ray', 'rectangle', 'horizontal_line', 'vertical_line', 'arrow', 'arrow_pointer'].includes(this.selectedDrawing.type);
                if (!isLineWithText) return;
                this.selectedDrawing[key] = value;
            } else {
                this.selectedDrawing[key] = value;
            }
            this.update();
        } else {
            const drawingType = this.selectedDrawing ? this.selectedDrawing.type : 'trend_line';
            if (key === 'bold' || key === 'italic' || key === 'fontSize' || key === 'text' || key === 'textColor' || key === 'alignVert' || key === 'alignHorz') {
                if (drawingType === 'trend_line' || drawingType === 'ray' || drawingType === 'rectangle') {
                    this.defaults.trend_line[key] = value;
                }
            } else {
                if (drawingType === 'trend_line' || drawingType === 'ray' || drawingType === 'rectangle') {
                    this.defaults.trend_line[key] = value;
                } else if (drawingType === 'horizontal_line') {
                    this.defaults.horizontal_line[key] = value;
                } else if (drawingType === 'vertical_line') {
                    this.defaults.vertical_line[key] = value;
                } else if (drawingType === 'arrow' || drawingType === 'arrow_pointer') {
                    this.defaults.arrow[key] = value;
                } else {
                    this.defaults.trend_line[key] = value;
                }
            }
        }
        this.updateSettingsPanelUI();
    }
}
