/**
 * MYP Platform Advanced UI Components
 * Erweiterte Komponenten: Progress-Bars, File-Upload, Datepicker
 * Version: 2.0.0
 */

(function() {
    'use strict';
    
    // Namespace erweitern
    window.MYP = window.MYP || {};
    window.MYP.Advanced = window.MYP.Advanced || {};
    
    /**
     * Progress Bar Component
     */
    class ProgressBar {
        constructor(container, options = {}) {
            this.container = typeof container === 'string' ? document.querySelector(container) : container;
            this.options = {
                value: 0,
                max: 100,
                showLabel: true,
                showPercentage: true,
                animated: true,
                color: 'blue',
                size: 'md',
                striped: false,
                ...options
            };
            
            this.currentValue = this.options.value;
            this.init();
        }
        
        init() {
            if (!this.container) {
                console.error('ProgressBar: Container nicht gefunden');
                return;
            }
            
            this.render();
        }
        
        render() {
            const percentage = Math.round((this.currentValue / this.options.max) * 100);
            const sizeClass = this.getSizeClass();
            const colorClass = this.getColorClass();
            
            this.container.innerHTML = `
                <div class="progress-bar-container ${sizeClass}">
                    ${this.options.showLabel ? `
                        <div class="flex justify-between items-center mb-2">
                            <span class="text-sm font-medium text-slate-700 dark:text-slate-300">
                                ${this.options.label || 'Fortschritt'}
                            </span>
                            ${this.options.showPercentage ? `
                                <span class="text-sm font-medium text-slate-700 dark:text-slate-300">
                                    ${percentage}%
                                </span>
                            ` : ''}
                        </div>
                    ` : ''}
                    
                    <div class="progress-bar-track ${sizeClass}">
                        <div class="progress-bar-fill ${colorClass} ${this.options.animated ? 'animated' : ''} ${this.options.striped ? 'striped' : ''}" 
                             style="width: ${percentage}%" 
                             role="progressbar" 
                             aria-valuenow="${this.currentValue}" 
                             aria-valuemin="0" 
                             aria-valuemax="${this.options.max}">
                        </div>
                    </div>
                </div>
            `;
        }
        
        getSizeClass() {
            const sizes = {
                'sm': 'h-2',
                'md': 'h-3',
                'lg': 'h-4',
                'xl': 'h-6'
            };
            return sizes[this.options.size] || sizes.md;
        }
        
        getColorClass() {
            const colors = {
                'blue': 'bg-blue-500',
                'green': 'bg-green-500',
                'red': 'bg-red-500',
                'yellow': 'bg-yellow-500',
                'purple': 'bg-purple-500',
                'indigo': 'bg-indigo-500'
            };
            return colors[this.options.color] || colors.blue;
        }
        
        setValue(value, animate = true) {
            const oldValue = this.currentValue;
            this.currentValue = Math.max(0, Math.min(this.options.max, value));
            
            if (animate) {
                this.animateToValue(oldValue, this.currentValue);
            } else {
                this.render();
            }
        }
        
        animateToValue(from, to) {
            const duration = 500; // ms
            const steps = 60;
            const stepValue = (to - from) / steps;
            let currentStep = 0;
            
            const animate = () => {
                if (currentStep < steps) {
                    this.currentValue = from + (stepValue * currentStep);
                    this.render();
                    currentStep++;
                    requestAnimationFrame(animate);
                } else {
                    this.currentValue = to;
                    this.render();
                }
            };
            
            animate();
        }
        
        increment(amount = 1) {
            this.setValue(this.currentValue + amount);
        }
        
        decrement(amount = 1) {
            this.setValue(this.currentValue - amount);
        }
        
        reset() {
            this.setValue(0);
        }
        
        complete() {
            this.setValue(this.options.max);
        }
    }
    
    /**
     * Advanced File Upload Component
     */
    class FileUpload {
        constructor(container, options = {}) {
            this.container = typeof container === 'string' ? document.querySelector(container) : container;
            this.options = {
                multiple: false,
                accept: '*/*',
                maxSize: 50 * 1024 * 1024, // 50MB
                maxFiles: 10,
                dragDrop: true,
                showProgress: true,
                showPreview: true,
                uploadUrl: '/api/upload',
                chunkSize: 1024 * 1024, // 1MB chunks
                ...options
            };
            
            this.files = [];
            this.uploads = new Map();
            this.init();
        }
        
        init() {
            if (!this.container) {
                console.error('FileUpload: Container nicht gefunden');
                return;
            }
            
            this.render();
            this.setupEventListeners();
        }
        
        render() {
            this.container.innerHTML = `
                <div class="file-upload-area" id="fileUploadArea">
                    <div class="file-upload-dropzone ${this.options.dragDrop ? 'drag-enabled' : ''}" id="dropzone">
                        <div class="text-center py-12">
                            <svg class="mx-auto h-12 w-12 text-slate-400" stroke="currentColor" fill="none" viewBox="0 0 48 48">
                                <path d="M28 8H12a4 4 0 00-4 4v20m32-12v8m0 0v8a4 4 0 01-4 4H12a4 4 0 01-4-4v-4m32-4l-3.172-3.172a4 4 0 00-5.656 0L28 28M8 32l9.172-9.172a4 4 0 015.656 0L28 28m0 0l4 4m4-24h8m-4-4v8m-12 4h.02" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
                            </svg>
                            <div class="mt-4">
                                <label for="fileInput" class="cursor-pointer">
                                    <span class="mt-2 block text-sm font-medium text-slate-900 dark:text-white">
                                        ${this.options.dragDrop ? 'Dateien hierher ziehen oder' : ''} 
                                        <span class="text-blue-600 dark:text-blue-400 hover:text-blue-500">durchsuchen</span>
                                    </span>
                                </label>
                                <input type="file" 
                                       id="fileInput" 
                                       name="files" 
                                       ${this.options.multiple ? 'multiple' : ''} 
                                       accept="${this.options.accept}" 
                                       class="sr-only">
                            </div>
                            <p class="mt-1 text-xs text-slate-500 dark:text-slate-400">
                                ${this.getFileTypeText()} • Max. ${this.formatFileSize(this.options.maxSize)}
                            </p>
                        </div>
                    </div>
                    
                    <div class="file-list mt-4" id="fileList"></div>
                </div>
            `;
        }
        
        setupEventListeners() {
            const fileInput = this.container.querySelector('#fileInput');
            const dropzone = this.container.querySelector('#dropzone');
            
            // File Input Change
            fileInput.addEventListener('change', (e) => {
                this.handleFiles(Array.from(e.target.files));
            });
            
            if (this.options.dragDrop) {
                // Drag and Drop Events
                dropzone.addEventListener('dragover', (e) => {
                    e.preventDefault();
                    dropzone.classList.add('drag-over');
                });
                
                dropzone.addEventListener('dragleave', (e) => {
                    e.preventDefault();
                    dropzone.classList.remove('drag-over');
                });
                
                dropzone.addEventListener('drop', (e) => {
                    e.preventDefault();
                    dropzone.classList.remove('drag-over');
                    this.handleFiles(Array.from(e.dataTransfer.files));
                });
            }
        }
        
        handleFiles(fileList) {
            for (const file of fileList) {
                if (this.validateFile(file)) {
                    this.addFile(file);
                }
            }
            
            this.renderFileList();
        }
        
        validateFile(file) {
            // Dateigröße prüfen
            if (file.size > this.options.maxSize) {
                this.showError(`Datei "${file.name}" ist zu groß. Maximum: ${this.formatFileSize(this.options.maxSize)}`);
                return false;
            }
            
            // Anzahl Dateien prüfen
            if (!this.options.multiple && this.files.length > 0) {
                this.files = []; // Ersetze einzelne Datei
            } else if (this.files.length >= this.options.maxFiles) {
                this.showError(`Maximal ${this.options.maxFiles} Dateien erlaubt`);
                return false;
            }
            
            return true;
        }
        
        addFile(file) {
            const fileData = {
                id: this.generateId(),
                file: file,
                name: file.name,
                size: file.size,
                type: file.type,
                status: 'pending',
                progress: 0,
                error: null
            };
            
            this.files.push(fileData);
            
            // Preview generieren
            if (this.options.showPreview && file.type.startsWith('image/')) {
                this.generatePreview(fileData);
            }
        }
        
        generatePreview(fileData) {
            const reader = new FileReader();
            reader.onload = (e) => {
                fileData.preview = e.target.result;
                this.renderFileList();
            };
            reader.readAsDataURL(fileData.file);
        }
        
        renderFileList() {
            const fileListContainer = this.container.querySelector('#fileList');
            
            if (this.files.length === 0) {
                fileListContainer.innerHTML = '';
                return;
            }
            
            fileListContainer.innerHTML = this.files.map(fileData => `
                <div class="file-item" data-file-id="${fileData.id}">
                    <div class="flex items-center space-x-4 p-4 bg-slate-50 dark:bg-slate-800 rounded-lg">
                        ${fileData.preview ? `
                            <img src="${fileData.preview}" class="w-12 h-12 object-cover rounded" alt="Preview">
                        ` : `
                            <div class="w-12 h-12 bg-slate-200 dark:bg-slate-700 rounded flex items-center justify-center">
                                <svg class="w-6 h-6 text-slate-400" fill="currentColor" viewBox="0 0 20 20">
                                    <path fill-rule="evenodd" d="M4 4a2 2 0 012-2h4.586A2 2 0 0112 2.586L15.414 6A2 2 0 0116 7.414V16a2 2 0 01-2 2H6a2 2 0 01-2-2V4z" clip-rule="evenodd"/>
                                </svg>
                            </div>
                        `}
                        
                        <div class="flex-1 min-w-0">
                            <div class="flex items-center justify-between">
                                <p class="text-sm font-medium text-slate-900 dark:text-white truncate">
                                    ${fileData.name}
                                </p>
                                <button class="remove-file text-slate-400 hover:text-red-500" data-file-id="${fileData.id}">
                                    <svg class="w-4 h-4" fill="currentColor" viewBox="0 0 20 20">
                                        <path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"/>
                                    </svg>
                                </button>
                            </div>
                            <p class="text-xs text-slate-500 dark:text-slate-400">
                                ${this.formatFileSize(fileData.size)} • ${this.getStatusText(fileData.status)}
                            </p>
                            
                            ${this.options.showProgress && fileData.status === 'uploading' ? `
                                <div class="mt-2">
                                    <div class="w-full bg-slate-200 dark:bg-slate-600 rounded-full h-2">
                                        <div class="bg-blue-500 h-2 rounded-full transition-all duration-300" 
                                             style="width: ${fileData.progress}%"></div>
                                    </div>
                                </div>
                            ` : ''}
                            
                            ${fileData.error ? `
                                <p class="text-xs text-red-500 mt-1">${fileData.error}</p>
                            ` : ''}
                        </div>
                    </div>
                </div>
            `).join('');
            
            // Event Listeners für Remove-Buttons
            fileListContainer.querySelectorAll('.remove-file').forEach(button => {
                button.addEventListener('click', (e) => {
                    const fileId = e.target.closest('.remove-file').dataset.fileId;
                    this.removeFile(fileId);
                });
            });
        }
        
        removeFile(fileId) {
            this.files = this.files.filter(f => f.id !== fileId);
            this.renderFileList();
        }
        
        async uploadFiles() {
            const pendingFiles = this.files.filter(f => f.status === 'pending');
            
            for (const fileData of pendingFiles) {
                await this.uploadFile(fileData);
            }
        }
        
        async uploadFile(fileData) {
            fileData.status = 'uploading';
            fileData.progress = 0;
            this.renderFileList();
            
            try {
                const formData = new FormData();
                formData.append('file', fileData.file);
                
                const response = await fetch(this.options.uploadUrl, {
                    method: 'POST',
                    body: formData,
                    headers: {
                        'X-CSRFToken': document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || ''
                    }
                });
                
                if (response.ok) {
                    fileData.status = 'completed';
                    fileData.progress = 100;
                    const result = await response.json();
                    fileData.url = result.url;
                } else {
                    throw new Error(`Upload fehlgeschlagen: ${response.status}`);
                }
            } catch (error) {
                fileData.status = 'error';
                fileData.error = error.message;
            }
            
            this.renderFileList();
        }
        
        getFileTypeText() {
            if (this.options.accept === '*/*') return 'Alle Dateitypen';
            if (this.options.accept.includes('image/')) return 'Bilder';
            if (this.options.accept.includes('.pdf')) return 'PDF-Dateien';
            return 'Spezifische Dateitypen';
        }
        
        getStatusText(status) {
            const statusTexts = {
                'pending': 'Wartend',
                'uploading': 'Wird hochgeladen...',
                'completed': 'Abgeschlossen',
                'error': 'Fehler'
            };
            return statusTexts[status] || status;
        }
        
        formatFileSize(bytes) {
            if (bytes === 0) return '0 Bytes';
            const k = 1024;
            const sizes = ['Bytes', 'KB', 'MB', 'GB'];
            const i = Math.floor(Math.log(bytes) / Math.log(k));
            return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
        }
        
        generateId() {
            return 'file_' + Math.random().toString(36).substr(2, 9);
        }
        
        showError(message) {
            if (window.showToast) {
                window.showToast(message, 'error');
            } else {
                alert(message);
            }
        }
        
        getFiles() {
            return this.files;
        }
        
        getCompletedFiles() {
            return this.files.filter(f => f.status === 'completed');
        }
        
        clear() {
            this.files = [];
            this.renderFileList();
        }
    }
    
    /**
     * Simple Datepicker Component
     */
    class DatePicker {
        constructor(input, options = {}) {
            this.input = typeof input === 'string' ? document.querySelector(input) : input;
            this.options = {
                format: 'dd.mm.yyyy',
                minDate: null,
                maxDate: null,
                disabledDates: [],
                language: 'de',
                closeOnSelect: true,
                showWeekNumbers: false,
                ...options
            };
            
            this.isOpen = false;
            this.currentDate = new Date();
            this.selectedDate = null;
            this.init();
        }
        
        init() {
            if (!this.input) {
                console.error('DatePicker: Input-Element nicht gefunden');
                return;
            }
            
            this.setupInput();
            this.createCalendar();
            this.setupEventListeners();
        }
        
        setupInput() {
            this.input.setAttribute('readonly', 'true');
            this.input.classList.add('datepicker-input');
            
            // Container für Input und Calendar
            this.container = document.createElement('div');
            this.container.className = 'datepicker-container relative';
            this.input.parentNode.insertBefore(this.container, this.input);
            this.container.appendChild(this.input);
        }
        
        createCalendar() {
            this.calendar = document.createElement('div');
            this.calendar.className = 'datepicker-calendar absolute top-full left-0 mt-1 bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-600 rounded-lg shadow-lg z-50 hidden';
            this.calendar.innerHTML = this.renderCalendar();
            this.container.appendChild(this.calendar);
        }
        
        renderCalendar() {
            const year = this.currentDate.getFullYear();
            const month = this.currentDate.getMonth();
            const monthName = this.getMonthName(month);
            
            return `
                <div class="datepicker-header p-4 border-b border-slate-200 dark:border-slate-600">
                    <div class="flex items-center justify-between">
                        <button type="button" class="prev-month p-1 hover:bg-slate-100 dark:hover:bg-slate-700 rounded">
                            <svg class="w-4 h-4" fill="currentColor" viewBox="0 0 20 20">
                                <path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd"/>
                            </svg>
                        </button>
                        <div class="text-sm font-medium text-slate-900 dark:text-white">
                            ${monthName} ${year}
                        </div>
                        <button type="button" class="next-month p-1 hover:bg-slate-100 dark:hover:bg-slate-700 rounded">
                            <svg class="w-4 h-4" fill="currentColor" viewBox="0 0 20 20">
                                <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"/>
                            </svg>
                        </button>
                    </div>
                </div>
                
                <div class="datepicker-body p-4">
                    <div class="grid grid-cols-7 gap-1 mb-2">
                        ${this.getWeekdayHeaders()}
                    </div>
                    <div class="grid grid-cols-7 gap-1">
                        ${this.getDaysOfMonth(year, month)}
                    </div>
                </div>
            `;
        }
        
        getWeekdayHeaders() {
            const weekdays = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So'];
            return weekdays.map(day => 
                `<div class="text-xs font-medium text-slate-500 dark:text-slate-400 text-center p-1">${day}</div>`
            ).join('');
        }
        
        getDaysOfMonth(year, month) {
            const firstDay = new Date(year, month, 1);
            const lastDay = new Date(year, month + 1, 0);
            const startDate = new Date(firstDay);
            startDate.setDate(startDate.getDate() - ((firstDay.getDay() + 6) % 7));
            
            const days = [];
            const current = new Date(startDate);
            
            while (current <= lastDay || current.getMonth() === month) {
                const isCurrentMonth = current.getMonth() === month;
                const isToday = this.isToday(current);
                const isSelected = this.isSelectedDate(current);
                const isDisabled = this.isDisabledDate(current);
                
                const classes = [
                    'w-8 h-8 text-sm rounded cursor-pointer flex items-center justify-center transition-colors',
                    isCurrentMonth ? 'text-slate-900 dark:text-white' : 'text-slate-400 dark:text-slate-600',
                    isToday ? 'bg-blue-100 dark:bg-blue-900 text-blue-900 dark:text-blue-100' : '',
                    isSelected ? 'bg-blue-500 text-white' : '',
                    !isDisabled && isCurrentMonth ? 'hover:bg-slate-100 dark:hover:bg-slate-700' : '',
                    isDisabled ? 'cursor-not-allowed opacity-50' : ''
                ].filter(Boolean);
                
                days.push(`
                    <div class="${classes.join(' ')}" 
                         data-date="${this.formatDateForData(current)}"
                         ${isDisabled ? '' : 'data-selectable="true"'}>
                        ${current.getDate()}
                    </div>
                `);
                
                current.setDate(current.getDate() + 1);
                
                if (days.length >= 42) break; // Max 6 Wochen
            }
            
            return days.join('');
        }
        
        setupEventListeners() {
            // Input click
            this.input.addEventListener('click', () => {
                this.toggle();
            });
            
            // Calendar clicks
            this.calendar.addEventListener('click', (e) => {
                if (e.target.classList.contains('prev-month')) {
                    this.previousMonth();
                } else if (e.target.classList.contains('next-month')) {
                    this.nextMonth();
                } else if (e.target.dataset.selectable) {
                    this.selectDate(new Date(e.target.dataset.date));
                }
            });
            
            // Click outside
            document.addEventListener('click', (e) => {
                if (!this.container.contains(e.target)) {
                    this.close();
                }
            });
        }
        
        toggle() {
            if (this.isOpen) {
                this.close();
            } else {
                this.open();
            }
        }
        
        open() {
            this.calendar.classList.remove('hidden');
            this.isOpen = true;
            this.updateCalendar();
        }
        
        close() {
            this.calendar.classList.add('hidden');
            this.isOpen = false;
        }
        
        selectDate(date) {
            this.selectedDate = new Date(date);
            this.input.value = this.formatDate(date);
            
            // Custom Event
            this.input.dispatchEvent(new CustomEvent('dateselected', {
                detail: { date: new Date(date) }
            }));
            
            if (this.options.closeOnSelect) {
                this.close();
            }
        }
        
        previousMonth() {
            this.currentDate.setMonth(this.currentDate.getMonth() - 1);
            this.updateCalendar();
        }
        
        nextMonth() {
            this.currentDate.setMonth(this.currentDate.getMonth() + 1);
            this.updateCalendar();
        }
        
        updateCalendar() {
            this.calendar.innerHTML = this.renderCalendar();
        }
        
        isToday(date) {
            const today = new Date();
            return date.toDateString() === today.toDateString();
        }
        
        isSelectedDate(date) {
            return this.selectedDate && date.toDateString() === this.selectedDate.toDateString();
        }
        
        isDisabledDate(date) {
            if (this.options.minDate && date < this.options.minDate) return true;
            if (this.options.maxDate && date > this.options.maxDate) return true;
            return this.options.disabledDates.some(disabled => 
                date.toDateString() === disabled.toDateString()
            );
        }
        
        formatDate(date) {
            const day = date.getDate().toString().padStart(2, '0');
            const month = (date.getMonth() + 1).toString().padStart(2, '0');
            const year = date.getFullYear();
            
            return this.options.format
                .replace('dd', day)
                .replace('mm', month)
                .replace('yyyy', year);
        }
        
        formatDateForData(date) {
            return date.toISOString().split('T')[0];
        }
        
        getMonthName(monthIndex) {
            const months = [
                'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni',
                'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'
            ];
            return months[monthIndex];
        }
        
        setValue(date) {
            if (date) {
                this.selectDate(new Date(date));
            }
        }
        
        getValue() {
            return this.selectedDate;
        }
        
        clear() {
            this.selectedDate = null;
            this.input.value = '';
        }
    }
    
    // Globale API
    window.MYP.Advanced = {
        ProgressBar,
        FileUpload,
        DatePicker,
        
        // Convenience Functions
        createProgressBar: (container, options) => new ProgressBar(container, options),
        createFileUpload: (container, options) => new FileUpload(container, options),
        createDatePicker: (input, options) => new DatePicker(input, options)
    };
    
    // Auto-Initialize
    document.addEventListener('DOMContentLoaded', function() {
        // Auto-initialize datepickers
        document.querySelectorAll('[data-datepicker]').forEach(input => {
            const options = JSON.parse(input.dataset.datepicker || '{}');
            new DatePicker(input, options);
        });
        
        // Auto-initialize file uploads
        document.querySelectorAll('[data-file-upload]').forEach(container => {
            const options = JSON.parse(container.dataset.fileUpload || '{}');
            new FileUpload(container, options);
        });
        
        console.log('🚀 MYP Advanced Components geladen');
    });
    
})(); 