/**
 * Cut Manager Module
 * Handles cut CRUD operations and display functionality
 */

import { showStatus } from './utils.js';

export class CutManager {
    constructor() {
        this.cuts = [];
        this.currentCut = null;
        this.currentCutLayer = null;
        this.map = null;
        this.isInitialized = false;
        
        // Add support for multiple cuts
        this.displayedCuts = new Map(); // Track multiple displayed cuts
        this.cutLayers = new Map(); // Track cut layers by ID
    }
    
    /**
     * Initialize the cut manager
     */
    async initialize(map) {
        this.map = map;
        this.isInitialized = true;
        
        // Load public cuts for display
        await this.loadPublicCuts();
        
        console.log('Cut manager initialized');
    }
    
    /**
     * Load all cuts (admin) or public cuts (users)
     */
    async loadCuts(adminMode = false) {
        try {
            const endpoint = adminMode ? '/api/cuts' : '/api/cuts/public';
            const response = await fetch(endpoint, {
                credentials: 'include'
            });
            
            if (!response.ok) {
                throw new Error(`Failed to load cuts: ${response.statusText}`);
            }
            
            const data = await response.json();
            this.cuts = data.list || [];
            
            console.log(`Loaded ${this.cuts.length} cuts`);
            return this.cuts;
        } catch (error) {
            console.error('Error loading cuts:', error);
            showStatus('Failed to load cuts', 'error');
            return [];
        }
    }
    
    /**
     * Load public cuts for map display
     */
    async loadPublicCuts() {
        return await this.loadCuts(false);
    }
    
    /**
     * Get single cut by ID
     */
    async getCut(id) {
        try {
            const response = await fetch(`/api/cuts/${id}`, {
                credentials: 'include'
            });
            
            if (!response.ok) {
                throw new Error(`Failed to load cut: ${response.statusText}`);
            }
            
            return await response.json();
        } catch (error) {
            console.error('Error loading cut:', error);
            showStatus('Failed to load cut', 'error');
            return null;
        }
    }
    
    /**
     * Create new cut
     */
    async createCut(cutData) {
        try {
            const response = await fetch('/api/cuts', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                credentials: 'include',
                body: JSON.stringify(cutData)
            });
            
            if (!response.ok) {
                const errorData = await response.json();
                throw new Error(errorData.error || `Failed to create cut: ${response.statusText}`);
            }
            
            const result = await response.json();
            showStatus('Cut created successfully', 'success');
            
            // Reload cuts
            await this.loadCuts(true);
            
            return result;
        } catch (error) {
            console.error('Error creating cut:', error);
            showStatus(error.message, 'error');
            return null;
        }
    }
    
    /**
     * Update existing cut
     */
    async updateCut(id, cutData) {
        try {
            const response = await fetch(`/api/cuts/${id}`, {
                method: 'PUT',
                headers: {
                    'Content-Type': 'application/json'
                },
                credentials: 'include',
                body: JSON.stringify(cutData)
            });
            
            if (!response.ok) {
                const errorData = await response.json();
                throw new Error(errorData.error || `Failed to update cut: ${response.statusText}`);
            }
            
            const result = await response.json();
            showStatus('Cut updated successfully', 'success');
            
            // Reload cuts
            await this.loadCuts(true);
            
            return result;
        } catch (error) {
            console.error('Error updating cut:', error);
            showStatus(error.message, 'error');
            return null;
        }
    }
    
    /**
     * Delete cut
     */
    async deleteCut(id) {
        try {
            const response = await fetch(`/api/cuts/${id}`, {
                method: 'DELETE',
                credentials: 'include'
            });
            
            if (!response.ok) {
                const errorData = await response.json();
                throw new Error(errorData.error || `Failed to delete cut: ${response.statusText}`);
            }
            
            showStatus('Cut deleted successfully', 'success');
            
            // If this was the currently displayed cut, hide it
            if (this.currentCut && this.currentCut.id === id) {
                this.hideCut();
            }
            
            // Reload cuts
            await this.loadCuts(true);
            
            return true;
        } catch (error) {
            console.error('Error deleting cut:', error);
            showStatus(error.message, 'error');
            return false;
        }
    }

    // ...existing code...

displayCut(cutData, autoDisplayed = false) {
    if (!this.map) {
        console.error('Map not initialized');
        return false;
    }
    
    // Normalize field names for consistent access
    const normalizedCut = {
        ...cutData,
        id: cutData.id || cutData.Id || cutData.ID,
        name: cutData.name || cutData.Name,
        description: cutData.description || cutData.Description,
        color: cutData.color || cutData.Color,
        opacity: cutData.opacity || cutData.Opacity,
        category: cutData.category || cutData.Category,
        geojson: cutData.geojson || cutData.GeoJSON || cutData['GeoJSON Data'],
        is_public: cutData.is_public || cutData['Public Visibility'],
        is_official: cutData.is_official || cutData['Official Cut'],
        autoDisplayed: autoDisplayed // Track if this was auto-displayed
    };
    
    // Check if already displayed
    if (this.cutLayers.has(normalizedCut.id)) {
        console.log(`Cut already displayed: ${normalizedCut.name}`);
        return true;
    }
    
    if (!normalizedCut.geojson) {
        console.error('Cut has no GeoJSON data');
        return false;
    }
    
    try {
        const geojsonData = typeof normalizedCut.geojson === 'string' ? 
            JSON.parse(normalizedCut.geojson) : normalizedCut.geojson;
        
        // Parse opacity value - ensure it's a number between 0 and 1
        let opacityValue = parseFloat(normalizedCut.opacity);
        
        // Validate opacity is within range
        if (isNaN(opacityValue) || opacityValue < 0 || opacityValue > 1) {
            opacityValue = 0.3; // Default fallback
            console.log(`Invalid opacity value (${normalizedCut.opacity}), using default: ${opacityValue}`);
        }
        
        const cutLayer = L.geoJSON(geojsonData, {
            style: {
                color: normalizedCut.color || '#3388ff',
                fillColor: normalizedCut.color || '#3388ff',
                fillOpacity: opacityValue,
                weight: 2,
                opacity: 0.8, // Stroke opacity - keeping this slightly transparent for better visibility
                className: 'cut-polygon'
            },
            // Add onEachFeature to apply styles to each individual feature
            onEachFeature: function (feature, layer) {
                // Apply styles directly to the layer to ensure they override CSS
                if (layer.setStyle) {
                    layer.setStyle({
                        fillOpacity: opacityValue,
                        color: normalizedCut.color || '#3388ff',
                        fillColor: normalizedCut.color || '#3388ff',
                        weight: 2,
                        opacity: 0.8
                    });
                }
                
                // Add cut-polygon class to the path element
                if (layer._path) {
                    layer._path.classList.add('cut-polygon');
                }
            }
        });
        
        // Add popup with cut info
        cutLayer.bindPopup(`
            <div class="cut-popup">
                <h3>${normalizedCut.name}</h3>
                ${normalizedCut.description ? `<p>${normalizedCut.description}</p>` : ''}
                ${normalizedCut.category ? `<p><strong>Category:</strong> ${normalizedCut.category}</p>` : ''}
                ${normalizedCut.is_official ? '<span class="badge official">Official Cut</span>' : ''}
            </div>
        `);
        
        cutLayer.addTo(this.map);
        
        // Ensure cut-polygon class is applied to all path elements after adding to map
        cutLayer.eachLayer(function(layer) {
            if (layer._path) {
                layer._path.classList.add('cut-polygon');
                // Force the fill-opacity style to ensure it overrides CSS
                layer._path.style.fillOpacity = opacityValue;
            }
        });
        
        // Store in both tracking systems
        this.cutLayers.set(normalizedCut.id, cutLayer);
        this.displayedCuts.set(normalizedCut.id, normalizedCut);
        
        // Update current cut reference (for legacy compatibility)
        this.currentCut = normalizedCut;
        this.currentCutLayer = cutLayer;
        
        console.log(`Displayed cut: ${normalizedCut.name} (ID: ${normalizedCut.id}) with opacity: ${opacityValue} (raw: ${normalizedCut.opacity})`);
        return true;
        
    } catch (error) {
        console.error('Error displaying cut:', error);
        return false;
    }
}

// ...existing code...

    hideCut() {
        this.hideAllCuts();
    }
    
    /**
     * Hide specific cut by ID
     */
    hideCutById(cutId) {
        // Try different ID formats to handle type mismatches
        let layer = this.cutLayers.get(cutId);
        let actualKey = cutId;
        
        if (!layer) {
            // Try as string
            const stringId = String(cutId);
            layer = this.cutLayers.get(stringId);
            if (layer) actualKey = stringId;
        }
        
        if (!layer) {
            // Try as number
            const numberId = Number(cutId);
            if (!isNaN(numberId)) {
                layer = this.cutLayers.get(numberId);
                if (layer) actualKey = numberId;
            }
        }
        
        if (layer && this.map) {
            this.map.removeLayer(layer);
            this.cutLayers.delete(actualKey);
            this.displayedCuts.delete(actualKey);
            console.log(`Successfully hidden cut ID: ${actualKey} (original: ${cutId})`);
            return true;
        }
        
        console.warn(`Failed to hide cut ID: ${cutId} - not found in layers`);
        return false;
    }
    
    /**
     * Hide all displayed cuts
     */
    hideAllCuts() {
        // Hide all cuts using the new system
        Array.from(this.cutLayers.keys()).forEach(cutId => {
            this.hideCutById(cutId);
        });
        
        // Legacy cleanup
        if (this.currentCutLayer && this.map) {
            this.map.removeLayer(this.currentCutLayer);
            this.currentCutLayer = null;
            this.currentCut = null;
        }
        console.log('All cuts hidden');
    }
    
    /**
     * Toggle cut visibility
     */
    toggleCut(cutData) {
        if (this.currentCut && this.currentCut.id === cutData.id) {
            this.hideCut();
            return false; // Hidden
        } else {
            this.displayCut(cutData);
            return true; // Shown
        }
    }
    
    /**
     * Get currently displayed cut
     */
    getCurrentCut() {
        return this.currentCut;
    }
    
    /**
     * Check if a cut is currently displayed
     */
    isCutDisplayed(cutId) {
        // Try different ID types to handle string/number mismatches
        const hasInMap = this.displayedCuts.has(cutId);
        const hasInMapAsString = this.displayedCuts.has(String(cutId));
        const hasInMapAsNumber = this.displayedCuts.has(Number(cutId));
        const currentCutMatch = this.currentCut && this.currentCut.id === cutId;
        
        return hasInMap || hasInMapAsString || hasInMapAsNumber || currentCutMatch;
    }
    
    /**
     * Get all displayed cuts
     */
    getDisplayedCuts() {
        return Array.from(this.displayedCuts.values());
    }
    
    /**
     * Get all available cuts
     */
    getCuts() {
        return this.cuts;
    }
    
    /**
     * Get cuts by category
     */
    getCutsByCategory(category) {
        return this.cuts.filter(cut => {
            const cutCategory = cut.category || cut.Category || 'Other';
            return cutCategory === category;
        });
    }
    
    /**
     * Search cuts by name
     */
    searchCuts(query) {
        if (!query) return this.cuts;
        
        const searchTerm = query.toLowerCase();
        return this.cuts.filter(cut => {
            // Handle different possible field names
            const name = cut.name || cut.Name || '';
            const description = cut.description || cut.Description || '';
            
            return name.toLowerCase().includes(searchTerm) ||
                   description.toLowerCase().includes(searchTerm);
        });
    }
    
    /**
     * Export cuts as JSON
     */
    exportCuts(cutsToExport = null) {
        const cuts = cutsToExport || this.cuts;
        const exportData = {
            version: '1.0',
            timestamp: new Date().toISOString(),
            cuts: cuts.map(cut => ({
                name: cut.name,
                description: cut.description,
                color: cut.color,
                opacity: cut.opacity,
                category: cut.category,
                is_official: cut.is_official,
                geojson: cut.geojson,
                bounds: cut.bounds
            }))
        };
        
        return JSON.stringify(exportData, null, 2);
    }
    
    /**
     * Validate cut data for import
     */
    validateCutData(cutData) {
        const errors = [];
        
        if (!cutData.name || typeof cutData.name !== 'string') {
            errors.push('Name is required and must be a string');
        }
        
        if (!cutData.geojson) {
            errors.push('GeoJSON data is required');
        } else {
            try {
                const geojson = JSON.parse(cutData.geojson);
                if (!geojson.type || !['Polygon', 'MultiPolygon'].includes(geojson.type)) {
                    errors.push('GeoJSON must be a Polygon or MultiPolygon');
                }
            } catch (e) {
                errors.push('Invalid GeoJSON format');
            }
        }
        
        if (cutData.opacity !== undefined) {
            const opacity = parseFloat(cutData.opacity);
            if (isNaN(opacity) || opacity < 0 || opacity > 1) {
                errors.push('Opacity must be a number between 0 and 1');
            }
        }
        
        return errors;
    }
    
    /**
     * Get cut statistics
     */
    getStatistics() {
        const stats = {
            total: this.cuts.length,
            public: this.cuts.filter(cut => {
                const isPublic = cut.is_public || cut['Public Visibility'];
                return isPublic === true || isPublic === 1 || isPublic === '1';
            }).length,
            private: this.cuts.filter(cut => {
                const isPublic = cut.is_public || cut['Public Visibility'];
                return !(isPublic === true || isPublic === 1 || isPublic === '1');
            }).length,
            official: this.cuts.filter(cut => {
                const isOfficial = cut.is_official || cut['Official Cut'];
                return isOfficial === true || isOfficial === 1 || isOfficial === '1';
            }).length,
            byCategory: {}
        };
        
        // Count by category
        this.cuts.forEach(cut => {
            const category = cut.category || cut.Category || 'Uncategorized';
            stats.byCategory[category] = (stats.byCategory[category] || 0) + 1;
        });
        
        return stats;
    }
    
    /**
     * Hide all displayed cuts
     */
    /**
     * Get displayed cut data by ID
     */
    getDisplayedCut(cutId) {
        return this.displayedCuts.get(cutId);
    }
}

// Create global instance
export const cutManager = new CutManager();
