/**
 * CollectionManager - Dynamic content collection management for .insertr-add elements
 * 
 * Handles:
 * - Template detection from existing children
 * - Add/remove/reorder UI controls
 * - Collection data management
 * - Integration with existing .insertr editing system
 */

import { InsertrFormRenderer } from './form-renderer.js';

export class CollectionManager {
    constructor(meta, apiClient, auth) {
        this.meta = meta;
        this.container = meta.element;
        this.apiClient = apiClient;
        this.auth = auth;
        
        // Extract collection ID from container
        this.collectionId = this.container.getAttribute('data-content-id');
        if (!this.collectionId) {
            console.error('❌ Collection container missing data-content-id attribute');
            return;
        }
        
        // Collection state
        this.template = null;
        this.items = [];
        this.isActive = false;
        
        // UI elements
        this.addButton = null;
        this.itemControls = new Map(); // Map item element to its controls
        
        console.log('🔄 CollectionManager initialized for:', this.container, 'Collection ID:', this.collectionId);
    }
    
    /**
     * Initialize the collection manager
     */
    async initialize() {
        if (this.isActive) return;
        
        console.log('🚀 Starting collection management for:', this.container.className);
        
        // Analyze existing content to detect template
        this.analyzeTemplate();

        // Sync with backend to map existing items to collection item IDs
        await this.syncWithBackend();
        
        // Add collection management UI only when in edit mode
        this.setupEditModeDetection();
        
        this.isActive = true;
    }
    
    /**
     * Set up detection for when edit mode is activated
     */
    setupEditModeDetection() {
        // Check current auth state
        if (this.auth.isAuthenticated() && this.auth.isEditMode()) {
            this.activateCollectionUI();
        }
        
        // Listen for auth state changes (assuming the auth object has events)
        // For now, we'll poll - in a real implementation we'd use events
        this.authCheckInterval = setInterval(() => {
            const shouldBeActive = this.auth.isAuthenticated() && this.auth.isEditMode();
            if (shouldBeActive && !this.hasCollectionUI()) {
                this.activateCollectionUI();
            } else if (!shouldBeActive && this.hasCollectionUI()) {
                this.deactivateCollectionUI();
            }
        }, 1000);
    }
    
    /**
     * Check if collection UI is currently active
     */
    hasCollectionUI() {
        return this.addButton && this.addButton.parentNode;
    }
    
    /**
     * Activate collection UI when in edit mode
     */
    activateCollectionUI() {
        console.log('✅ Activating collection UI');
        
        // Add visual indicator to container
        this.container.classList.add('insertr-collection-active');
        
        // Add the "+ Add" button (top right of container per spec)
        this.createAddButton();
        
        // Add control buttons to each existing item
        this.addControlsToExistingItems();
    }
    
    /**
     * Deactivate collection UI when not in edit mode
     */
    deactivateCollectionUI() {
        console.log('❌ Deactivating collection UI');
        
        // Remove visual indicator
        this.container.classList.remove('insertr-collection-active');
        
        // Remove add button
        if (this.addButton) {
            this.addButton.remove();
            this.addButton = null;
        }
        
        // Remove all item controls
        this.itemControls.forEach((controls, item) => {
            controls.remove();
        });
        this.itemControls.clear();
    }
    
    /**
     * Analyze existing children to detect template pattern
     */
    analyzeTemplate() {
        const children = Array.from(this.container.children);
        
        if (children.length === 0) {
            console.warn('⚠️ No children found for template analysis');
            return;
        }
        
        // Use first child as template baseline
        const firstChild = children[0];
        
        this.template = {
            structure: this.extractElementStructure(firstChild),
            editableFields: this.findEditableElements(firstChild),
            htmlTemplate: firstChild.outerHTML
        };
        
        console.log('📋 Template detected:', this.template);
        
        // Store reference to current items
        // For existing items, try to extract collection item IDs if they exist
        this.items = children.map((child, index) => ({
            element: child,
            index: index,
            id: this.generateItemId(index),
            collectionItemId: this.extractCollectionItemId(child)
        }));
    }
    
    /**
     * Extract the structural pattern of an element
     */
    extractElementStructure(element) {
        return {
            tagName: element.tagName,
            classes: Array.from(element.classList),
            attributes: this.getRelevantAttributes(element),
            childStructure: this.analyzeChildStructure(element)
        };
    }
    
    /**
     * Get relevant attributes (excluding data-content-id which will be unique)
     */
    getRelevantAttributes(element) {
        const relevantAttrs = {};
        for (const attr of element.attributes) {
            if (attr.name !== 'data-content-id') {
                relevantAttrs[attr.name] = attr.value;
            }
        }
        return relevantAttrs;
    }
    
    /**
     * Analyze child structure for template replication
     */
    analyzeChildStructure(element) {
        return Array.from(element.children).map(child => ({
            tagName: child.tagName,
            classes: Array.from(child.classList),
            hasInsertrClass: child.classList.contains('insertr'),
            content: child.classList.contains('insertr') ? '' : child.textContent
        }));
    }
    
    /**
     * Find editable elements within a container
     */
    findEditableElements(container) {
        return Array.from(container.querySelectorAll('.insertr')).map(el => ({
            selector: this.generateRelativeSelector(el, container),
            type: this.determineFieldType(el),
            placeholder: this.generatePlaceholder(el)
        }));
    }
    
    /**
     * Generate a relative selector for an element within a container
     */
    generateRelativeSelector(element, container) {
        // Simple approach: use tag name and classes
        const tagName = element.tagName.toLowerCase();
        const classes = Array.from(element.classList).join('.');
        return classes ? `${tagName}.${classes}` : tagName;
    }
    
    /**
     * Determine the type of field for editing
     */
    determineFieldType(element) {
        const tagName = element.tagName.toLowerCase();
        if (tagName === 'a') return 'link';
        if (tagName === 'img') return 'image';
        return 'text';
    }
    
    /**
     * Generate placeholder text for empty fields
     */
    generatePlaceholder(element) {
        const tagName = element.tagName.toLowerCase();
        if (tagName === 'h1' || tagName === 'h2') return 'Enter heading...';
        if (tagName === 'blockquote') return 'Enter quote...';
        if (tagName === 'cite') return 'Enter author...';
        return 'Enter text...';
    }
    
    /**
     * Generate unique ID for new items
     */
    generateItemId(index) {
        return `item-${Date.now()}-${index}`;
    }

    /**
     * Extract collection item ID from existing DOM element
     * This is used for existing items that were reconstructed from database
     */
    extractCollectionItemId(element) {
        // Look for data-collection-item-id attribute first (newly created items)
        let itemId = element.getAttribute('data-collection-item-id');
        if (itemId) {
            return itemId;
        }

        // For existing items reconstructed from database, try to infer from data-content-id
        // The backend should have generated collection item IDs based on collection ID
        const contentId = element.getAttribute('data-content-id');
        if (contentId && this.collectionId) {
            // This is a heuristic - we'll need to fetch the actual mapping from the backend
            // For now, return null and let the backend operations handle missing IDs
            return null;
        }

        return null;
    }

    /**
     * Sync frontend state with backend collection items
     * This maps existing DOM elements to their collection item IDs
     */
    async syncWithBackend() {
        if (!this.collectionId) {
            console.warn('⚠️ Cannot sync with backend: no collection ID');
            return;
        }

        try {
            // Fetch current collection items from backend
            const backendItems = await this.apiClient.getCollectionItems(this.collectionId);
            console.log('📋 Backend collection items:', backendItems);

            // Map backend items to existing DOM elements by position
            // This assumes the DOM order matches the database order
            backendItems.forEach((backendItem, index) => {
                if (this.items[index]) {
                    this.items[index].collectionItemId = backendItem.item_id;
                    this.items[index].element.setAttribute('data-collection-item-id', backendItem.item_id);
                    console.log(`🔗 Mapped DOM element ${index} to collection item ${backendItem.item_id}`);
                }
            });

            console.log('✅ Frontend-backend sync completed');
        } catch (error) {
            console.error('❌ Failed to sync with backend:', error);
            // Continue without backend sync - collection management will still work for new items
        }
    }
    
    /**
     * Create the "+ Add" button positioned in top right of container
     */
    createAddButton() {
        if (this.addButton) return; // Already exists
        
        this.addButton = document.createElement('button');
        this.addButton.className = 'insertr-add-btn';
        this.addButton.innerHTML = '+ Add Item';
        this.addButton.title = 'Add new item to collection';
        
        // Position in top right of container as per spec
        this.container.style.position = 'relative';
        
        this.addButton.addEventListener('click', (e) => {
            e.preventDefault();
            e.stopPropagation();
            this.addNewItem();
        });
        
        this.container.appendChild(this.addButton);
        console.log('➕ Add button created');
    }
    
    /**
     * Add control buttons to all existing items
     */
    addControlsToExistingItems() {
        this.items.forEach((item, index) => {
            this.addItemControls(item.element, index);
        });
    }
    
    /**
     * Add management controls to an item (remove, reorder)
     */
    addItemControls(itemElement, index) {
        if (this.itemControls.has(itemElement)) return; // Already has controls
        
        const controls = document.createElement('div');
        controls.className = 'insertr-item-controls';
        
        // Remove button (always present)
        const removeBtn = this.createControlButton('×', 'Remove item', () => 
            this.removeItem(itemElement)
        );
        
        // Move up button (if not first item)
        if (index > 0) {
            const upBtn = this.createControlButton('↑', 'Move up', () => 
                this.moveItem(itemElement, 'up')
            );
            controls.appendChild(upBtn);
        }
        
        // Move down button (if not last item)
        if (index < this.items.length - 1) {
            const downBtn = this.createControlButton('↓', 'Move down', () => 
                this.moveItem(itemElement, 'down')
            );
            controls.appendChild(downBtn);
        }
        
        controls.appendChild(removeBtn);
        
        // Position in top right corner of item as per spec
        itemElement.style.position = 'relative';
        itemElement.appendChild(controls);
        
        // Store reference
        this.itemControls.set(itemElement, controls);
        
        // Add hover behavior
        this.setupItemHoverBehavior(itemElement, controls);
    }
    
    /**
     * Create a control button
     */
    createControlButton(text, title, onClick) {
        const button = document.createElement('button');
        button.className = 'insertr-control-btn';
        button.textContent = text;
        button.title = title;
        button.addEventListener('click', (e) => {
            e.preventDefault();
            e.stopPropagation();
            onClick();
        });
        return button;
    }
    
    /**
     * Set up hover behavior for item controls
     */
    setupItemHoverBehavior(itemElement, controls) {
        itemElement.addEventListener('mouseenter', () => {
            controls.style.opacity = '1';
        });
        
        itemElement.addEventListener('mouseleave', () => {
            controls.style.opacity = '0';
        });
    }
    
    /**
     * Add a new item to the collection (backend-first approach)
     */
    async addNewItem() {
        console.log('➕ Adding new item to collection');
        
        if (!this.template || !this.collectionId) {
            console.error('❌ No template or collection ID available for creating new items');
            return;
        }

        try {
            // 1. Create collection item in database first (backend-first approach)
            const templateId = 1; // Use first template by default
            const collectionItem = await this.apiClient.createCollectionItem(this.collectionId, templateId);
            
            // 2. Create DOM element from the returned collection item data
            const newItem = this.createItemFromCollectionData(collectionItem);
            
            // 3. Add to DOM
            this.container.insertBefore(newItem, this.addButton);
            
            // 4. Update items array with backend data
            const newItemData = {
                element: newItem,
                index: this.items.length,
                id: collectionItem.item_id,
                collectionItem: collectionItem
            };
            this.items.push(newItemData);
            
            // 5. Add controls to new item
            this.addItemControls(newItem, this.items.length - 1);
            
            // 6. Re-initialize any .insertr elements in the new item
            this.initializeInsertrElements(newItem);
            
            // 7. Update all item controls (indices may have changed)
            this.updateAllItemControls();
            
            // 8. Trigger site enhancement to update static files
            await this.apiClient.enhanceSite();
            
            console.log('✅ New item added successfully:', collectionItem.item_id);
        } catch (error) {
            console.error('❌ Failed to add new collection item:', error);
            alert('Failed to add new item. Please try again.');
        }
    }
    
    /**
     * Create a DOM element from collection item data returned by backend
     * Backend is the source of truth - use its HTML content directly
     */
    createItemFromCollectionData(collectionItem) {
        // Use backend HTML content directly (database is source of truth)
        if (collectionItem.html_content && collectionItem.html_content.trim()) {
            const tempContainer = document.createElement('div');
            tempContainer.innerHTML = collectionItem.html_content;
            const newItem = tempContainer.firstElementChild;
            
            // Set the collection item ID as data attribute for future reference
            newItem.setAttribute('data-collection-item-id', collectionItem.item_id);
            
            return newItem;
        } else {
            // Fallback: create from frontend template if backend content is empty
            const tempContainer = document.createElement('div');
            tempContainer.innerHTML = this.template.htmlTemplate;
            const newItem = tempContainer.firstElementChild;
            
            // Set the collection item ID as data attribute for future reference
            newItem.setAttribute('data-collection-item-id', collectionItem.item_id);
            
            return newItem;
        }
    }

    /**
     * Create a new item from the template (legacy method, kept for compatibility)
     */
    createItemFromTemplate() {
        // Create element from template HTML
        const tempContainer = document.createElement('div');
        tempContainer.innerHTML = this.template.htmlTemplate;
        const newItem = tempContainer.firstElementChild;
        
        // Clear content from editable fields
        this.template.editableFields.forEach(field => {
            const element = newItem.querySelector(field.selector);
            if (element) {
                this.clearElementContent(element, field.type);
                // Add placeholder text
                if (field.type === 'text') {
                    element.textContent = field.placeholder;
                    element.style.color = '#999';
                    element.style.fontStyle = 'italic';
                    
                    // Remove placeholder styling when user starts editing
                    element.addEventListener('focus', () => {
                        if (element.textContent === field.placeholder) {
                            element.textContent = '';
                            element.style.color = '';
                            element.style.fontStyle = '';
                        }
                    });
                }
            }
        });
        
        // Generate unique data-content-id for the item
        newItem.setAttribute('data-content-id', this.generateItemId(Date.now()));
        
        return newItem;
    }
    
    /**
     * Clear content from an element based on its type
     */
    clearElementContent(element, type) {
        if (type === 'link') {
            element.textContent = '';
            element.removeAttribute('href');
        } else if (type === 'image') {
            element.removeAttribute('src');
            element.removeAttribute('alt');
        } else {
            element.textContent = '';
        }
    }
    
    /**
     * Initialize .insertr elements within a new item
     * This integrates with the existing editing system
     */
    initializeInsertrElements(container) {
        const insertrElements = container.querySelectorAll('.insertr');
        insertrElements.forEach(element => {
            // Add click handler for editing (same as existing system)
            element.addEventListener('click', (e) => {
                // Only allow editing if authenticated and in edit mode
                if (!this.auth.isAuthenticated() || !this.auth.isEditMode()) {
                    return;
                }
                
                e.preventDefault();
                e.stopPropagation();
                
                // Use the existing form renderer
                const formRenderer = new InsertrFormRenderer(this.apiClient);
                const meta = {
                    contentId: element.getAttribute('data-content-id'),
                    element: element,
                    htmlMarkup: element.outerHTML
                };
                const currentContent = this.extractCurrentContent(element);
                
                formRenderer.showEditForm(
                    meta,
                    currentContent,
                    (formData) => this.handleItemSave(meta, formData),
                    () => formRenderer.closeForm()
                );
            });
        });
    }
    
    /**
     * Extract current content (simplified version of editor.js method)
     */
    extractCurrentContent(element) {
        if (element.tagName.toLowerCase() === 'a') {
            return {
                text: element.textContent.trim(),
                url: element.getAttribute('href') || ''
            };
        }
        return element.textContent.trim();
    }
    
    /**
     * Handle saving of individual item content
     */
    async handleItemSave(meta, formData) {
        console.log('💾 Saving item content:', meta.contentId, formData);
        
        try {
            let contentValue;
            if (typeof formData === 'string') {
                contentValue = formData;
            } else if (formData.content) {
                contentValue = formData.content;
            } else if (formData.text) {
                contentValue = formData.text;
            } else {
                contentValue = formData;
            }
            
            let result;
            if (meta.contentId) {
                result = await this.apiClient.updateContent(meta.contentId, contentValue);
            } else {
                result = await this.apiClient.createContent(contentValue, meta.htmlMarkup);
            }
            
            if (result) {
                meta.element.setAttribute('data-content-id', result.id);
                console.log(`✅ Item content saved: ${result.id}`);
            } else {
                console.error('❌ Failed to save item content to server');
            }
            
        } catch (error) {
            console.error('❌ Error saving item content:', error);
        }
    }
    
    /**
     * Remove an item from the collection (backend-first approach)
     */
    async removeItem(itemElement) {
        if (!confirm('Are you sure you want to remove this item?')) {
            return;
        }
        
        console.log('🗑️ Removing item from collection');

        try {
            // 1. Get the collection item ID from the element
            const collectionItemId = itemElement.getAttribute('data-collection-item-id');
            if (!collectionItemId) {
                console.error('❌ Cannot remove item: missing data-collection-item-id attribute');
                return;
            }

            // 2. Delete from database first (backend-first approach)
            const success = await this.apiClient.deleteCollectionItem(this.collectionId, collectionItemId);
            if (!success) {
                alert('Failed to remove item from database. Please try again.');
                return;
            }

            // 3. Remove controls
            const controls = this.itemControls.get(itemElement);
            if (controls) {
                controls.remove();
                this.itemControls.delete(itemElement);
            }
            
            // 4. Remove from items array
            this.items = this.items.filter(item => item.element !== itemElement);
            
            // 5. Remove from DOM
            itemElement.remove();
            
            // 6. Update all item controls (indices changed)
            this.updateAllItemControls();

            // 7. Trigger site enhancement to update static files
            await this.apiClient.enhanceSite();
            
            console.log('✅ Item removed successfully:', collectionItemId);
        } catch (error) {
            console.error('❌ Failed to remove collection item:', error);
            alert('Failed to remove item. Please try again.');
        }
    }
    
    /**
     * Move an item up or down in the collection (backend-first approach)
     */
    async moveItem(itemElement, direction) {
        console.log(`🔄 Moving item ${direction}`);
        
        const currentIndex = this.items.findIndex(item => item.element === itemElement);
        if (currentIndex === -1) return;
        
        let newIndex;
        if (direction === 'up' && currentIndex > 0) {
            newIndex = currentIndex - 1;
        } else if (direction === 'down' && currentIndex < this.items.length - 1) {
            newIndex = currentIndex + 1;
        } else {
            return; // Can't move in that direction
        }

        try {
            // 1. Get the collection item ID
            const collectionItemId = itemElement.getAttribute('data-collection-item-id');
            if (!collectionItemId) {
                console.error('❌ Cannot move item: missing data-collection-item-id attribute');
                return;
            }

            // 2. Update position in database first (backend-first approach)
            // Note: Backend expects 0-based positions, but we may need to adjust based on backend implementation
            const success = await this.apiClient.updateCollectionItemPosition(this.collectionId, collectionItemId, newIndex);
            if (!success) {
                alert('Failed to update item position in database. Please try again.');
                return;
            }
            
            // 3. Get the target position in DOM
            const targetItem = this.items[newIndex];
            
            // 4. Move in DOM
            if (direction === 'up') {
                this.container.insertBefore(itemElement, targetItem.element);
            } else {
                this.container.insertBefore(itemElement, targetItem.element.nextSibling);
            }
            
            // 5. Update items array
            [this.items[currentIndex], this.items[newIndex]] = [this.items[newIndex], this.items[currentIndex]];
            this.items[currentIndex].index = currentIndex;
            this.items[newIndex].index = newIndex;
            
            // 6. Update all item controls
            this.updateAllItemControls();

            // 7. Trigger site enhancement to update static files
            await this.apiClient.enhanceSite();
            
            console.log('✅ Item moved successfully:', collectionItemId, '→ position', newIndex);
        } catch (error) {
            console.error('❌ Failed to move collection item:', error);
            alert('Failed to move item. Please try again.');
        }
    }
    
    /**
     * Update controls for all items (called after reordering)
     */
    updateAllItemControls() {
        // Remove all existing controls
        this.itemControls.forEach((controls, item) => {
            controls.remove();
        });
        this.itemControls.clear();
        
        // Re-add controls with correct up/down button states
        this.items.forEach((item, index) => {
            this.addItemControls(item.element, index);
        });
    }
    
    /**
     * Cleanup when the collection manager is destroyed
     */
    destroy() {
        if (this.authCheckInterval) {
            clearInterval(this.authCheckInterval);
        }
        
        this.deactivateCollectionUI();
        this.isActive = false;
        
        console.log('🧹 CollectionManager destroyed');
    }
}