/* ============================================
   RSL Gantt Chart Component
   Version: 1.0.0
   Description: A powerful, zero-dependency Gantt chart
   for project timeline visualization and management.
   ============================================ */

(function() {
    'use strict';

    // Initialize RSL namespace
    window.RSL = window.RSL || {};

    /**
     * RSL Gantt Chart Component
     */
    class GanttChart {
        constructor(element, options = {}) {
            this.container = typeof element === 'string'
                ? document.querySelector(element)
                : element;

            if (!this.container) {
                console.error('RSL Gantt: Container element not found');
                return;
            }

            // Parse data attributes
            const dataOptions = this._parseDataAttributes();

            // Merge options
            this.options = Object.assign({
                // Data
                tasks: [],

                // Identity
                title: null, // Name for this chart (used in aria-label for accessibility)

                // Display
                zoom: 'week',
                showTaskList: true,
                showProgress: true,
                showToday: true,
                showWeekends: true,
                showDependencies: true,
                highlightCriticalPath: false,

                // Behavior
                editable: true,
                resizable: true,
                draggable: true,

                // Dimensions
                rowHeight: 40,
                headerHeight: 60,
                taskListWidth: 300,
                minColumnWidth: 40,

                // Date range (auto-calculated if not provided)
                startDate: null,
                endDate: null,

                // Export
                exportable: true,
                exportFormats: ['png', 'csv', 'json'],
                exportFilename: 'gantt-chart',

                // Callbacks
                onTaskClick: null,
                onTaskDoubleClick: null,
                onTaskUpdate: null,
                onTaskCreate: null,
                onTaskDelete: null,
                onSelectionChange: null,
                onZoomChange: null

            }, dataOptions, options);

            // State
            this.state = {
                tasks: [],
                selectedTaskIds: new Set(),
                expandedGroups: new Set(),
                zoom: this.options.zoom,
                scrollLeft: 0,
                scrollTop: 0,
                dateRange: { start: null, end: null },
                columnWidth: 0,
                totalWidth: 0,
                isDragging: false,
                isResizing: false,
                dragTask: null,
                resizeTask: null,
                resizeHandle: null
            };

            // DOM References
            this.elements = {};

            // Initialize
            this._init();
        }

        /**
         * Parse data attributes from container
         */
        _parseDataAttributes() {
            const data = this.container.dataset;
            const options = {};

            if (data.ganttTitle) options.title = data.ganttTitle;
            if (data.ganttZoom) options.zoom = data.ganttZoom;
            if (data.ganttEditable !== undefined) options.editable = data.ganttEditable !== 'false';
            if (data.ganttShowProgress !== undefined) options.showProgress = data.ganttShowProgress !== 'false';
            if (data.ganttShowToday !== undefined) options.showToday = data.ganttShowToday !== 'false';
            if (data.ganttShowWeekends !== undefined) options.showWeekends = data.ganttShowWeekends !== 'false';
            if (data.ganttShowDependencies !== undefined) options.showDependencies = data.ganttShowDependencies !== 'false';
            if (data.ganttShowTaskList !== undefined) options.showTaskList = data.ganttShowTaskList !== 'false';
            if (data.ganttHighlightCriticalPath !== undefined) options.highlightCriticalPath = data.ganttHighlightCriticalPath === 'true';
            if (data.ganttRowHeight) options.rowHeight = parseInt(data.ganttRowHeight, 10);
            if (data.ganttStartDate) options.startDate = data.ganttStartDate;
            if (data.ganttEndDate) options.endDate = data.ganttEndDate;
            if (data.ganttExportable !== undefined) options.exportable = data.ganttExportable !== 'false';
            if (data.ganttExportFormats) options.exportFormats = data.ganttExportFormats.split(',');
            if (data.ganttExportFilename) options.exportFilename = data.ganttExportFilename;

            return options;
        }

        /**
         * Initialize the Gantt chart
         */
        _init() {
            // Load tasks from options or parse from table
            this._loadTasks();

            // Calculate date range
            this._calculateDateRange();

            // Build the UI
            this._buildUI();

            // Render the chart
            this._render();

            // Setup event listeners
            this._setupEventListeners();

            // Mark as initialized
            this.container.setAttribute('data-rsl-gantt-initialized', 'true');

            // Dispatch init event
            this._dispatchEvent('init', { instance: this });
        }

        /**
         * Load tasks from various sources
         */
        _loadTasks() {
            // Priority 1: Tasks from options
            if (this.options.tasks && this.options.tasks.length > 0) {
                this.state.tasks = this._normalizeTasks(this.options.tasks);
                return;
            }

            // Priority 2: Tasks from table inside container
            const table = this.container.querySelector('table');
            if (table) {
                this.state.tasks = this._parseTasksFromTable(table);
                table.style.display = 'none';
                return;
            }

            // Priority 3: Tasks from JSON script tag
            const script = this.container.querySelector('script[type="application/json"]');
            if (script) {
                try {
                    const data = JSON.parse(script.textContent);
                    this.state.tasks = this._normalizeTasks(data.tasks || data);
                } catch (e) {
                    console.error('RSL Gantt: Failed to parse JSON data', e);
                }
                return;
            }

            // Empty state
            this.state.tasks = [];
        }

        /**
         * Parse tasks from HTML table
         */
        _parseTasksFromTable(table) {
            const tasks = [];
            const rows = table.querySelectorAll('tbody tr');

            rows.forEach((row, index) => {
                const cells = row.querySelectorAll('td');
                if (cells.length < 3) return;

                const task = {
                    id: row.dataset.taskId || `task-${index + 1}`,
                    name: cells[0]?.textContent?.trim() || `Task ${index + 1}`,
                    start: this._parseDate(row.dataset.taskStart || cells[1]?.textContent?.trim()),
                    end: this._parseDate(row.dataset.taskEnd || cells[2]?.textContent?.trim()),
                    progress: parseInt(row.dataset.taskProgress || cells[3]?.textContent?.trim() || '0', 10),
                    type: row.dataset.taskType || 'task',
                    color: row.dataset.taskColor || null,
                    depends: row.dataset.taskDepends ? row.dataset.taskDepends.split(',').map(s => s.trim()) : [],
                    parentId: row.dataset.taskParent || null,
                    assignee: row.dataset.taskAssignee || cells[4]?.textContent?.trim() || null,
                    collapsed: false
                };

                tasks.push(task);
            });

            return tasks;
        }

        /**
         * Normalize tasks to consistent format
         */
        _normalizeTasks(tasks) {
            return tasks.map((task, index) => ({
                id: task.id || `task-${index + 1}`,
                name: task.name || task.title || `Task ${index + 1}`,
                start: this._parseDate(task.start || task.startDate),
                end: this._parseDate(task.end || task.endDate),
                progress: parseInt(task.progress || 0, 10),
                type: task.type || 'task',
                color: task.color || null,
                depends: Array.isArray(task.depends) ? task.depends :
                         (task.depends ? task.depends.split(',').map(s => s.trim()) : []),
                parentId: task.parentId || task.parent || null,
                assignee: task.assignee || null,
                collapsed: task.collapsed || false,
                data: task.data || {}
            }));
        }

        /**
         * Parse date from various formats
         */
        _parseDate(dateStr) {
            if (!dateStr) return null;
            if (dateStr instanceof Date) return dateStr;

            // Try parsing ISO format
            const date = new Date(dateStr);
            if (!isNaN(date.getTime())) return date;

            // Try parsing common formats
            const formats = [
                /^(\d{4})-(\d{2})-(\d{2})$/,           // YYYY-MM-DD
                /^(\d{2})\/(\d{2})\/(\d{4})$/,         // MM/DD/YYYY
                /^(\d{2})-(\d{2})-(\d{4})$/            // DD-MM-YYYY
            ];

            for (const format of formats) {
                const match = dateStr.match(format);
                if (match) {
                    return new Date(match[1], match[2] - 1, match[3]);
                }
            }

            return null;
        }

        /**
         * Format date for display
         */
        _formatDate(date, format = 'short') {
            if (!date) return '';

            const d = new Date(date);
            const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
            const fullMonths = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];

            switch (format) {
                case 'short':
                    return `${months[d.getMonth()]} ${d.getDate()}`;
                case 'medium':
                    return `${months[d.getMonth()]} ${d.getDate()}, ${d.getFullYear()}`;
                case 'long':
                    return `${fullMonths[d.getMonth()]} ${d.getDate()}, ${d.getFullYear()}`;
                case 'iso':
                    return d.toISOString().split('T')[0];
                default:
                    return `${months[d.getMonth()]} ${d.getDate()}`;
            }
        }

        /**
         * Calculate date range from tasks
         */
        _calculateDateRange() {
            let minDate = this.options.startDate ? this._parseDate(this.options.startDate) : null;
            let maxDate = this.options.endDate ? this._parseDate(this.options.endDate) : null;

            if (!minDate || !maxDate) {
                this.state.tasks.forEach(task => {
                    if (task.start && (!minDate || task.start < minDate)) {
                        minDate = new Date(task.start);
                    }
                    if (task.end && (!maxDate || task.end > maxDate)) {
                        maxDate = new Date(task.end);
                    }
                    // For milestones, use start as both
                    if (task.type === 'milestone' && task.start) {
                        if (!maxDate || task.start > maxDate) {
                            maxDate = new Date(task.start);
                        }
                    }
                });
            }

            // Default to current month if no tasks
            if (!minDate) {
                minDate = new Date();
                minDate.setDate(1);
            }
            if (!maxDate) {
                maxDate = new Date(minDate);
                maxDate.setMonth(maxDate.getMonth() + 1);
            }

            // Add padding based on zoom level
            const padding = this._getDatePadding();
            minDate = new Date(minDate);
            minDate.setDate(minDate.getDate() - padding);
            maxDate = new Date(maxDate);
            maxDate.setDate(maxDate.getDate() + padding);

            this.state.dateRange = { start: minDate, end: maxDate };
        }

        /**
         * Get date padding based on zoom level
         */
        _getDatePadding() {
            const paddings = {
                day: 3,
                week: 7,
                month: 15,
                quarter: 30,
                year: 60
            };
            return paddings[this.state.zoom] || 7;
        }

        /**
         * Build the UI structure
         */
        _buildUI() {
            this.container.innerHTML = '';
            this.container.classList.add('rsl-gantt');
            this.container.setAttribute('role', 'application');

            // Build aria-label with title if provided
            const chartLabel = this.options.title
                ? `${this.options.title} - Gantt chart`
                : 'Gantt chart - Interactive project timeline';
            this.container.setAttribute('aria-label', chartLabel);

            // Create toolbar
            if (this.options.exportable || this.options.editable) {
                this.elements.toolbar = this._createToolbar();
                this.container.appendChild(this.elements.toolbar);
            }

            // Create main body
            this.elements.body = document.createElement('div');
            this.elements.body.className = 'rsl-gantt-body';
            this.elements.body.setAttribute('role', 'group');
            this.elements.body.setAttribute('aria-label', 'Chart content');

            // Create task list (left panel)
            if (this.options.showTaskList) {
                this.elements.taskList = this._createTaskList();
                this.elements.body.appendChild(this.elements.taskList);
            }

            // Create mobile overlay (for closing task list on mobile)
            this.elements.mobileOverlay = document.createElement('div');
            this.elements.mobileOverlay.className = 'rsl-gantt-mobile-overlay';
            this.elements.mobileOverlay.addEventListener('click', () => this._toggleMobileTaskList(false));
            this.elements.body.appendChild(this.elements.mobileOverlay);

            // Create timeline (right panel)
            this.elements.timeline = this._createTimeline();
            this.elements.body.appendChild(this.elements.timeline);

            this.container.appendChild(this.elements.body);

            // Create tooltip (append to body for proper positioning)
            this.elements.tooltip = this._createTooltip();
            document.body.appendChild(this.elements.tooltip);

            // Create context menu
            this.elements.contextMenu = this._createContextMenu();
            document.body.appendChild(this.elements.contextMenu);
        }

        /**
         * Create toolbar
         */
        _createToolbar() {
            const toolbar = document.createElement('div');
            toolbar.className = 'rsl-gantt-toolbar';
            toolbar.setAttribute('role', 'toolbar');
            toolbar.setAttribute('aria-label', 'Gantt chart controls');

            // Mobile toggle button (for showing/hiding task list on mobile)
            const mobileToggle = document.createElement('button');
            mobileToggle.className = 'rsl-gantt-mobile-toggle';
            mobileToggle.innerHTML = '<i class="fas fa-bars" aria-hidden="true"></i>';
            mobileToggle.setAttribute('aria-label', 'Show or hide task list panel');
            mobileToggle.setAttribute('aria-expanded', 'false');
            mobileToggle.addEventListener('click', () => this._toggleMobileTaskList());
            this.elements.mobileToggle = mobileToggle;
            toolbar.appendChild(mobileToggle);

            // Today button
            const todayBtn = this._createButton('Today', 'fa-calendar-day', () => this.scrollToToday(), 'Scroll timeline to today\'s date');
            toolbar.appendChild(todayBtn);

            toolbar.appendChild(this._createDivider());

            // Zoom selector
            const zoomGroup = document.createElement('div');
            zoomGroup.className = 'rsl-gantt-zoom-selector';
            zoomGroup.setAttribute('role', 'group');
            zoomGroup.setAttribute('aria-label', 'Timeline zoom level');

            const zoomLevels = [
                { id: 'day', label: 'Day', description: 'View timeline by day' },
                { id: 'week', label: 'Week', description: 'View timeline by week' },
                { id: 'month', label: 'Month', description: 'View timeline by month' },
                { id: 'quarter', label: 'Quarter', description: 'View timeline by quarter' },
                { id: 'year', label: 'Year', description: 'View timeline by year' }
            ];

            zoomLevels.forEach(level => {
                const btn = this._createButton(level.label, null, () => this.setZoom(level.id), level.description);
                btn.dataset.zoom = level.id;
                btn.setAttribute('aria-pressed', level.id === this.state.zoom ? 'true' : 'false');
                if (level.id === this.state.zoom) btn.classList.add('active');
                zoomGroup.appendChild(btn);
            });
            this.elements.zoomGroup = zoomGroup;

            toolbar.appendChild(zoomGroup);

            toolbar.appendChild(this._createDivider());

            // Expand/Collapse all
            const expandAllBtn = this._createButton('', 'fa-expand-alt', () => this.expandAll(), 'Expand all task groups to show subtasks');
            expandAllBtn.classList.add('rsl-gantt-btn-icon');
            expandAllBtn.setAttribute('aria-label', 'Expand all task groups to show subtasks');
            this.elements.expandAllBtn = expandAllBtn;
            toolbar.appendChild(expandAllBtn);

            const collapseAllBtn = this._createButton('', 'fa-compress-alt', () => this.collapseAll(), 'Collapse all task groups to hide subtasks');
            collapseAllBtn.classList.add('rsl-gantt-btn-icon');
            collapseAllBtn.setAttribute('aria-label', 'Collapse all task groups to hide subtasks');
            this.elements.collapseAllBtn = collapseAllBtn;
            toolbar.appendChild(collapseAllBtn);

            // Search
            const search = document.createElement('div');
            search.className = 'rsl-gantt-search';
            search.innerHTML = `
                <i class="fas fa-search"></i>
                <input type="text" placeholder="Search tasks..." aria-label="Search tasks">
            `;
            this.elements.searchInput = search.querySelector('input');
            toolbar.appendChild(search);

            // Spacer
            const spacer = document.createElement('div');
            spacer.style.flex = '1';
            toolbar.appendChild(spacer);

            // Date range display
            const dateRange = document.createElement('div');
            dateRange.className = 'rsl-gantt-date-range';
            this.elements.dateRangeDisplay = dateRange;
            toolbar.appendChild(dateRange);

            // Export button
            if (this.options.exportable) {
                toolbar.appendChild(this._createDivider());

                const exportBtn = this._createButton('Export', 'fa-download', () => this._showExportModal());
                toolbar.appendChild(exportBtn);
            }

            return toolbar;
        }

        /**
         * Create button element
         */
        _createButton(text, icon, onClick, title) {
            const btn = document.createElement('button');
            btn.className = 'rsl-gantt-btn';
            btn.type = 'button';
            if (title) {
                btn.title = title;
                // If no text, use title as aria-label
                if (!text) {
                    btn.setAttribute('aria-label', title);
                }
            }
            if (icon) btn.innerHTML = `<i class="fas ${icon}" aria-hidden="true"></i>`;
            if (text) btn.innerHTML += `<span>${text}</span>`;
            if (onClick) btn.addEventListener('click', onClick);
            return btn;
        }

        /**
         * Create divider element
         */
        _createDivider() {
            const divider = document.createElement('div');
            divider.className = 'rsl-gantt-toolbar-divider';
            return divider;
        }

        /**
         * Create task list panel
         */
        _createTaskList() {
            const taskList = document.createElement('div');
            taskList.className = 'rsl-gantt-task-list';
            taskList.setAttribute('role', 'region');
            taskList.setAttribute('aria-label', 'Task list');

            // Header
            const header = document.createElement('div');
            header.className = 'rsl-gantt-task-list-header';
            header.setAttribute('role', 'rowgroup');
            header.innerHTML = `
                <div class="rsl-gantt-task-list-header-cell" role="columnheader">Task Name</div>
            `;
            taskList.appendChild(header);

            // Body
            const body = document.createElement('div');
            body.className = 'rsl-gantt-task-list-body';
            body.setAttribute('role', 'rowgroup');
            body.setAttribute('aria-label', 'Tasks');
            this.elements.taskListBody = body;
            taskList.appendChild(body);

            // Resize handle
            const resizeHandle = document.createElement('div');
            resizeHandle.className = 'rsl-gantt-resize-handle';
            resizeHandle.setAttribute('role', 'separator');
            resizeHandle.setAttribute('aria-label', 'Resize task list panel');
            resizeHandle.setAttribute('tabindex', '0');
            taskList.appendChild(resizeHandle);

            return taskList;
        }

        /**
         * Create timeline panel
         */
        _createTimeline() {
            const timeline = document.createElement('div');
            timeline.className = 'rsl-gantt-timeline';
            timeline.setAttribute('role', 'region');
            timeline.setAttribute('aria-label', 'Timeline chart');

            // Header
            const header = document.createElement('div');
            header.className = 'rsl-gantt-timeline-header';
            header.setAttribute('role', 'rowgroup');
            header.setAttribute('aria-label', 'Timeline dates');

            const headerScroll = document.createElement('div');
            headerScroll.className = 'rsl-gantt-timeline-header-scroll';
            this.elements.timelineHeader = headerScroll;
            header.appendChild(headerScroll);

            timeline.appendChild(header);

            // Body
            const body = document.createElement('div');
            body.className = 'rsl-gantt-timeline-body';
            body.setAttribute('aria-label', 'Task bars - use arrow keys to navigate');

            const scroll = document.createElement('div');
            scroll.className = 'rsl-gantt-timeline-scroll';
            this.elements.timelineScroll = scroll;

            // Grid background
            const grid = document.createElement('div');
            grid.className = 'rsl-gantt-grid';
            this.elements.grid = grid;
            scroll.appendChild(grid);

            // Dependencies SVG
            const deps = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
            deps.setAttribute('class', 'rsl-gantt-dependencies');
            this.elements.dependencies = deps;
            scroll.appendChild(deps);

            // Task bars container
            const bars = document.createElement('div');
            bars.className = 'rsl-gantt-bars';
            this.elements.bars = bars;
            scroll.appendChild(bars);

            // Today line
            if (this.options.showToday) {
                const todayLine = document.createElement('div');
                todayLine.className = 'rsl-gantt-today-line';
                this.elements.todayLine = todayLine;
                scroll.appendChild(todayLine);
            }

            body.appendChild(scroll);
            this.elements.timelineBody = body;
            timeline.appendChild(body);

            return timeline;
        }

        /**
         * Create tooltip element
         */
        _createTooltip() {
            const tooltip = document.createElement('div');
            tooltip.className = 'rsl-gantt-tooltip';
            tooltip.setAttribute('role', 'tooltip');
            return tooltip;
        }

        /**
         * Create context menu
         */
        _createContextMenu() {
            const menu = document.createElement('div');
            menu.className = 'rsl-gantt-context-menu';
            menu.style.display = 'none';

            const items = [
                { icon: 'fa-edit', label: 'Edit Task', action: 'edit' },
                { icon: 'fa-plus', label: 'Add Subtask', action: 'add-subtask' },
                { divider: true },
                { icon: 'fa-arrow-up', label: 'Move Up', action: 'move-up' },
                { icon: 'fa-arrow-down', label: 'Move Down', action: 'move-down' },
                { divider: true },
                { icon: 'fa-copy', label: 'Duplicate', action: 'duplicate' },
                { icon: 'fa-trash', label: 'Delete', action: 'delete', danger: true }
            ];

            items.forEach(item => {
                if (item.divider) {
                    const divider = document.createElement('div');
                    divider.className = 'rsl-gantt-context-menu-divider';
                    menu.appendChild(divider);
                } else {
                    const menuItem = document.createElement('div');
                    menuItem.className = 'rsl-gantt-context-menu-item';
                    if (item.danger) menuItem.classList.add('danger');
                    menuItem.dataset.action = item.action;
                    menuItem.innerHTML = `<i class="fas ${item.icon}"></i><span>${item.label}</span>`;
                    menu.appendChild(menuItem);
                }
            });

            return menu;
        }

        /**
         * Render the chart
         */
        _render() {
            this._calculateDimensions();
            this._renderHeader();
            this._renderGrid();
            this._renderTaskList();
            this._renderBars();
            this._renderDependencies();
            this._renderTodayLine();
            this._updateDateRangeDisplay();
            this._updateExpandCollapseButtons();
        }

        /**
         * Update expand/collapse button states based on whether groups exist
         */
        _updateExpandCollapseButtons() {
            if (!this.elements.expandAllBtn || !this.elements.collapseAllBtn) return;

            // Check if any tasks have type 'group' or have children (parentId references)
            const hasGroups = this.state.tasks.some(task => task.type === 'group');
            const hasChildren = this.state.tasks.some(task => task.parentId);
            const hasHierarchy = hasGroups || hasChildren;

            if (hasHierarchy) {
                this.elements.expandAllBtn.disabled = false;
                this.elements.collapseAllBtn.disabled = false;
                this.elements.expandAllBtn.style.opacity = '1';
                this.elements.collapseAllBtn.style.opacity = '1';
                this.elements.expandAllBtn.style.cursor = 'pointer';
                this.elements.collapseAllBtn.style.cursor = 'pointer';
            } else {
                this.elements.expandAllBtn.disabled = true;
                this.elements.collapseAllBtn.disabled = true;
                this.elements.expandAllBtn.style.opacity = '0.4';
                this.elements.collapseAllBtn.style.opacity = '0.4';
                this.elements.expandAllBtn.style.cursor = 'not-allowed';
                this.elements.collapseAllBtn.style.cursor = 'not-allowed';
            }
        }

        /**
         * Calculate timeline dimensions
         */
        _calculateDimensions() {
            const { start, end } = this.state.dateRange;
            const days = Math.ceil((end - start) / (1000 * 60 * 60 * 24));

            // Calculate column width based on zoom
            const columnWidths = {
                day: 60,
                week: 100,
                month: 120,
                quarter: 80,
                year: 50
            };

            // Calculate number of columns
            let columns;
            switch (this.state.zoom) {
                case 'day':
                    columns = days;
                    break;
                case 'week':
                    columns = Math.ceil(days / 7);
                    break;
                case 'month':
                    columns = this._getMonthsBetween(start, end);
                    break;
                case 'quarter':
                    columns = Math.ceil(this._getMonthsBetween(start, end) / 3);
                    break;
                case 'year':
                    columns = end.getFullYear() - start.getFullYear() + 1;
                    break;
                default:
                    columns = Math.ceil(days / 7);
            }

            this.state.columnWidth = columnWidths[this.state.zoom] || 100;
            this.state.totalWidth = columns * this.state.columnWidth;
            this.state.columns = columns;
            this.state.days = days;
        }

        /**
         * Get months between two dates
         */
        _getMonthsBetween(start, end) {
            return (end.getFullYear() - start.getFullYear()) * 12 +
                   (end.getMonth() - start.getMonth()) + 1;
        }

        /**
         * Render timeline header
         */
        _renderHeader() {
            const header = this.elements.timelineHeader;
            header.innerHTML = '';
            header.style.width = `${this.state.totalWidth}px`;

            const primaryRow = document.createElement('div');
            primaryRow.className = 'rsl-gantt-header-row primary';

            const secondaryRow = document.createElement('div');
            secondaryRow.className = 'rsl-gantt-header-row secondary';

            const { start, end } = this.state.dateRange;
            const today = new Date();
            today.setHours(0, 0, 0, 0);

            switch (this.state.zoom) {
                case 'day':
                    this._renderDayHeader(primaryRow, secondaryRow, start, today);
                    break;
                case 'week':
                    this._renderWeekHeader(primaryRow, secondaryRow, start, today);
                    break;
                case 'month':
                    this._renderMonthHeader(primaryRow, secondaryRow, start, end, today);
                    break;
                case 'quarter':
                    this._renderQuarterHeader(primaryRow, secondaryRow, start, end);
                    break;
                case 'year':
                    this._renderYearHeader(primaryRow, secondaryRow, start, end);
                    break;
            }

            header.appendChild(primaryRow);
            header.appendChild(secondaryRow);
        }

        /**
         * Render day zoom header
         */
        _renderDayHeader(primaryRow, secondaryRow, start, today) {
            let currentMonth = -1;
            let monthCell = null;
            let monthDays = 0;

            for (let i = 0; i < this.state.days; i++) {
                const date = new Date(start);
                date.setDate(date.getDate() + i);

                // Primary row (months)
                if (date.getMonth() !== currentMonth) {
                    if (monthCell) {
                        monthCell.style.width = `${monthDays * this.state.columnWidth}px`;
                    }
                    currentMonth = date.getMonth();
                    monthCell = document.createElement('div');
                    monthCell.className = 'rsl-gantt-header-cell primary';
                    monthCell.textContent = this._formatDate(date, 'medium');
                    primaryRow.appendChild(monthCell);
                    monthDays = 0;
                }
                monthDays++;

                // Secondary row (days)
                const dayCell = document.createElement('div');
                dayCell.className = 'rsl-gantt-header-cell';
                dayCell.style.width = `${this.state.columnWidth}px`;
                dayCell.textContent = date.getDate();

                const dayOfWeek = date.getDay();
                if (dayOfWeek === 0 || dayOfWeek === 6) {
                    dayCell.classList.add('weekend');
                }
                if (date.getTime() === today.getTime()) {
                    dayCell.classList.add('today');
                }

                secondaryRow.appendChild(dayCell);
            }

            // Set width of last month cell
            if (monthCell) {
                monthCell.style.width = `${monthDays * this.state.columnWidth}px`;
            }
        }

        /**
         * Render week zoom header
         */
        _renderWeekHeader(primaryRow, secondaryRow, start, today) {
            let currentMonth = -1;
            let monthCell = null;
            let monthWeeks = 0;

            const weekStart = new Date(start);
            weekStart.setDate(weekStart.getDate() - weekStart.getDay());

            for (let i = 0; i < this.state.columns; i++) {
                const date = new Date(weekStart);
                date.setDate(date.getDate() + (i * 7));

                // Primary row (months)
                if (date.getMonth() !== currentMonth) {
                    if (monthCell) {
                        monthCell.style.width = `${monthWeeks * this.state.columnWidth}px`;
                    }
                    currentMonth = date.getMonth();
                    monthCell = document.createElement('div');
                    monthCell.className = 'rsl-gantt-header-cell primary';
                    monthCell.textContent = `${this._formatDate(date, 'short')} ${date.getFullYear()}`;
                    primaryRow.appendChild(monthCell);
                    monthWeeks = 0;
                }
                monthWeeks++;

                // Secondary row (weeks)
                const weekEnd = new Date(date);
                weekEnd.setDate(weekEnd.getDate() + 6);

                const weekCell = document.createElement('div');
                weekCell.className = 'rsl-gantt-header-cell';
                weekCell.style.width = `${this.state.columnWidth}px`;
                weekCell.textContent = `${date.getDate()}-${weekEnd.getDate()}`;

                const todayTime = today.getTime();
                if (todayTime >= date.getTime() && todayTime <= weekEnd.getTime()) {
                    weekCell.classList.add('today');
                }

                secondaryRow.appendChild(weekCell);
            }

            if (monthCell) {
                monthCell.style.width = `${monthWeeks * this.state.columnWidth}px`;
            }
        }

        /**
         * Render month zoom header
         */
        _renderMonthHeader(primaryRow, secondaryRow, start, end, today) {
            const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
            let currentYear = -1;
            let yearCell = null;
            let yearMonths = 0;

            let date = new Date(start.getFullYear(), start.getMonth(), 1);

            while (date <= end) {
                // Primary row (years)
                if (date.getFullYear() !== currentYear) {
                    if (yearCell) {
                        yearCell.style.width = `${yearMonths * this.state.columnWidth}px`;
                    }
                    currentYear = date.getFullYear();
                    yearCell = document.createElement('div');
                    yearCell.className = 'rsl-gantt-header-cell primary';
                    yearCell.textContent = currentYear;
                    primaryRow.appendChild(yearCell);
                    yearMonths = 0;
                }
                yearMonths++;

                // Secondary row (months)
                const monthCell = document.createElement('div');
                monthCell.className = 'rsl-gantt-header-cell';
                monthCell.style.width = `${this.state.columnWidth}px`;
                monthCell.textContent = months[date.getMonth()];

                if (date.getFullYear() === today.getFullYear() && date.getMonth() === today.getMonth()) {
                    monthCell.classList.add('today');
                }

                secondaryRow.appendChild(monthCell);

                date.setMonth(date.getMonth() + 1);
            }

            if (yearCell) {
                yearCell.style.width = `${yearMonths * this.state.columnWidth}px`;
            }
        }

        /**
         * Render quarter zoom header
         */
        _renderQuarterHeader(primaryRow, secondaryRow, start, end) {
            let currentYear = -1;
            let yearCell = null;
            let yearQuarters = 0;

            const startQuarter = Math.floor(start.getMonth() / 3);
            let date = new Date(start.getFullYear(), startQuarter * 3, 1);

            while (date <= end) {
                // Primary row (years)
                if (date.getFullYear() !== currentYear) {
                    if (yearCell) {
                        yearCell.style.width = `${yearQuarters * this.state.columnWidth}px`;
                    }
                    currentYear = date.getFullYear();
                    yearCell = document.createElement('div');
                    yearCell.className = 'rsl-gantt-header-cell primary';
                    yearCell.textContent = currentYear;
                    primaryRow.appendChild(yearCell);
                    yearQuarters = 0;
                }
                yearQuarters++;

                // Secondary row (quarters)
                const quarter = Math.floor(date.getMonth() / 3) + 1;
                const quarterCell = document.createElement('div');
                quarterCell.className = 'rsl-gantt-header-cell';
                quarterCell.style.width = `${this.state.columnWidth}px`;
                quarterCell.textContent = `Q${quarter}`;

                secondaryRow.appendChild(quarterCell);

                date.setMonth(date.getMonth() + 3);
            }

            if (yearCell) {
                yearCell.style.width = `${yearQuarters * this.state.columnWidth}px`;
            }
        }

        /**
         * Render year zoom header
         */
        _renderYearHeader(primaryRow, secondaryRow, start, end) {
            // Primary row empty for year view
            const emptyCell = document.createElement('div');
            emptyCell.className = 'rsl-gantt-header-cell primary';
            emptyCell.style.width = `${this.state.totalWidth}px`;
            emptyCell.textContent = 'Timeline';
            primaryRow.appendChild(emptyCell);

            // Secondary row (years)
            for (let year = start.getFullYear(); year <= end.getFullYear(); year++) {
                const yearCell = document.createElement('div');
                yearCell.className = 'rsl-gantt-header-cell';
                yearCell.style.width = `${this.state.columnWidth}px`;
                yearCell.textContent = year;
                secondaryRow.appendChild(yearCell);
            }
        }

        /**
         * Render grid background
         */
        _renderGrid() {
            const grid = this.elements.grid;
            grid.innerHTML = '';
            grid.style.width = `${this.state.totalWidth}px`;

            const visibleTasks = this._getVisibleTasks();

            visibleTasks.forEach((task, index) => {
                const row = document.createElement('div');
                row.className = 'rsl-gantt-grid-row';
                row.style.height = `${this.options.rowHeight}px`;

                // Add cells for weekend highlighting in day view
                if (this.state.zoom === 'day' && this.options.showWeekends) {
                    for (let i = 0; i < this.state.days; i++) {
                        const date = new Date(this.state.dateRange.start);
                        date.setDate(date.getDate() + i);
                        const dayOfWeek = date.getDay();

                        const cell = document.createElement('div');
                        cell.className = 'rsl-gantt-grid-cell';
                        cell.style.width = `${this.state.columnWidth}px`;
                        if (dayOfWeek === 0 || dayOfWeek === 6) {
                            cell.classList.add('weekend');
                        }
                        row.appendChild(cell);
                    }
                }

                grid.appendChild(row);
            });

            // Set timeline scroll height
            this.elements.timelineScroll.style.height = `${visibleTasks.length * this.options.rowHeight}px`;
            this.elements.timelineScroll.style.width = `${this.state.totalWidth}px`;
        }

        /**
         * Render task list
         */
        _renderTaskList() {
            if (!this.elements.taskListBody) return;

            const body = this.elements.taskListBody;
            body.innerHTML = '';

            const visibleTasks = this._getVisibleTasks();

            visibleTasks.forEach((task, index) => {
                const row = this._createTaskRow(task, index);
                body.appendChild(row);
            });
        }

        /**
         * Create task row element
         */
        _createTaskRow(task, index) {
            const row = document.createElement('div');
            row.className = 'rsl-gantt-task-row';
            row.dataset.taskId = task.id;
            row.tabIndex = 0;
            row.setAttribute('role', 'row');

            // Build descriptive aria-label
            let ariaLabel = `${task.name}`;
            if (task.type === 'milestone') {
                ariaLabel += `, milestone on ${this._formatDate(task.start, 'medium')}`;
            } else if (task.type === 'group') {
                ariaLabel += `, task group`;
            } else if (task.start && task.end) {
                ariaLabel += `, from ${this._formatDate(task.start, 'medium')} to ${this._formatDate(task.end, 'medium')}`;
            }
            if (task.progress !== undefined && task.progress > 0) {
                ariaLabel += `, ${task.progress}% complete`;
            }
            row.setAttribute('aria-label', ariaLabel);

            if (this.state.selectedTaskIds.has(task.id)) {
                row.classList.add('selected');
                row.setAttribute('aria-selected', 'true');
            }

            // Calculate indent level
            const indent = this._getTaskIndent(task);

            // Expand toggle (for groups)
            const hasChildren = this.state.tasks.some(t => t.parentId === task.id);
            const expand = document.createElement('div');
            expand.className = 'rsl-gantt-task-expand';
            if (hasChildren) {
                const isExpanded = this.state.expandedGroups.has(task.id);
                expand.innerHTML = '<i class="fas fa-chevron-right" aria-hidden="true"></i>';
                expand.setAttribute('role', 'button');
                expand.setAttribute('tabindex', '0');
                expand.setAttribute('aria-expanded', isExpanded ? 'true' : 'false');
                expand.setAttribute('aria-label', isExpanded ? `Collapse ${task.name} group` : `Expand ${task.name} group`);
                if (isExpanded) {
                    expand.classList.add('expanded');
                }
            } else {
                expand.classList.add('hidden');
                expand.setAttribute('aria-hidden', 'true');
            }
            row.appendChild(expand);

            // Task info
            const info = document.createElement('div');
            info.className = 'rsl-gantt-task-info';
            info.style.setProperty('--rsl-gantt-indent', `${indent * 20}px`);

            // Type icon
            const icon = document.createElement('div');
            icon.className = `rsl-gantt-task-icon ${task.type}`;
            const iconMap = {
                task: 'fa-tasks',
                milestone: 'fa-diamond',
                group: 'fa-folder'
            };
            icon.innerHTML = `<i class="fas ${iconMap[task.type] || 'fa-tasks'}"></i>`;
            info.appendChild(icon);

            // Task name
            const name = document.createElement('div');
            name.className = 'rsl-gantt-task-name';
            name.textContent = task.name;
            info.appendChild(name);

            row.appendChild(info);

            // Dates
            const dates = document.createElement('div');
            dates.className = 'rsl-gantt-task-dates';
            if (task.type === 'milestone') {
                dates.textContent = this._formatDate(task.start);
            } else if (task.start && task.end) {
                dates.textContent = `${this._formatDate(task.start)} - ${this._formatDate(task.end)}`;
            }
            row.appendChild(dates);

            return row;
        }

        /**
         * Get task indent level
         */
        _getTaskIndent(task) {
            let indent = 0;
            let currentTask = task;
            while (currentTask.parentId) {
                indent++;
                currentTask = this.state.tasks.find(t => t.id === currentTask.parentId);
                if (!currentTask) break;
            }
            return indent;
        }

        /**
         * Get visible tasks (respecting collapse state and search filter)
         */
        _getVisibleTasks() {
            const visible = [];
            const collapsedParents = new Set();

            // First pass: identify collapsed parents
            this.state.tasks.forEach(task => {
                if (task.type === 'group' && !this.state.expandedGroups.has(task.id)) {
                    collapsedParents.add(task.id);
                }
            });

            // Second pass: filter visible tasks
            this.state.tasks.forEach(task => {
                // Skip hidden tasks (from search filter)
                if (task._hidden) {
                    return;
                }

                let isVisible = true;
                let currentParentId = task.parentId;

                while (currentParentId) {
                    if (collapsedParents.has(currentParentId)) {
                        isVisible = false;
                        break;
                    }
                    const parent = this.state.tasks.find(t => t.id === currentParentId);
                    currentParentId = parent ? parent.parentId : null;
                }

                if (isVisible) {
                    visible.push(task);
                }
            });

            return visible;
        }

        /**
         * Render task bars
         */
        _renderBars() {
            const bars = this.elements.bars;
            bars.innerHTML = '';

            const visibleTasks = this._getVisibleTasks();

            visibleTasks.forEach((task, index) => {
                if (!task.start) return;

                const bar = this._createTaskBar(task, index);
                if (bar) {
                    bars.appendChild(bar);
                }
            });
        }

        /**
         * Create task bar element
         */
        _createTaskBar(task, rowIndex) {
            const { start, end } = this.state.dateRange;
            const totalMs = end - start;

            // Calculate position
            const taskStart = task.start || task.end;
            const taskEnd = task.end || task.start;

            if (!taskStart) return null;

            const startOffset = (taskStart - start) / totalMs;
            const endOffset = (taskEnd - start) / totalMs;

            const left = startOffset * this.state.totalWidth;
            const width = Math.max((endOffset - startOffset) * this.state.totalWidth, 24);

            const bar = document.createElement('div');
            bar.className = 'rsl-gantt-bar';
            bar.classList.add(task.type);
            bar.dataset.taskId = task.id;
            bar.tabIndex = 0;
            bar.setAttribute('role', 'button');

            // Build comprehensive aria-label
            let barLabel = task.name;
            if (task.type === 'milestone') {
                barLabel += `, milestone on ${this._formatDate(taskStart, 'medium')}`;
            } else {
                barLabel += `, from ${this._formatDate(taskStart, 'medium')} to ${this._formatDate(taskEnd, 'medium')}`;
            }
            if (task.progress !== undefined) {
                barLabel += `, ${task.progress}% complete`;
            }
            if (this.options.editable) {
                barLabel += '. Press Enter to select, drag to move.';
            }
            bar.setAttribute('aria-label', barLabel);

            bar.style.left = `${left}px`;
            bar.style.top = `${rowIndex * this.options.rowHeight + (this.options.rowHeight - 24) / 2}px`;

            if (task.type !== 'milestone') {
                bar.style.width = `${width}px`;
            }

            if (task.color) {
                bar.dataset.color = task.color;
            }

            if (this.state.selectedTaskIds.has(task.id)) {
                bar.classList.add('selected');
                bar.setAttribute('aria-pressed', 'true');
            }

            // Progress bar
            if (this.options.showProgress && task.type === 'task' && task.progress > 0) {
                const progress = document.createElement('div');
                progress.className = 'rsl-gantt-bar-progress';
                progress.style.width = `${Math.min(task.progress, 100)}%`;
                bar.appendChild(progress);
            }

            // Label (visual only, info already in aria-label)
            if (task.type === 'task') {
                const label = document.createElement('div');
                label.className = 'rsl-gantt-bar-label';
                label.textContent = task.name;
                label.setAttribute('aria-hidden', 'true');
                bar.appendChild(label);
            }

            // Resize handles
            if (this.options.resizable && this.options.editable && task.type === 'task') {
                const leftHandle = document.createElement('div');
                leftHandle.className = 'rsl-gantt-bar-handle left';
                leftHandle.setAttribute('role', 'slider');
                leftHandle.setAttribute('aria-label', `Resize ${task.name} start date`);
                leftHandle.setAttribute('tabindex', '0');
                bar.appendChild(leftHandle);

                const rightHandle = document.createElement('div');
                rightHandle.className = 'rsl-gantt-bar-handle right';
                rightHandle.setAttribute('role', 'slider');
                rightHandle.setAttribute('aria-label', `Resize ${task.name} end date`);
                rightHandle.setAttribute('tabindex', '0');
                bar.appendChild(rightHandle);
            }

            return bar;
        }

        /**
         * Render dependencies
         */
        _renderDependencies() {
            if (!this.options.showDependencies) return;

            const svg = this.elements.dependencies;
            svg.innerHTML = '';
            svg.setAttribute('width', this.state.totalWidth);
            svg.setAttribute('height', this._getVisibleTasks().length * this.options.rowHeight);

            const visibleTasks = this._getVisibleTasks();
            const taskIndexMap = new Map();
            visibleTasks.forEach((task, index) => taskIndexMap.set(task.id, index));

            visibleTasks.forEach(task => {
                if (!task.depends || task.depends.length === 0) return;

                task.depends.forEach(depId => {
                    const depTask = this.state.tasks.find(t => t.id === depId);
                    if (!depTask || !taskIndexMap.has(depId)) return;

                    this._renderDependencyArrow(svg, depTask, task, taskIndexMap);
                });
            });
        }

        /**
         * Render dependency arrow
         */
        _renderDependencyArrow(svg, fromTask, toTask, taskIndexMap) {
            const { start, end } = this.state.dateRange;
            const totalMs = end - start;

            const fromIndex = taskIndexMap.get(fromTask.id);
            const toIndex = taskIndexMap.get(toTask.id);

            const fromEnd = fromTask.end || fromTask.start;
            const toStart = toTask.start || toTask.end;

            if (!fromEnd || !toStart) return;

            const fromX = ((fromEnd - start) / totalMs) * this.state.totalWidth;
            const fromY = (fromIndex + 0.5) * this.options.rowHeight;
            const toX = ((toStart - start) / totalMs) * this.state.totalWidth;
            const toY = (toIndex + 0.5) * this.options.rowHeight;

            // Create path
            const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
            path.setAttribute('class', 'rsl-gantt-dependency-path');

            // Calculate control points for smooth curve
            const midX = fromX + 20;
            const d = `M ${fromX} ${fromY}
                       L ${midX} ${fromY}
                       Q ${midX + 10} ${fromY} ${midX + 10} ${fromY + (toY > fromY ? 10 : -10)}
                       L ${midX + 10} ${toY - (toY > fromY ? 10 : -10)}
                       Q ${midX + 10} ${toY} ${midX + 20} ${toY}
                       L ${toX - 8} ${toY}`;

            path.setAttribute('d', d);
            svg.appendChild(path);

            // Arrow head
            const arrow = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');
            arrow.setAttribute('class', 'rsl-gantt-dependency-arrow');
            arrow.setAttribute('points', `${toX},${toY} ${toX - 8},${toY - 4} ${toX - 8},${toY + 4}`);
            svg.appendChild(arrow);
        }

        /**
         * Render today line
         */
        _renderTodayLine() {
            if (!this.options.showToday || !this.elements.todayLine) return;

            const today = new Date();
            today.setHours(0, 0, 0, 0);

            const { start, end } = this.state.dateRange;

            if (today < start || today > end) {
                this.elements.todayLine.style.display = 'none';
                return;
            }

            const position = ((today - start) / (end - start)) * this.state.totalWidth;
            this.elements.todayLine.style.left = `${position}px`;
            this.elements.todayLine.style.display = 'block';
        }

        /**
         * Update date range display
         */
        _updateDateRangeDisplay() {
            if (!this.elements.dateRangeDisplay) return;

            const { start, end } = this.state.dateRange;
            this.elements.dateRangeDisplay.innerHTML = `
                <i class="fas fa-calendar-alt"></i>
                <span>${this._formatDate(start, 'medium')} - ${this._formatDate(end, 'medium')}</span>
            `;
        }

        /**
         * Setup event listeners
         */
        _setupEventListeners() {
            // Synchronized scrolling
            if (this.elements.timelineBody && this.elements.taskListBody) {
                this.elements.timelineBody.addEventListener('scroll', () => {
                    this.elements.taskListBody.scrollTop = this.elements.timelineBody.scrollTop;
                    this.elements.timelineHeader.parentElement.scrollLeft = this.elements.timelineBody.scrollLeft;
                });

                this.elements.taskListBody.addEventListener('scroll', () => {
                    this.elements.timelineBody.scrollTop = this.elements.taskListBody.scrollTop;
                });
            }

            // Task list interactions
            if (this.elements.taskListBody) {
                this.elements.taskListBody.addEventListener('click', (e) => this._onTaskListClick(e));
                this.elements.taskListBody.addEventListener('dblclick', (e) => this._onTaskListDoubleClick(e));
            }

            // Task bar interactions
            if (this.elements.bars) {
                this.elements.bars.addEventListener('click', (e) => this._onBarClick(e));
                this.elements.bars.addEventListener('dblclick', (e) => this._onBarDoubleClick(e));
                this.elements.bars.addEventListener('mousedown', (e) => this._onBarMouseDown(e));
                this.elements.bars.addEventListener('contextmenu', (e) => this._onBarContextMenu(e));
            }

            // Mouse move and up for dragging/resizing
            document.addEventListener('mousemove', (e) => this._onMouseMove(e));
            document.addEventListener('mouseup', (e) => this._onMouseUp(e));

            // Search
            if (this.elements.searchInput) {
                this.elements.searchInput.addEventListener('input', (e) => this._onSearch(e.target.value));
            }

            // Task list resize
            if (this.elements.taskList) {
                const resizeHandle = this.elements.taskList.querySelector('.rsl-gantt-resize-handle');
                if (resizeHandle) {
                    resizeHandle.addEventListener('mousedown', (e) => this._onTaskListResizeStart(e));
                }
            }

            // Context menu
            document.addEventListener('click', () => this._hideContextMenu());
            this.elements.contextMenu.addEventListener('click', (e) => this._onContextMenuClick(e));

            // Keyboard navigation
            this.container.addEventListener('keydown', (e) => this._onKeyDown(e));

            // Tooltip
            if (this.elements.bars) {
                this.elements.bars.addEventListener('mouseover', (e) => this._onBarMouseOver(e));
                this.elements.bars.addEventListener('mouseout', () => this._hideTooltip());
            }

            // Window resize
            window.addEventListener('resize', () => this._onWindowResize());
        }

        /**
         * Handle task list click
         */
        _onTaskListClick(e) {
            const row = e.target.closest('.rsl-gantt-task-row');
            if (!row) return;

            const taskId = row.dataset.taskId;
            const expand = e.target.closest('.rsl-gantt-task-expand');

            if (expand && !expand.classList.contains('hidden')) {
                this._toggleGroup(taskId);
            } else {
                this._selectTask(taskId, e.ctrlKey || e.metaKey);
            }
        }

        /**
         * Handle task list double click
         */
        _onTaskListDoubleClick(e) {
            const row = e.target.closest('.rsl-gantt-task-row');
            if (!row) return;

            const taskId = row.dataset.taskId;
            const task = this.state.tasks.find(t => t.id === taskId);

            if (task && this.options.onTaskDoubleClick) {
                this.options.onTaskDoubleClick(task);
            }
        }

        /**
         * Handle bar click
         */
        _onBarClick(e) {
            const bar = e.target.closest('.rsl-gantt-bar');
            if (!bar) return;

            const taskId = bar.dataset.taskId;
            this._selectTask(taskId, e.ctrlKey || e.metaKey);

            const task = this.state.tasks.find(t => t.id === taskId);
            if (task && this.options.onTaskClick) {
                this.options.onTaskClick(task);
            }
        }

        /**
         * Handle bar double click
         */
        _onBarDoubleClick(e) {
            const bar = e.target.closest('.rsl-gantt-bar');
            if (!bar) return;

            const taskId = bar.dataset.taskId;
            const task = this.state.tasks.find(t => t.id === taskId);

            if (task && this.options.onTaskDoubleClick) {
                this.options.onTaskDoubleClick(task);
            }
        }

        /**
         * Handle bar mouse down (drag/resize start)
         */
        _onBarMouseDown(e) {
            if (!this.options.editable) return;

            const bar = e.target.closest('.rsl-gantt-bar');
            if (!bar) return;

            const handle = e.target.closest('.rsl-gantt-bar-handle');
            const taskId = bar.dataset.taskId;
            const task = this.state.tasks.find(t => t.id === taskId);

            if (!task || task.type !== 'task') return;

            if (handle && this.options.resizable) {
                // Start resize
                this.state.isResizing = true;
                this.state.resizeTask = task;
                this.state.resizeHandle = handle.classList.contains('left') ? 'left' : 'right';
                this.state.resizeStartX = e.clientX;
                this.state.resizeStartLeft = parseFloat(bar.style.left);
                this.state.resizeStartWidth = parseFloat(bar.style.width);
                bar.classList.add('selected');
            } else if (this.options.draggable) {
                // Start drag
                this.state.isDragging = true;
                this.state.dragTask = task;
                this.state.dragStartX = e.clientX;
                this.state.dragStartY = e.clientY;
                this.state.dragStartLeft = parseFloat(bar.style.left);
                this.state.dragStartTop = parseFloat(bar.style.top);
                bar.classList.add('dragging');
            }

            e.preventDefault();
        }

        /**
         * Handle bar context menu
         */
        _onBarContextMenu(e) {
            const bar = e.target.closest('.rsl-gantt-bar');
            if (!bar || !this.options.editable) return;

            e.preventDefault();

            const taskId = bar.dataset.taskId;
            this._selectTask(taskId);
            this._showContextMenu(e.clientX, e.clientY, taskId);
        }

        /**
         * Handle mouse move (drag/resize)
         */
        _onMouseMove(e) {
            if (this.state.isDragging) {
                this._onDrag(e);
            } else if (this.state.isResizing) {
                this._onResize(e);
            } else if (this.state.isTaskListResizing) {
                this._onTaskListResize(e);
            }
        }

        /**
         * Handle dragging
         */
        _onDrag(e) {
            const deltaX = e.clientX - this.state.dragStartX;
            const deltaY = e.clientY - this.state.dragStartY;

            const bar = this.elements.bars.querySelector(`[data-task-id="${this.state.dragTask.id}"]`);
            if (!bar) return;

            // Horizontal movement (date change)
            const newLeft = Math.max(0, this.state.dragStartLeft + deltaX);
            bar.style.left = `${newLeft}px`;

            // Vertical movement (row change) - snap to rows
            const newRow = Math.round((this.state.dragStartTop + deltaY) / this.options.rowHeight);
            const maxRow = this._getVisibleTasks().length - 1;
            const clampedRow = Math.max(0, Math.min(newRow, maxRow));
            bar.style.top = `${clampedRow * this.options.rowHeight + (this.options.rowHeight - 24) / 2}px`;
        }

        /**
         * Handle resizing
         */
        _onResize(e) {
            const deltaX = e.clientX - this.state.resizeStartX;
            const bar = this.elements.bars.querySelector(`[data-task-id="${this.state.resizeTask.id}"]`);
            if (!bar) return;

            if (this.state.resizeHandle === 'left') {
                const newLeft = Math.max(0, this.state.resizeStartLeft + deltaX);
                const newWidth = Math.max(24, this.state.resizeStartWidth - deltaX);
                bar.style.left = `${newLeft}px`;
                bar.style.width = `${newWidth}px`;
            } else {
                const newWidth = Math.max(24, this.state.resizeStartWidth + deltaX);
                bar.style.width = `${newWidth}px`;
            }
        }

        /**
         * Handle mouse up (end drag/resize)
         */
        _onMouseUp(e) {
            if (this.state.isDragging) {
                this._endDrag(e);
            } else if (this.state.isResizing) {
                this._endResize(e);
            } else if (this.state.isTaskListResizing) {
                this._endTaskListResize();
            }
        }

        /**
         * End drag operation
         */
        _endDrag(e) {
            const task = this.state.dragTask;
            const bar = this.elements.bars.querySelector(`[data-task-id="${task.id}"]`);

            if (bar) {
                bar.classList.remove('dragging');

                // Calculate new dates
                const left = parseFloat(bar.style.left);
                const { start, end } = this.state.dateRange;
                const totalMs = end - start;
                const position = left / this.state.totalWidth;

                const newStartMs = start.getTime() + (position * totalMs);
                const duration = task.end - task.start;

                task.start = new Date(newStartMs);
                task.end = new Date(newStartMs + duration);

                // Calculate new row (for reordering)
                const top = parseFloat(bar.style.top);
                const newRow = Math.round((top - (this.options.rowHeight - 24) / 2) / this.options.rowHeight);
                const visibleTasks = this._getVisibleTasks();
                const currentIndex = visibleTasks.findIndex(t => t.id === task.id);

                if (newRow !== currentIndex && newRow >= 0 && newRow < visibleTasks.length) {
                    // Reorder tasks
                    const taskIndex = this.state.tasks.findIndex(t => t.id === task.id);
                    this.state.tasks.splice(taskIndex, 1);

                    const targetTask = visibleTasks[newRow];
                    const targetIndex = this.state.tasks.findIndex(t => t.id === targetTask.id);
                    this.state.tasks.splice(targetIndex, 0, task);
                }

                // Re-render
                this._render();

                // Callback
                if (this.options.onTaskUpdate) {
                    this.options.onTaskUpdate(task);
                }

                this._dispatchEvent('taskUpdate', { task });
            }

            this.state.isDragging = false;
            this.state.dragTask = null;
        }

        /**
         * End resize operation
         */
        _endResize(e) {
            const task = this.state.resizeTask;
            const bar = this.elements.bars.querySelector(`[data-task-id="${task.id}"]`);

            if (bar) {
                const left = parseFloat(bar.style.left);
                const width = parseFloat(bar.style.width);
                const { start, end } = this.state.dateRange;
                const totalMs = end - start;

                const startPosition = left / this.state.totalWidth;
                const endPosition = (left + width) / this.state.totalWidth;

                task.start = new Date(start.getTime() + (startPosition * totalMs));
                task.end = new Date(start.getTime() + (endPosition * totalMs));

                // Re-render
                this._render();

                // Callback
                if (this.options.onTaskUpdate) {
                    this.options.onTaskUpdate(task);
                }

                this._dispatchEvent('taskUpdate', { task });
            }

            this.state.isResizing = false;
            this.state.resizeTask = null;
            this.state.resizeHandle = null;
        }

        /**
         * Handle task list resize start
         */
        _onTaskListResizeStart(e) {
            this.state.isTaskListResizing = true;
            this.state.taskListResizeStartX = e.clientX;
            this.state.taskListResizeStartWidth = this.elements.taskList.offsetWidth;
            e.preventDefault();
        }

        /**
         * Handle task list resizing
         */
        _onTaskListResize(e) {
            const deltaX = e.clientX - this.state.taskListResizeStartX;
            const newWidth = Math.max(150, Math.min(this.state.taskListResizeStartWidth + deltaX, this.container.offsetWidth / 2));
            this.elements.taskList.style.width = `${newWidth}px`;
        }

        /**
         * End task list resize
         */
        _endTaskListResize() {
            this.state.isTaskListResizing = false;
        }

        /**
         * Handle search
         */
        _onSearch(query) {
            const normalizedQuery = query.toLowerCase().trim();

            this.state.tasks.forEach(task => {
                task._hidden = normalizedQuery && !task.name.toLowerCase().includes(normalizedQuery);
            });

            this._render();
        }

        /**
         * Handle keyboard navigation
         */
        _onKeyDown(e) {
            const selectedIds = Array.from(this.state.selectedTaskIds);
            if (selectedIds.length === 0) return;

            const visibleTasks = this._getVisibleTasks();
            const currentIndex = visibleTasks.findIndex(t => t.id === selectedIds[0]);

            switch (e.key) {
                case 'ArrowUp':
                    e.preventDefault();
                    if (currentIndex > 0) {
                        this._selectTask(visibleTasks[currentIndex - 1].id);
                    }
                    break;
                case 'ArrowDown':
                    e.preventDefault();
                    if (currentIndex < visibleTasks.length - 1) {
                        this._selectTask(visibleTasks[currentIndex + 1].id);
                    }
                    break;
                case 'Delete':
                case 'Backspace':
                    if (this.options.editable) {
                        e.preventDefault();
                        selectedIds.forEach(id => this.deleteTask(id));
                    }
                    break;
                case 'Enter':
                case ' ':
                    e.preventDefault();
                    const task = this.state.tasks.find(t => t.id === selectedIds[0]);
                    if (task && this.options.onTaskDoubleClick) {
                        this.options.onTaskDoubleClick(task);
                    }
                    break;
                case 'Escape':
                    this._clearSelection();
                    break;
            }
        }

        /**
         * Handle bar mouse over (tooltip)
         */
        _onBarMouseOver(e) {
            const bar = e.target.closest('.rsl-gantt-bar');
            if (!bar) return;

            const taskId = bar.dataset.taskId;
            const task = this.state.tasks.find(t => t.id === taskId);
            if (!task) return;

            this._showTooltip(task, bar);
        }

        /**
         * Show tooltip
         */
        _showTooltip(task, bar) {
            const tooltip = this.elements.tooltip;

            let html = `<div class="rsl-gantt-tooltip-title">${task.name}</div>`;

            if (task.type !== 'milestone') {
                html += `
                    <div class="rsl-gantt-tooltip-row">
                        <span class="rsl-gantt-tooltip-label">Start:</span>
                        <span class="rsl-gantt-tooltip-value">${this._formatDate(task.start, 'medium')}</span>
                    </div>
                    <div class="rsl-gantt-tooltip-row">
                        <span class="rsl-gantt-tooltip-label">End:</span>
                        <span class="rsl-gantt-tooltip-value">${this._formatDate(task.end, 'medium')}</span>
                    </div>
                `;

                if (this.options.showProgress) {
                    html += `
                        <div class="rsl-gantt-tooltip-row">
                            <span class="rsl-gantt-tooltip-label">Progress:</span>
                            <span class="rsl-gantt-tooltip-value">${task.progress}%</span>
                        </div>
                    `;
                }
            } else {
                html += `
                    <div class="rsl-gantt-tooltip-row">
                        <span class="rsl-gantt-tooltip-label">Date:</span>
                        <span class="rsl-gantt-tooltip-value">${this._formatDate(task.start, 'medium')}</span>
                    </div>
                `;
            }

            if (task.assignee) {
                html += `
                    <div class="rsl-gantt-tooltip-row">
                        <span class="rsl-gantt-tooltip-label">Assignee:</span>
                        <span class="rsl-gantt-tooltip-value">${task.assignee}</span>
                    </div>
                `;
            }

            tooltip.innerHTML = html;

            // Position tooltip using viewport coordinates (tooltip is in document.body)
            const barRect = bar.getBoundingClientRect();

            tooltip.style.left = `${barRect.left + barRect.width / 2 + window.scrollX}px`;
            tooltip.style.top = `${barRect.top - 10 + window.scrollY}px`;
            tooltip.style.transform = 'translate(-50%, -100%)';

            tooltip.classList.add('visible');
        }

        /**
         * Hide tooltip
         */
        _hideTooltip() {
            this.elements.tooltip.classList.remove('visible');
        }

        /**
         * Toggle mobile task list visibility
         */
        _toggleMobileTaskList(forceState) {
            const taskList = this.elements.taskList;
            const overlay = this.elements.mobileOverlay;
            const toggle = this.elements.mobileToggle;

            if (!taskList) return;

            const isVisible = taskList.classList.contains('mobile-visible');
            const shouldShow = forceState !== undefined ? forceState : !isVisible;

            if (shouldShow) {
                taskList.classList.add('mobile-visible');
                overlay.classList.add('visible');
                toggle.classList.add('active');
                toggle.innerHTML = '<i class="fas fa-times" aria-hidden="true"></i>';
                toggle.setAttribute('aria-expanded', 'true');
                toggle.setAttribute('aria-label', 'Hide task list panel');
            } else {
                taskList.classList.remove('mobile-visible');
                overlay.classList.remove('visible');
                toggle.classList.remove('active');
                toggle.innerHTML = '<i class="fas fa-bars" aria-hidden="true"></i>';
                toggle.setAttribute('aria-expanded', 'false');
                toggle.setAttribute('aria-label', 'Show task list panel');
            }
        }

        /**
         * Show context menu
         */
        _showContextMenu(x, y, taskId) {
            const menu = this.elements.contextMenu;
            menu.dataset.taskId = taskId;
            menu.style.left = `${x}px`;
            menu.style.top = `${y}px`;
            menu.style.display = 'block';
        }

        /**
         * Hide context menu
         */
        _hideContextMenu() {
            this.elements.contextMenu.style.display = 'none';
        }

        /**
         * Handle context menu click
         */
        _onContextMenuClick(e) {
            const item = e.target.closest('.rsl-gantt-context-menu-item');
            if (!item) return;

            const action = item.dataset.action;
            const taskId = this.elements.contextMenu.dataset.taskId;

            switch (action) {
                case 'edit':
                    const task = this.state.tasks.find(t => t.id === taskId);
                    if (task && this.options.onTaskDoubleClick) {
                        this.options.onTaskDoubleClick(task);
                    }
                    break;
                case 'delete':
                    this.deleteTask(taskId);
                    break;
                case 'duplicate':
                    this.duplicateTask(taskId);
                    break;
                case 'move-up':
                    this._moveTask(taskId, -1);
                    break;
                case 'move-down':
                    this._moveTask(taskId, 1);
                    break;
            }

            this._hideContextMenu();
        }

        /**
         * Handle window resize
         */
        _onWindowResize() {
            clearTimeout(this._resizeTimeout);
            this._resizeTimeout = setTimeout(() => {
                this._render();
            }, 100);
        }

        /**
         * Select a task
         */
        _selectTask(taskId, multi = false) {
            if (!multi) {
                this.state.selectedTaskIds.clear();
            }

            if (this.state.selectedTaskIds.has(taskId)) {
                this.state.selectedTaskIds.delete(taskId);
            } else {
                this.state.selectedTaskIds.add(taskId);
            }

            this._updateSelection();

            if (this.options.onSelectionChange) {
                const selectedTasks = this.state.tasks.filter(t => this.state.selectedTaskIds.has(t.id));
                this.options.onSelectionChange(selectedTasks);
            }
        }

        /**
         * Clear selection
         */
        _clearSelection() {
            this.state.selectedTaskIds.clear();
            this._updateSelection();
        }

        /**
         * Update selection UI
         */
        _updateSelection() {
            // Update task list rows
            if (this.elements.taskListBody) {
                this.elements.taskListBody.querySelectorAll('.rsl-gantt-task-row').forEach(row => {
                    row.classList.toggle('selected', this.state.selectedTaskIds.has(row.dataset.taskId));
                });
            }

            // Update bars
            if (this.elements.bars) {
                this.elements.bars.querySelectorAll('.rsl-gantt-bar').forEach(bar => {
                    bar.classList.toggle('selected', this.state.selectedTaskIds.has(bar.dataset.taskId));
                });
            }
        }

        /**
         * Toggle group expand/collapse
         */
        _toggleGroup(taskId) {
            if (this.state.expandedGroups.has(taskId)) {
                this.state.expandedGroups.delete(taskId);
            } else {
                this.state.expandedGroups.add(taskId);
            }
            this._render();
        }

        /**
         * Move task up or down
         */
        _moveTask(taskId, direction) {
            const index = this.state.tasks.findIndex(t => t.id === taskId);
            if (index === -1) return;

            const newIndex = index + direction;
            if (newIndex < 0 || newIndex >= this.state.tasks.length) return;

            const task = this.state.tasks.splice(index, 1)[0];
            this.state.tasks.splice(newIndex, 0, task);

            this._render();
        }

        /**
         * Show export modal
         */
        _showExportModal() {
            // Create modal if not exists
            if (!this.elements.exportModal) {
                this.elements.exportModal = document.createElement('div');
                this.elements.exportModal.className = 'rsl-gantt-export-modal';
                this.elements.exportModal.innerHTML = `
                    <div class="rsl-gantt-export-modal-content">
                        <h3 class="rsl-gantt-export-modal-title">Export Chart</h3>
                        <div class="rsl-gantt-export-options">
                            <div class="rsl-gantt-export-option" data-format="png">
                                <i class="fas fa-image"></i>
                                <div>
                                    <div class="rsl-gantt-export-option-label">PNG Image</div>
                                    <div class="rsl-gantt-export-option-desc">High-quality image for presentations</div>
                                </div>
                            </div>
                            <div class="rsl-gantt-export-option" data-format="csv">
                                <i class="fas fa-file-csv"></i>
                                <div>
                                    <div class="rsl-gantt-export-option-label">CSV File</div>
                                    <div class="rsl-gantt-export-option-desc">Spreadsheet-compatible data</div>
                                </div>
                            </div>
                            <div class="rsl-gantt-export-option" data-format="json">
                                <i class="fas fa-code"></i>
                                <div>
                                    <div class="rsl-gantt-export-option-label">JSON Data</div>
                                    <div class="rsl-gantt-export-option-desc">Raw data for developers</div>
                                </div>
                            </div>
                        </div>
                        <div class="rsl-gantt-export-modal-actions">
                            <button class="rsl-gantt-btn" data-action="cancel">Cancel</button>
                            <button class="rsl-gantt-btn active" data-action="export">Export</button>
                        </div>
                    </div>
                `;
                document.body.appendChild(this.elements.exportModal);

                // Add event listeners
                let selectedFormat = 'png';
                this.elements.exportModal.querySelectorAll('.rsl-gantt-export-option').forEach(opt => {
                    opt.addEventListener('click', () => {
                        this.elements.exportModal.querySelectorAll('.rsl-gantt-export-option').forEach(o => o.classList.remove('selected'));
                        opt.classList.add('selected');
                        selectedFormat = opt.dataset.format;
                    });
                });

                this.elements.exportModal.querySelector('[data-action="cancel"]').addEventListener('click', () => {
                    this.elements.exportModal.classList.remove('visible');
                });

                this.elements.exportModal.querySelector('[data-action="export"]').addEventListener('click', () => {
                    this._exportChart(selectedFormat);
                    this.elements.exportModal.classList.remove('visible');
                });

                // Select first option
                this.elements.exportModal.querySelector('.rsl-gantt-export-option').classList.add('selected');
            }

            this.elements.exportModal.classList.add('visible');
        }

        /**
         * Export chart
         */
        _exportChart(format) {
            switch (format) {
                case 'png':
                    this._exportToPNG();
                    break;
                case 'csv':
                    this._exportToCSV();
                    break;
                case 'json':
                    this._exportToJSON();
                    break;
            }
        }

        /**
         * Export to PNG
         */
        _exportToPNG() {
            // Use html2canvas if available, otherwise alert
            if (typeof html2canvas === 'function') {
                html2canvas(this.container).then(canvas => {
                    const link = document.createElement('a');
                    link.download = `${this.options.exportFilename}.png`;
                    link.href = canvas.toDataURL('image/png');
                    link.click();
                });
            } else {
                alert('PNG export requires html2canvas library. Include it in your page for PNG export support.');
            }
        }

        /**
         * Export to CSV
         */
        _exportToCSV() {
            const headers = ['ID', 'Name', 'Type', 'Start Date', 'End Date', 'Progress', 'Dependencies', 'Assignee'];
            const rows = this.state.tasks.map(task => [
                task.id,
                `"${task.name.replace(/"/g, '""')}"`,
                task.type,
                this._formatDate(task.start, 'iso'),
                this._formatDate(task.end, 'iso'),
                task.progress,
                task.depends.join(';'),
                task.assignee || ''
            ]);

            const csv = [headers.join(','), ...rows.map(r => r.join(','))].join('\n');
            this._downloadFile(csv, `${this.options.exportFilename}.csv`, 'text/csv');
        }

        /**
         * Export to JSON
         */
        _exportToJSON() {
            const data = {
                version: '1.0',
                exportDate: new Date().toISOString(),
                tasks: this.state.tasks.map(task => ({
                    id: task.id,
                    name: task.name,
                    type: task.type,
                    start: this._formatDate(task.start, 'iso'),
                    end: this._formatDate(task.end, 'iso'),
                    progress: task.progress,
                    depends: task.depends,
                    parentId: task.parentId,
                    color: task.color,
                    assignee: task.assignee
                }))
            };

            this._downloadFile(JSON.stringify(data, null, 2), `${this.options.exportFilename}.json`, 'application/json');
        }

        /**
         * Download file
         */
        _downloadFile(content, filename, mimeType) {
            const blob = new Blob([content], { type: mimeType });
            const url = URL.createObjectURL(blob);
            const link = document.createElement('a');
            link.href = url;
            link.download = filename;
            link.click();
            URL.revokeObjectURL(url);
        }

        /**
         * Dispatch custom event
         */
        _dispatchEvent(name, detail) {
            this.container.dispatchEvent(new CustomEvent(`rsl-gantt:${name}`, {
                bubbles: true,
                detail
            }));
        }

        // ==========================================
        // Public API Methods
        // ==========================================

        /**
         * Set zoom level
         */
        setZoom(zoom) {
            if (!['day', 'week', 'month', 'quarter', 'year'].includes(zoom)) return;

            this.state.zoom = zoom;

            // Update toolbar buttons
            if (this.elements.toolbar) {
                this.elements.toolbar.querySelectorAll('[data-zoom]').forEach(btn => {
                    const isActive = btn.dataset.zoom === zoom;
                    btn.classList.toggle('active', isActive);
                    btn.setAttribute('aria-pressed', isActive ? 'true' : 'false');
                });
            }

            this._calculateDateRange();
            this._render();

            if (this.options.onZoomChange) {
                this.options.onZoomChange(zoom);
            }

            this._dispatchEvent('zoomChange', { zoom });
        }

        /**
         * Get current zoom level
         */
        getZoom() {
            return this.state.zoom;
        }

        /**
         * Scroll to today
         */
        scrollToToday() {
            const today = new Date();
            today.setHours(0, 0, 0, 0);

            const { start, end } = this.state.dateRange;

            // If today is outside the date range, extend the range and re-render
            if (today < start || today > end) {
                // Extend date range to include today with padding
                const padding = 7 * 24 * 60 * 60 * 1000; // 7 days in ms
                if (today < start) {
                    this.state.dateRange.start = new Date(today.getTime() - padding);
                } else {
                    this.state.dateRange.end = new Date(today.getTime() + padding);
                }

                // Recalculate dimensions and re-render
                this._calculateDimensions();
                this._render();
            }

            // Now scroll to today
            const position = ((today - this.state.dateRange.start) / (this.state.dateRange.end - this.state.dateRange.start)) * this.state.totalWidth;
            const containerWidth = this.elements.timelineBody.offsetWidth;

            this.elements.timelineBody.scrollLeft = position - containerWidth / 2;
        }

        /**
         * Scroll to task
         */
        scrollToTask(taskId) {
            const visibleTasks = this._getVisibleTasks();
            const index = visibleTasks.findIndex(t => t.id === taskId);
            if (index === -1) return;

            const task = visibleTasks[index];

            // Scroll vertically
            this.elements.timelineBody.scrollTop = index * this.options.rowHeight;

            // Scroll horizontally to task start
            if (task.start) {
                const { start, end } = this.state.dateRange;
                const position = ((task.start - start) / (end - start)) * this.state.totalWidth;
                this.elements.timelineBody.scrollLeft = position - 100;
            }

            this._selectTask(taskId);
        }

        /**
         * Add a new task
         */
        addTask(taskData) {
            const task = this._normalizeTasks([taskData])[0];
            this.state.tasks.push(task);

            this._calculateDateRange();
            this._render();

            if (this.options.onTaskCreate) {
                this.options.onTaskCreate(task);
            }

            this._dispatchEvent('taskCreate', { task });

            return task;
        }

        /**
         * Update a task
         */
        updateTask(taskId, updates) {
            const task = this.state.tasks.find(t => t.id === taskId);
            if (!task) return null;

            Object.assign(task, updates);

            if (updates.start) task.start = this._parseDate(updates.start);
            if (updates.end) task.end = this._parseDate(updates.end);

            this._calculateDateRange();
            this._render();

            if (this.options.onTaskUpdate) {
                this.options.onTaskUpdate(task);
            }

            this._dispatchEvent('taskUpdate', { task });

            return task;
        }

        /**
         * Delete a task
         */
        deleteTask(taskId) {
            const index = this.state.tasks.findIndex(t => t.id === taskId);
            if (index === -1) return false;

            const task = this.state.tasks[index];
            this.state.tasks.splice(index, 1);
            this.state.selectedTaskIds.delete(taskId);

            // Remove from dependencies
            this.state.tasks.forEach(t => {
                t.depends = t.depends.filter(id => id !== taskId);
            });

            this._render();

            if (this.options.onTaskDelete) {
                this.options.onTaskDelete(task);
            }

            this._dispatchEvent('taskDelete', { task });

            return true;
        }

        /**
         * Duplicate a task
         */
        duplicateTask(taskId) {
            const task = this.state.tasks.find(t => t.id === taskId);
            if (!task) return null;

            const newTask = {
                ...task,
                id: `${task.id}-copy-${Date.now()}`,
                name: `${task.name} (Copy)`,
                depends: []
            };

            return this.addTask(newTask);
        }

        /**
         * Get all tasks
         */
        getTasks() {
            return [...this.state.tasks];
        }

        /**
         * Get task by ID
         */
        getTask(taskId) {
            return this.state.tasks.find(t => t.id === taskId);
        }

        /**
         * Get selected tasks
         */
        getSelectedTasks() {
            return this.state.tasks.filter(t => this.state.selectedTaskIds.has(t.id));
        }

        /**
         * Select tasks
         */
        selectTasks(taskIds) {
            this.state.selectedTaskIds = new Set(taskIds);
            this._updateSelection();
        }

        /**
         * Clear selection
         */
        clearSelection() {
            this._clearSelection();
        }

        /**
         * Expand all groups
         */
        expandAll() {
            this.state.tasks.forEach(task => {
                if (task.type === 'group') {
                    this.state.expandedGroups.add(task.id);
                }
            });
            this._render();
        }

        /**
         * Collapse all groups
         */
        collapseAll() {
            this.state.expandedGroups.clear();
            this._render();
        }

        /**
         * Set date range
         */
        setDateRange(startDate, endDate) {
            this.state.dateRange = {
                start: this._parseDate(startDate),
                end: this._parseDate(endDate)
            };
            this._render();
        }

        /**
         * Refresh the chart
         */
        refresh() {
            this._calculateDateRange();
            this._render();
        }

        /**
         * Destroy the instance
         */
        destroy() {
            // Remove event listeners
            document.removeEventListener('mousemove', this._onMouseMove);
            document.removeEventListener('mouseup', this._onMouseUp);
            window.removeEventListener('resize', this._onWindowResize);

            // Remove DOM elements appended to body
            if (this.elements.tooltip) {
                this.elements.tooltip.remove();
            }
            if (this.elements.contextMenu) {
                this.elements.contextMenu.remove();
            }
            if (this.elements.exportModal) {
                this.elements.exportModal.remove();
            }

            // Clear container
            this.container.innerHTML = '';
            this.container.classList.remove('rsl-gantt');
            this.container.removeAttribute('data-rsl-gantt-initialized');

            // Remove from instances
            GanttChart.instances.delete(this.container);
        }
    }

    // Static instances map
    GanttChart.instances = new Map();

    // ==========================================
    // Public API
    // ==========================================

    window.RSL.Gantt = {
        /**
         * Create a new Gantt chart
         */
        create: function(element, options) {
            const el = typeof element === 'string' ? document.querySelector(element) : element;
            if (!el) return null;

            // Return existing instance if already initialized
            if (GanttChart.instances.has(el)) {
                return GanttChart.instances.get(el);
            }

            const instance = new GanttChart(el, options);
            GanttChart.instances.set(el, instance);
            return instance;
        },

        /**
         * Get existing instance
         */
        getInstance: function(element) {
            const el = typeof element === 'string' ? document.querySelector(element) : element;
            return el ? GanttChart.instances.get(el) : null;
        },

        /**
         * Initialize all Gantt charts on page
         */
        init: function() {
            document.querySelectorAll('[data-rsl-gantt]:not([data-rsl-gantt-initialized])').forEach(el => {
                this.create(el);
            });
        },

        /**
         * Destroy instance
         */
        destroy: function(element) {
            const instance = this.getInstance(element);
            if (instance) {
                instance.destroy();
            }
        }
    };

    // Auto-initialize on DOMContentLoaded
    document.addEventListener('DOMContentLoaded', function() {
        window.RSL.Gantt.init();
    });

})();
