/**
 * Real-time Date Filtering with Chart Updates
 * Provides interactive date range selection with live chart updates
 */

class DateFilterCharts {
    constructor(options = {}) {
        this.options = {
            dateFormat: 'YYYY-MM-DD',
            apiEndpoint: '/api/reports/filtered-data/',
            chartContainers: {},
            predefinedRanges: {
                'today': { days: 0, label: 'Today' },
                'week': { days: 7, label: 'This Week' },
                'month': { days: 30, label: 'This Month' },
                'quarter': { days: 90, label: 'This Quarter' },
                'year': { days: 365, label: 'This Year' }
            },
            ...options
        };
        
        this.currentDateRange = {
            start: null,
            end: null
        };
        
        this.charts = {};
        this.isLoading = false;
        
        this.init();
    }
    
    init() {
        this.createDateRangePicker();
        this.createPredefinedButtons();
        this.bindEvents();
        this.setDefaultDateRange();
    }
    
    createDateRangePicker() {
        const dateFilterContainer = document.getElementById('date-filter-container');
        if (!dateFilterContainer) {
            console.error('Date filter container not found');
            return;
        }
        
        const datePickerHTML = `
            <div class="date-filter-widget">
                <div class="row">
                    <div class="col-md-3">
                        <label for="start-date" class="form-label">From Date</label>
                        <input type="date" id="start-date" class="form-control" />
                    </div>
                    <div class="col-md-3">
                        <label for="end-date" class="form-label">To Date</label>
                        <input type="date" id="end-date" class="form-control" />
                    </div>
                    <div class="col-md-4">
                        <label class="form-label">Quick Ranges</label>
                        <div class="btn-group" role="group" id="predefined-ranges">
                            <!-- Predefined buttons will be inserted here -->
                        </div>
                    </div>
                    <div class="col-md-2">
                        <label class="form-label">&nbsp;</label>
                        <div>
                            <button type="button" id="apply-filter" class="btn btn-primary">
                                <i class="fas fa-filter"></i> Apply
                            </button>
                            <button type="button" id="reset-filter" class="btn btn-outline-secondary">
                                <i class="fas fa-undo"></i> Reset
                            </button>
                        </div>
                    </div>
                </div>
                <div class="row mt-2">
                    <div class="col-12">
                        <div id="date-comparison" class="form-check">
                            <input class="form-check-input" type="checkbox" id="enable-comparison">
                            <label class="form-check-label" for="enable-comparison">
                                Compare with previous period
                            </label>
                        </div>
                    </div>
                </div>
            </div>
        `;
        
        dateFilterContainer.innerHTML = datePickerHTML;
    }
    
    createPredefinedButtons() {
        const container = document.getElementById('predefined-ranges');
        if (!container) return;
        
        Object.entries(this.options.predefinedRanges).forEach(([key, range]) => {
            const button = document.createElement('button');
            button.type = 'button';
            button.className = 'btn btn-outline-primary btn-sm';
            button.dataset.range = key;
            button.textContent = range.label;
            container.appendChild(button);
        });
    }
    
    bindEvents() {
        // Date input changes
        document.getElementById('start-date')?.addEventListener('change', () => {
            this.updateDateRange();
        });
        
        document.getElementById('end-date')?.addEventListener('change', () => {
            this.updateDateRange();
        });
        
        // Apply filter button
        document.getElementById('apply-filter')?.addEventListener('click', () => {
            this.applyFilter();
        });
        
        // Reset filter button
        document.getElementById('reset-filter')?.addEventListener('click', () => {
            this.resetFilter();
        });
        
        // Predefined range buttons
        document.getElementById('predefined-ranges')?.addEventListener('click', (e) => {
            if (e.target.dataset.range) {
                this.setPredefinedRange(e.target.dataset.range);
            }
        });
        
        // Comparison checkbox
        document.getElementById('enable-comparison')?.addEventListener('change', (e) => {
            this.toggleComparison(e.target.checked);
        });
    }
    
    setDefaultDateRange() {
        const today = new Date();
        const thirtyDaysAgo = new Date(today.getTime() - (30 * 24 * 60 * 60 * 1000));
        
        this.setDateRange(thirtyDaysAgo, today);
    }
    
    setDateRange(startDate, endDate) {
        const startInput = document.getElementById('start-date');
        const endInput = document.getElementById('end-date');
        
        if (startInput) startInput.value = this.formatDate(startDate);
        if (endInput) endInput.value = this.formatDate(endDate);
        
        this.currentDateRange = {
            start: startDate,
            end: endDate
        };
    }
    
    setPredefinedRange(rangeKey) {
        const range = this.options.predefinedRanges[rangeKey];
        if (!range) return;
        
        const endDate = new Date();
        const startDate = new Date();
        
        if (rangeKey === 'today') {
            startDate.setHours(0, 0, 0, 0);
            endDate.setHours(23, 59, 59, 999);
        } else {
            startDate.setDate(startDate.getDate() - range.days);
        }
        
        this.setDateRange(startDate, endDate);
        this.applyFilter();
        
        // Update button states
        document.querySelectorAll('#predefined-ranges button').forEach(btn => {
            btn.classList.remove('active');
        });
        document.querySelector(`[data-range="${rangeKey}"]`)?.classList.add('active');
    }
    
    updateDateRange() {
        const startInput = document.getElementById('start-date');
        const endInput = document.getElementById('end-date');
        
        if (startInput?.value && endInput?.value) {
            this.currentDateRange = {
                start: new Date(startInput.value),
                end: new Date(endInput.value)
            };
        }
    }
    
    async applyFilter() {
        if (this.isLoading) return;
        
        this.showLoading(true);
        
        try {
            const filteredData = await this.fetchFilteredData();
            await this.updateAllCharts(filteredData);
            this.updateSummaryCards(filteredData.summary);
        } catch (error) {
            console.error('Error applying filter:', error);
            this.showError('Failed to update charts. Please try again.');
        } finally {
            this.showLoading(false);
        }
    }
    
    async fetchFilteredData() {
        const params = new URLSearchParams({
            start_date: this.formatDate(this.currentDateRange.start),
            end_date: this.formatDate(this.currentDateRange.end),
            report_type: this.getCurrentReportType(),
            include_comparison: document.getElementById('enable-comparison')?.checked || false
        });
        
        const response = await fetch(`${this.options.apiEndpoint}?${params}`);
        
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }
        
        return await response.json();
    }
    
    async updateAllCharts(data) {
        const chartPromises = [];
        
        // Update each chart type based on current report
        Object.entries(this.options.chartContainers).forEach(([chartId, config]) => {
            const chartData = data.charts?.[chartId];
            if (chartData) {
                chartPromises.push(this.updateChart(chartId, chartData, config));
            }
        });
        
        await Promise.all(chartPromises);
    }
    
    async updateChart(chartId, chartData, config) {
        const container = document.getElementById(chartId);
        if (!container) return;
        
        // Show loading state for individual chart
        container.innerHTML = '<div class="text-center p-4"><i class="fas fa-spinner fa-spin"></i> Updating chart...</div>';
        
        try {
            if (config.type === 'chartjs') {
                await this.updateChartJSChart(chartId, chartData, config);
            } else if (config.type === 'plotly') {
                await this.updatePlotlyChart(chartId, chartData, config);
            }
        } catch (error) {
            console.error(`Error updating chart ${chartId}:`, error);
            container.innerHTML = '<div class="alert alert-warning">Failed to update chart</div>';
        }
    }
    
    async updateChartJSChart(chartId, chartData, config) {
        const canvas = document.getElementById(chartId + '-canvas') || this.createCanvas(chartId);
        const ctx = canvas.getContext('2d');
        
        // Destroy existing chart if it exists
        if (this.charts[chartId]) {
            this.charts[chartId].destroy();
        }
        
        // Create new chart with updated data
        this.charts[chartId] = new Chart(ctx, {
            type: config.chartType || 'bar',
            data: {
                labels: chartData.labels || [],
                datasets: chartData.datasets || []
            },
            options: {
                responsive: true,
                maintainAspectRatio: false,
                plugins: {
                    title: {
                        display: true,
                        text: chartData.title || config.title || 'Chart'
                    },
                    legend: {
                        display: true,
                        position: 'top'
                    }
                },
                scales: config.scales || {},
                animation: {
                    duration: 750,
                    easing: 'easeInOutQuart'
                }
            }
        });
    }
    
    async updatePlotlyChart(chartId, chartData, config) {
        const container = document.getElementById(chartId);
        
        const plotlyData = chartData.traces || [];
        const layout = {
            title: chartData.title || config.title || 'Chart',
            responsive: true,
            ...chartData.layout
        };
        
        const plotConfig = {
            displayModeBar: true,
            displaylogo: false,
            modeBarButtonsToRemove: ['pan2d', 'lasso2d', 'select2d'],
            responsive: true
        };
        
        await Plotly.newPlot(container, plotlyData, layout, plotConfig);
    }
    
    createCanvas(chartId) {
        const container = document.getElementById(chartId);
        const canvas = document.createElement('canvas');
        canvas.id = chartId + '-canvas';
        canvas.style.maxHeight = '400px';
        container.innerHTML = '';
        container.appendChild(canvas);
        return canvas;
    }
    
    updateSummaryCards(summaryData) {
        if (!summaryData) return;
        
        Object.entries(summaryData).forEach(([key, value]) => {
            const element = document.getElementById(`summary-${key}`);
            if (element) {
                // Animate value change
                this.animateValue(element, value);
            }
        });
    }
    
    animateValue(element, newValue) {
        const currentValue = parseFloat(element.textContent.replace(/[^0-9.-]+/g, '')) || 0;
        const increment = (newValue - currentValue) / 20;
        let current = currentValue;
        
        const timer = setInterval(() => {
            current += increment;
            if ((increment > 0 && current >= newValue) || (increment < 0 && current <= newValue)) {
                current = newValue;
                clearInterval(timer);
            }
            
            element.textContent = this.formatValue(current);
        }, 50);
    }
    
    formatValue(value) {
        if (typeof value === 'number') {
            return new Intl.NumberFormat('en-KE', {
                style: 'currency',
                currency: 'KES',
                minimumFractionDigits: 0
            }).format(value);
        }
        return value;
    }
    
    toggleComparison(enabled) {
        // Update UI to show/hide comparison elements
        const comparisonElements = document.querySelectorAll('.comparison-data');
        comparisonElements.forEach(el => {
            el.style.display = enabled ? 'block' : 'none';
        });
        
        if (enabled) {
            this.applyFilter(); // Refresh with comparison data
        }
    }
    
    resetFilter() {
        this.setDefaultDateRange();
        document.getElementById('enable-comparison').checked = false;
        document.querySelectorAll('#predefined-ranges button').forEach(btn => {
            btn.classList.remove('active');
        });
        this.applyFilter();
    }
    
    showLoading(show) {
        this.isLoading = show;
        const applyButton = document.getElementById('apply-filter');
        const loadingOverlay = document.getElementById('loading-overlay');
        
        if (applyButton) {
            applyButton.disabled = show;
            applyButton.innerHTML = show ? 
                '<i class="fas fa-spinner fa-spin"></i> Updating...' : 
                '<i class="fas fa-filter"></i> Apply';
        }
        
        if (loadingOverlay) {
            loadingOverlay.style.display = show ? 'flex' : 'none';
        }
    }
    
    showError(message) {
        const errorContainer = document.getElementById('error-container');
        if (errorContainer) {
            errorContainer.innerHTML = `
                <div class="alert alert-danger alert-dismissible fade show" role="alert">
                    ${message}
                    <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
                </div>
            `;
        }
    }
    
    getCurrentReportType() {
        // Determine current report type from URL or page context
        const path = window.location.pathname;
        if (path.includes('loans-due')) return 'loans_due';
        if (path.includes('delinquent')) return 'delinquent_loans';
        if (path.includes('arrears')) return 'loans_in_arrears';
        if (path.includes('processing-fees')) return 'processing_fees';
        if (path.includes('interest-income')) return 'interest_income';
        if (path.includes('registration-fees')) return 'registration_fees';
        return 'dashboard';
    }
    
    formatDate(date) {
        if (!date) return '';
        return date.toISOString().split('T')[0];
    }
    
    // Public API methods
    setChartContainer(chartId, config) {
        this.options.chartContainers[chartId] = config;
    }
    
    refreshCharts() {
        this.applyFilter();
    }
    
    getDateRange() {
        return { ...this.currentDateRange };
    }
}

// Auto-initialize when DOM is ready
document.addEventListener('DOMContentLoaded', function() {
    // Check if we're on a reports page
    if (document.getElementById('date-filter-container')) {
        window.dateFilterCharts = new DateFilterCharts();
    }
});

// Export for module usage
if (typeof module !== 'undefined' && module.exports) {
    module.exports = DateFilterCharts;
}