/**
 * Library Management System for The Academy
 * Handles media tagging, organization, quality ratings, and preference-based filtering
 */

class LibraryManager {
    constructor() {
        this.initializeLibrary();
    }

    /**
     * Initialize library structure in gameData if it doesn't exist
     * Integrates with existing desktopFileManager video/photo system
     */
    initializeLibrary() {
        if (!window.gameData.academyLibrary) {
            window.gameData.academyLibrary = {
                version: 1,
                lastUpdated: new Date().toISOString(),
                
                // Media items with tags and metadata
                // Keys are file paths from desktopFileManager.getAllVideos()
                media: {
                    // Key: file path from existing library, Value: metadata object
                    // Example: "C:/Users/drew/Videos/video1.mp4": { tags: [...], rating: 5, ... }
                },
                
                // Tag definitions and usage counts
                tags: {
                    // Content theme tags
                    contentThemes: ['dominance', 'submission', 'humiliation', 'worship', 'edging', 'denial', 
                                   'cei', 'sissy', 'bbc', 'feet', 'femdom', 'maledom', 'lesbian', 'gay', 
                                   'trans', 'hentai', 'pov', 'joi', 'gooning', 'mindbreak'],
                    
                    // Visual style tags
                    visualStyles: ['solo', 'couples', 'group', 'amateur', 'professional', 'animated', 
                                  'real', 'closeup', 'fullbody', 'pov', 'compilation', 'pmv', 'slowmo', 
                                  'artistic', 'raw'],
                    
                    // Intensity tags
                    intensity: ['soft', 'moderate', 'intense', 'extreme', 'hardcore', 'gentle', 'rough'],
                    
                    // Audio tags
                    audio: ['music', 'talking', 'moaning', 'silent', 'asmr', 'binaural', 'soundfx', 
                           'voiceover', 'ambient'],
                    
                    // Quality tags
                    quality: ['lowres', 'sd', 'hd', '720p', '1080p', '4k', 'vr'],
                    
                    // Duration tags
                    duration: ['short', 'medium', 'long', 'loop', 'extended'],
                    
                    // Actor/performer tags (will be populated dynamically)
                    performers: [],
                    
                    // Custom user tags
                    custom: []
                },
                
                // Tag usage statistics
                tagStats: {
                    // Tag name -> count of media items with that tag
                },
                
                // Quality ratings by user
                ratings: {
                    // File path -> rating (1-5 stars)
                },
                
                // User's favorite/disliked items
                favorites: [],
                disliked: [],
                
                // Collection system (playlists/categories)
                collections: {
                    // Collection name -> array of file paths
                },
                
                // Scan history (track what's been tagged)
                scanHistory: {
                    lastFullScan: null,
                    scannedFolders: [],
                    totalItemsScanned: 0,
                    totalItemsTagged: 0
                }
            };
            
            this.saveLibrary();
        }
    }

    /**
     * Get the full library object
     * @returns {Object} Library object
     */
    getLibrary() {
        return window.gameData.academyLibrary;
    }

    /**
     * Add or update media item with tags and metadata
     * @param {string} filePath - Path to media file
     * @param {Object} metadata - Metadata object { tags, rating, duration, etc. }
     * @returns {boolean} Success status
     */
    addMediaItem(filePath, metadata = {}) {
        const library = this.getLibrary();
        
        // Create or update media item
        if (!library.media[filePath]) {
            library.media[filePath] = {
                filePath: filePath,
                tags: [],
                rating: 0,
                timesPlayed: 0,
                lastPlayed: null,
                addedDate: new Date().toISOString(),
                duration: null,
                fileSize: null,
                format: this.getFileFormat(filePath)
            };
        }
        
        // Merge metadata
        Object.assign(library.media[filePath], metadata);
        
        // Update tag statistics
        if (metadata.tags) {
            this.updateTagStats(metadata.tags);
        }
        
        library.lastUpdated = new Date().toISOString();
        this.saveLibrary();
        return true;
    }

    /**
     * Add tags to a media item
     * @param {string} filePath - Path to media file
     * @param {Array<string>} tags - Array of tag names
     * @returns {boolean} Success status
     */
    addTags(filePath, tags) {
        const library = this.getLibrary();
        
        if (!library.media[filePath]) {
            this.addMediaItem(filePath);
        }
        
        const item = library.media[filePath];
        
        // Add new tags (avoid duplicates)
        tags.forEach(tag => {
            if (!item.tags.includes(tag)) {
                item.tags.push(tag);
            }
        });
        
        // Update tag statistics
        this.updateTagStats(tags);
        
        library.lastUpdated = new Date().toISOString();
        this.saveLibrary();
        return true;
    }

    /**
     * Remove tags from a media item
     * @param {string} filePath - Path to media file
     * @param {Array<string>} tags - Array of tag names to remove
     * @returns {boolean} Success status
     */
    removeTags(filePath, tags) {
        const library = this.getLibrary();
        
        if (!library.media[filePath]) {
            return false;
        }
        
        const item = library.media[filePath];
        
        tags.forEach(tag => {
            const index = item.tags.indexOf(tag);
            if (index > -1) {
                item.tags.splice(index, 1);
                
                // Decrement tag stat
                if (library.tagStats[tag]) {
                    library.tagStats[tag] = Math.max(0, library.tagStats[tag] - 1);
                }
            }
        });
        
        library.lastUpdated = new Date().toISOString();
        this.saveLibrary();
        return true;
    }

    /**
     * Bulk tag multiple files at once
     * @param {Array<string>} filePaths - Array of file paths
     * @param {Array<string>} tags - Array of tags to add to all files
     * @returns {Object} Result object with success count
     */
    bulkAddTags(filePaths, tags) {
        let successCount = 0;
        
        filePaths.forEach(filePath => {
            if (this.addTags(filePath, tags)) {
                successCount++;
            }
        });
        
        return {
            success: true,
            filesTagged: successCount,
            totalFiles: filePaths.length,
            tags: tags
        };
    }

    /**
     * Set quality rating for a media item
     * @param {string} filePath - Path to media file
     * @param {number} rating - Rating (1-5)
     * @returns {boolean} Success status
     */
    setRating(filePath, rating) {
        if (rating < 1 || rating > 5) {
            console.error('Rating must be between 1 and 5');
            return false;
        }
        
        const library = this.getLibrary();
        
        if (!library.media[filePath]) {
            this.addMediaItem(filePath);
        }
        
        library.media[filePath].rating = rating;
        library.ratings[filePath] = rating;
        
        library.lastUpdated = new Date().toISOString();
        this.saveLibrary();
        return true;
    }

    /**
     * Add media item to favorites
     * @param {string} filePath - Path to media file
     * @returns {boolean} Success status
     */
    addToFavorites(filePath) {
        const library = this.getLibrary();
        
        if (!library.favorites.includes(filePath)) {
            library.favorites.push(filePath);
            
            // Remove from disliked if present
            const dislikedIndex = library.disliked.indexOf(filePath);
            if (dislikedIndex > -1) {
                library.disliked.splice(dislikedIndex, 1);
            }
            
            library.lastUpdated = new Date().toISOString();
            this.saveLibrary();
        }
        
        return true;
    }

    /**
     * Add media item to disliked list
     * @param {string} filePath - Path to media file
     * @returns {boolean} Success status
     */
    addToDisliked(filePath) {
        const library = this.getLibrary();
        
        if (!library.disliked.includes(filePath)) {
            library.disliked.push(filePath);
            
            // Remove from favorites if present
            const favIndex = library.favorites.indexOf(filePath);
            if (favIndex > -1) {
                library.favorites.splice(favIndex, 1);
            }
            
            library.lastUpdated = new Date().toISOString();
            this.saveLibrary();
        }
        
        return true;
    }

    /**
     * Search/filter media by tags and criteria
     * @param {Object} filters - Filter configuration
     * @returns {Array<Object>} Array of matching media items
     */
    searchMedia(filters = {}) {
        const library = this.getLibrary();
        let results = Object.values(library.media);
        
        // Filter by required tags (item must have ALL these tags)
        if (filters.requiredTags && filters.requiredTags.length > 0) {
            results = results.filter(item => 
                filters.requiredTags.every(tag => item.tags.includes(tag))
            );
        }
        
        // Filter by any tags (item must have AT LEAST ONE of these tags)
        if (filters.anyTags && filters.anyTags.length > 0) {
            results = results.filter(item => 
                filters.anyTags.some(tag => item.tags.includes(tag))
            );
        }
        
        // Filter by excluded tags (item must NOT have any of these tags)
        if (filters.excludedTags && filters.excludedTags.length > 0) {
            results = results.filter(item => 
                !filters.excludedTags.some(tag => item.tags.includes(tag))
            );
        }
        
        // Filter by minimum rating
        if (filters.minRating) {
            results = results.filter(item => item.rating >= filters.minRating);
        }
        
        // Filter by favorites only
        if (filters.favoritesOnly) {
            results = results.filter(item => library.favorites.includes(item.filePath));
        }
        
        // Exclude disliked
        if (filters.excludeDisliked) {
            results = results.filter(item => !library.disliked.includes(item.filePath));
        }
        
        // Filter by format
        if (filters.format) {
            results = results.filter(item => item.format === filters.format);
        }
        
        // Sort results
        if (filters.sortBy) {
            results = this.sortResults(results, filters.sortBy, filters.sortOrder || 'desc');
        }
        
        // Limit results
        if (filters.limit) {
            results = results.slice(0, filters.limit);
        }
        
        return results;
    }

    /**
     * Get media items matching user's preferences (from preferenceManager)
     * @param {Object} preferenceFilter - Filter from preferenceManager.getContentFilter()
     * @param {number} limit - Maximum number of items to return
     * @returns {Array<Object>} Array of matching media items
     */
    getMediaForPreferences(preferenceFilter, limit = 10) {
        const filters = {
            anyTags: [
                ...preferenceFilter.themes,
                ...preferenceFilter.visuals,
                ...preferenceFilter.audio,
                ...preferenceFilter.tones
            ],
            excludedTags: [
                ...preferenceFilter.exclude.hardLimits,
                ...preferenceFilter.exclude.softLimits
            ],
            excludeDisliked: true,
            sortBy: 'rating',
            sortOrder: 'desc',
            limit: limit
        };
        
        return this.searchMedia(filters);
    }

    /**
     * Create a collection (playlist/category)
     * @param {string} name - Collection name
     * @param {Array<string>} filePaths - Array of file paths
     * @returns {boolean} Success status
     */
    createCollection(name, filePaths = []) {
        const library = this.getLibrary();
        
        library.collections[name] = filePaths;
        
        library.lastUpdated = new Date().toISOString();
        this.saveLibrary();
        return true;
    }

    /**
     * Add items to a collection
     * @param {string} collectionName - Collection name
     * @param {Array<string>} filePaths - File paths to add
     * @returns {boolean} Success status
     */
    addToCollection(collectionName, filePaths) {
        const library = this.getLibrary();
        
        if (!library.collections[collectionName]) {
            this.createCollection(collectionName, filePaths);
        } else {
            filePaths.forEach(filePath => {
                if (!library.collections[collectionName].includes(filePath)) {
                    library.collections[collectionName].push(filePath);
                }
            });
        }
        
        library.lastUpdated = new Date().toISOString();
        this.saveLibrary();
        return true;
    }

    /**
     * Get all items in a collection
     * @param {string} collectionName - Collection name
     * @returns {Array<Object>} Array of media items
     */
    getCollection(collectionName) {
        const library = this.getLibrary();
        
        if (!library.collections[collectionName]) {
            return [];
        }
        
        return library.collections[collectionName].map(filePath => 
            library.media[filePath]
        ).filter(item => item !== undefined);
    }

    /**
     * Get library statistics
     * @returns {Object} Stats object
     */
    getLibraryStats() {
        const library = this.getLibrary();
        
        const totalItems = Object.keys(library.media).length;
        const taggedItems = Object.values(library.media).filter(item => item.tags.length > 0).length;
        const ratedItems = Object.values(library.media).filter(item => item.rating > 0).length;
        
        // Calculate average rating
        const ratings = Object.values(library.media).map(item => item.rating).filter(r => r > 0);
        const avgRating = ratings.length > 0 ? (ratings.reduce((a, b) => a + b, 0) / ratings.length).toFixed(2) : 0;
        
        return {
            totalItems: totalItems,
            taggedItems: taggedItems,
            untaggedItems: totalItems - taggedItems,
            ratedItems: ratedItems,
            averageRating: parseFloat(avgRating),
            totalFavorites: library.favorites.length,
            totalDisliked: library.disliked.length,
            totalCollections: Object.keys(library.collections).length,
            totalTags: Object.keys(library.tagStats).length,
            mostUsedTags: this.getMostUsedTags(5),
            lastUpdated: library.lastUpdated,
            scanHistory: library.scanHistory
        };
    }

    /**
     * Get most used tags
     * @param {number} limit - Number of tags to return
     * @returns {Array<Object>} Array of {tag, count} objects
     */
    getMostUsedTags(limit = 10) {
        const library = this.getLibrary();
        
        return Object.entries(library.tagStats)
            .sort((a, b) => b[1] - a[1])
            .slice(0, limit)
            .map(([tag, count]) => ({ tag, count }));
    }

    /**
     * Get all available tags by category
     * @returns {Object} Tags organized by category
     */
    getAllTags() {
        return this.getLibrary().tags;
    }

    /**
     * Sync with existing video library from desktopFileManager
     * Imports videos from existing library and preserves existing Academy tags/ratings
     */
    syncWithExistingLibrary() {
        console.log('🔄 Syncing with existing video library...');
        
        let allVideos = [];
        
        // Get videos from desktopFileManager (primary source)
        if (window.desktopFileManager && typeof window.desktopFileManager.getAllVideos === 'function') {
            allVideos = window.desktopFileManager.getAllVideos();
            console.log(`📹 Found ${allVideos.length} videos from desktopFileManager`);
        }
        
        // Fallback to unifiedVideoLibrary in localStorage
        if (allVideos.length === 0) {
            const unifiedData = JSON.parse(localStorage.getItem('unifiedVideoLibrary') || '{}');
            allVideos = unifiedData.allVideos || [];
            console.log(`📹 Found ${allVideos.length} videos from unifiedVideoLibrary`);
        }
        
        // Import videos into Academy library while preserving existing Academy metadata
        const library = this.getLibrary();
        let newCount = 0;
        let existingCount = 0;
        
        allVideos.forEach(video => {
            const filePath = video.path || video.name;
            
            if (!library.media[filePath]) {
                // New video - add with minimal metadata
                library.media[filePath] = {
                    filePath: filePath,
                    name: video.name,
                    tags: [],
                    rating: 0,
                    timesPlayed: 0,
                    lastPlayed: null,
                    addedDate: new Date().toISOString(),
                    duration: video.duration || null,
                    fileSize: video.size || null,
                    format: video.format || this.getFileFormat(filePath),
                    // Preserve original library metadata
                    originalSource: video.directory || video.source || 'Unknown',
                    resolution: video.resolution || null,
                    thumbnail: video.thumbnail || null
                };
                newCount++;
            } else {
                // Existing video - update non-Academy fields only
                library.media[filePath].name = video.name;
                library.media[filePath].duration = video.duration || library.media[filePath].duration;
                library.media[filePath].fileSize = video.size || library.media[filePath].fileSize;
                library.media[filePath].format = video.format || library.media[filePath].format;
                library.media[filePath].resolution = video.resolution || library.media[filePath].resolution;
                library.media[filePath].thumbnail = video.thumbnail || library.media[filePath].thumbnail;
                existingCount++;
            }
        });
        
        library.lastUpdated = new Date().toISOString();
        library.scanHistory.lastFullScan = new Date().toISOString();
        library.scanHistory.totalItemsScanned = allVideos.length;
        library.scanHistory.totalItemsTagged = Object.values(library.media).filter(item => item.tags.length > 0).length;
        
        this.saveLibrary();
        
        console.log(`✅ Sync complete: ${newCount} new, ${existingCount} existing, ${allVideos.length} total videos`);
        
        return {
            total: allVideos.length,
            new: newCount,
            existing: existingCount
        };
    }

    /**
     * Get all videos from existing library (convenience method)
     * @returns {Array<Object>} Array of video objects with Academy metadata
     */
    getAllVideosWithMetadata() {
        const library = this.getLibrary();
        return Object.values(library.media);
    }

    /**
     * Get video by file path
     * @param {string} filePath - Path to video file
     * @returns {Object|null} Video object with metadata
     */
    getVideoByPath(filePath) {
        const library = this.getLibrary();
        return library.media[filePath] || null;
    }

    /**
     * Add a custom tag
     * @param {string} tagName - Custom tag name
     * @returns {boolean} Success status
     */
    addCustomTag(tagName) {
        const library = this.getLibrary();
        
        if (!library.tags.custom.includes(tagName)) {
            library.tags.custom.push(tagName);
            library.lastUpdated = new Date().toISOString();
            this.saveLibrary();
        }
        
        return true;
    }

    /**
     * Record that a media item was played
     * @param {string} filePath - Path to media file
     * @returns {boolean} Success status
     */
    recordPlay(filePath) {
        const library = this.getLibrary();
        
        if (!library.media[filePath]) {
            this.addMediaItem(filePath);
        }
        
        library.media[filePath].timesPlayed = (library.media[filePath].timesPlayed || 0) + 1;
        library.media[filePath].lastPlayed = new Date().toISOString();
        
        this.saveLibrary();
        return true;
    }

    /**
     * Get recently played items
     * @param {number} limit - Number of items to return
     * @returns {Array<Object>} Array of media items
     */
    getRecentlyPlayed(limit = 10) {
        const library = this.getLibrary();
        
        return Object.values(library.media)
            .filter(item => item.lastPlayed !== null)
            .sort((a, b) => new Date(b.lastPlayed) - new Date(a.lastPlayed))
            .slice(0, limit);
    }

    /**
     * Reset library to empty state
     * @returns {boolean} Success status
     */
    resetLibrary() {
        delete window.gameData.academyLibrary;
        this.initializeLibrary();
        return true;
    }

    /**
     * Add a directory of media files to the library
     * Uses desktopFileManager to select and scan a directory
     * @param {Array<string>} suggestedTags - Optional tags to apply to all files in directory
     * @returns {Promise<Object>} Result object with file count and status
     */
    async addDirectory(suggestedTags = []) {
        console.log('📁 Adding directory to library with suggested tags:', suggestedTags);
        
        // Check if desktopFileManager is available
        if (!window.desktopFileManager) {
            console.error('❌ desktopFileManager not available');
            throw new Error('Desktop file manager is required to add directories');
        }

        try {
            // Use desktopFileManager to add a video directory
            const result = await window.desktopFileManager.addVideoDirectory();
            
            if (!result || !result.videoCount || result.videoCount === 0) {
                console.log('⚠️ No files added from directory');
                return {
                    success: false,
                    fileCount: 0,
                    message: 'No files selected or found'
                };
            }

            // Get all videos from desktopFileManager after adding directory
            const allVideos = window.desktopFileManager.getAllVideos();
            console.log(`📹 Total videos in library: ${allVideos.length}`);

            // Sync the library with the new videos
            this.syncWithExistingLibrary();

            // If suggested tags were provided, apply them to the newly added videos
            if (suggestedTags.length > 0 && result.videos && result.videos.length > 0) {
                console.log(`🏷️ Applying suggested tags to ${result.videos.length} files:`, suggestedTags);
                
                // Get file paths from the result
                const filePaths = result.videos.map(video => video.path || video.fullPath || video.name);
                
                // Bulk add tags to all files
                const tagResult = this.bulkAddTags(filePaths, suggestedTags);
                console.log(`✅ Tagged ${tagResult.filesTagged} files with tags:`, suggestedTags);
            }

            const library = this.getLibrary();
            library.scanHistory.lastFullScan = new Date().toISOString();
            if (!library.scanHistory.scannedFolders.includes('user-selected')) {
                library.scanHistory.scannedFolders.push('user-selected');
            }
            
            this.saveLibrary();

            console.log(`✅ Directory added successfully: ${result.videoCount} files`);
            
            return {
                success: true,
                fileCount: result.videoCount,
                totalFiles: allVideos.length,
                message: `Added ${result.videoCount} files to library`
            };

        } catch (error) {
            console.error('❌ Error adding directory:', error);
            throw error;
        }
    }

    // Helper methods

    /**
     * Update tag statistics
     * @param {Array<string>} tags - Tags to increment
     */
    updateTagStats(tags) {
        const library = this.getLibrary();
        
        tags.forEach(tag => {
            library.tagStats[tag] = (library.tagStats[tag] || 0) + 1;
        });
    }

    /**
     * Get file format from path
     * @param {string} filePath - File path
     * @returns {string} File format (mp4, webm, etc.)
     */
    getFileFormat(filePath) {
        const ext = filePath.split('.').pop().toLowerCase();
        return ext;
    }

    /**
     * Sort results by field
     * @param {Array<Object>} results - Results to sort
     * @param {string} field - Field to sort by
     * @param {string} order - 'asc' or 'desc'
     * @returns {Array<Object>} Sorted results
     */
    sortResults(results, field, order = 'desc') {
        return results.sort((a, b) => {
            if (field === 'rating' || field === 'timesPlayed') {
                return order === 'desc' ? b[field] - a[field] : a[field] - b[field];
            } else if (field === 'lastPlayed' || field === 'addedDate') {
                const dateA = new Date(a[field]);
                const dateB = new Date(b[field]);
                return order === 'desc' ? dateB - dateA : dateA - dateB;
            } else {
                return 0;
            }
        });
    }

    /**
     * Save library to localStorage
     */
    saveLibrary() {
        try {
            localStorage.setItem('webGame-data', JSON.stringify(window.gameData));
        } catch (error) {
            console.error('Failed to save library:', error);
        }
    }
}

// Create global instance
window.libraryManager = new LibraryManager();
