import React, { useState, useEffect, useRef } from 'react';
import { useNavigate } from 'react-router-dom';
import { MapMarker, MapLayer, MapMetadata } from '../types';
import { authService } from '../services/AuthService';
import { DiscordUser } from '../types';

const WorldMap: React.FC = () => {
    const navigate = useNavigate();
    const [markers, setMarkers] = useState<MapMarker[]>([]);
    const [layers, setLayers] = useState<MapLayer[]>([]);
    const [mapMetadata, setMapMetadata] = useState<MapMetadata | null>(null);
    const [user, setUser] = useState<DiscordUser | null>(null);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState<string | null>(null);
    
    // Map interaction state
    const [isDragging, setIsDragging] = useState(false);
    const [dragStart, setDragStart] = useState({ x: 0, y: 0 });
    const [mapPosition, setMapPosition] = useState({ x: 0, y: 0 });
    const [scale, setScale] = useState(1);
    const [showAdminPanel, setShowAdminPanel] = useState(false);
    const [selectedMarker, setSelectedMarker] = useState<MapMarker | null>(null);
    const [isAddingMarker, setIsAddingMarker] = useState(false);
    const [showOriginPin, setShowOriginPin] = useState(false);
    
    // Map assembly state
    const [isAssembling, setIsAssembling] = useState(false);
    const [assemblyProgress, setAssemblyProgress] = useState<string>('');

    const mapContainerRef = useRef<HTMLDivElement>(null);
    const mapImageRef = useRef<HTMLImageElement>(null);

    // Subscribe to auth changes
    useEffect(() => {
        const unsub = authService.subscribe((currentUser) => {
            setUser(currentUser);
        });
        return unsub;
    }, []);

    // Load map data
    useEffect(() => {
        const loadData = async () => {
            try {
                setLoading(true);
                setError(null);

                // Load map metadata (may not exist if map hasn't been assembled)
                let metadata = null;
                try {
                    const metadataResponse = await fetch('/api/map/metadata');
                    if (metadataResponse.ok) {
                        metadata = await metadataResponse.json();
                        setMapMetadata(metadata);
                    } else {
                        console.log('Map metadata not found - map may not be assembled yet');
                    }
                } catch (metaErr) {
                    console.log('Map metadata not available:', metaErr);
                }

                // Load layers
                const layersResponse = await fetch('/api/map/layers');
                if (!layersResponse.ok) {
                    console.error('Layers API error:', layersResponse.status, layersResponse.statusText);
                    throw new Error(`Fehler beim Laden der Layer: ${layersResponse.status}`);
                }
                let layerData;
                try {
                    layerData = await layersResponse.json();
                } catch (jsonErr) {
                    console.error('Layers JSON parse error:', jsonErr);
                    throw new Error('Fehler beim Verarbeiten der Layer-Daten');
                }
                setLayers(layerData);

                // Load markers
                const markersResponse = await fetch('/api/map/markers/public');
                if (!markersResponse.ok) {
                    console.error('Markers API error:', markersResponse.status, markersResponse.statusText);
                    throw new Error(`Fehler beim Laden der Marker: ${markersResponse.status}`);
                }
                let markerData;
                try {
                    markerData = await markersResponse.json();
                } catch (jsonErr) {
                    console.error('Markers JSON parse error:', jsonErr);
                    throw new Error('Fehler beim Verarbeiten der Marker-Daten');
                }
                setMarkers(markerData);

            } catch (err) {
                console.error('Error loading map data:', err);
                setError(err instanceof Error ? err.message : 'Unbekannter Fehler');
            } finally {
                setLoading(false);
            }
        };

        loadData();
    }, []);

    // Map interaction handlers
    const handleMouseDown = (e: React.MouseEvent) => {
        if (!mapContainerRef.current) return;
        
        setIsDragging(true);
        setDragStart({
            x: e.clientX - mapPosition.x,
            y: e.clientY - mapPosition.y
        });
    };

    const handleMouseMove = (e: MouseEvent) => {
        if (!isDragging || !mapContainerRef.current) return;

        const newX = e.clientX - dragStart.x;
        const newY = e.clientY - dragStart.y;

        setMapPosition({ x: newX, y: newY });
    };

    const handleMouseUp = () => {
        setIsDragging(false);
    };

    const handleWheel = (e: WheelEvent) => {
        if (!mapContainerRef.current) return;

        e.preventDefault();
        
        const delta = e.deltaY > 0 ? 0.9 : 1.1;
        const newScale = Math.max(0.5, Math.min(3, scale * delta));
        
        // Adjust position to zoom towards mouse cursor
        const mouseX = e.clientX;
        const mouseY = e.clientY;
        const containerRect = mapContainerRef.current.getBoundingClientRect();
        
        const containerCenterX = containerRect.width / 2;
        const containerCenterY = containerRect.height / 2;
        
        const currentScale = scale;
        const newScaleValue = newScale;
        
        const offsetX = (mouseX - containerCenterX) * (1 - newScaleValue / currentScale);
        const offsetY = (mouseY - containerCenterY) * (1 - newScaleValue / currentScale);

        setMapPosition({
            x: mapPosition.x - offsetX,
            y: mapPosition.y - offsetY
        });
        
        setScale(newScale);
    };

    useEffect(() => {
        if (isDragging) {
            document.addEventListener('mousemove', handleMouseMove);
            document.addEventListener('mouseup', handleMouseUp);
            document.addEventListener('mouseleave', handleMouseUp);
        } else {
            document.removeEventListener('mousemove', handleMouseMove);
            document.removeEventListener('mouseup', handleMouseUp);
            document.removeEventListener('mouseleave', handleMouseUp);
        }

        return () => {
            document.removeEventListener('mousemove', handleMouseMove);
            document.removeEventListener('mouseup', handleMouseUp);
            document.removeEventListener('mouseleave', handleMouseUp);
        };
    }, [isDragging, dragStart.x, dragStart.y, mapPosition.x, mapPosition.y]);

    useEffect(() => {
        const container = mapContainerRef.current;
        if (container) {
            container.addEventListener('wheel', handleWheel, { passive: false });
        }

        return () => {
            if (container) {
                container.removeEventListener('wheel', handleWheel);
            }
        };
    }, [scale, mapPosition.x, mapPosition.y]);

    // Handle marker clicks
    const handleMarkerClick = (marker: MapMarker) => {
        setSelectedMarker(marker);
        
        // Navigate to linked entity if exists
        if (marker.linked_entity_type && marker.linked_entity_id) {
            if (marker.linked_entity_type === 'organization' || marker.linked_entity_type === 'city') {
                navigate(`/cities/${marker.linked_entity_id}`);
            }
        }
    };

    // Admin functions
    const handleAddMarker = (e: React.MouseEvent) => {
        if (!user?.isAdmin || !mapContainerRef.current || !mapImageRef.current) return;

        const rect = mapContainerRef.current.getBoundingClientRect();
        const imageRect = mapImageRef.current.getBoundingClientRect();
        
        // Calculate relative position within the image
        const relativeX = e.clientX - imageRect.left;
        const relativeY = e.clientY - imageRect.top;
        
        // Convert to percentage
        const percentX = (relativeX / imageRect.width) * 100;
        const percentY = (relativeY / imageRect.height) * 100;

        // Convert percentage to Minecraft coordinates using metadata
        if (mapMetadata) {
            const pixelX = (percentX / 100) * mapMetadata.width;
            const pixelY = (percentY / 100) * mapMetadata.height;
            
            // Convert back to Minecraft coordinates
            const minecraftX = pixelX - mapMetadata.offsetX;
            const minecraftZ = pixelY - mapMetadata.offsetZ;

            // Create new marker
            const newMarker = {
                name: 'Neuer Marker',
                type: 'poi' as const,
                x_coord: Math.round(minecraftX),
                z_coord: Math.round(minecraftZ),
                description: '',
                linked_entity_type: null,
                linked_entity_id: null,
                icon_type: 'flag',
                color: '#2563eb',
                is_public: 1
            };

            // Send to server
            fetch('/api/map/markers', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify(newMarker)
            })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    // Reload markers
                    return fetch('/api/map/markers/public');
                } else {
                    throw new Error(data.message || 'Fehler beim Erstellen des Markers');
                }
            })
            .then(response => response.json())
            .then(markerData => {
                setMarkers(markerData);
            })
            .catch(err => {
                console.error('Error creating marker:', err);
                setError(err.message);
            });
        }
    };

    const handleDeleteMarker = (markerId: string) => {
        if (!user?.isAdmin) return;

        fetch(`/api/map/markers/${markerId}`, {
            method: 'DELETE'
        })
        .then(response => response.json())
        .then(data => {
            if (data.success) {
                setMarkers(markers.filter(m => m.id !== markerId));
                setSelectedMarker(null);
            } else {
                throw new Error(data.message || 'Fehler beim Löschen des Markers');
            }
        })
        .catch(err => {
            console.error('Error deleting marker:', err);
            setError(err.message);
        });
    };

    // Map assembly function with progress tracking
    const handleAssembleMap = async () => {
        if (!user?.isAdmin || isAssembling) return;

        setIsAssembling(true);
        setAssemblyProgress('Starte Karten-Zusammenstellung...');

        try {
            setAssemblyProgress('Überprüfe Kacheln...');
            
            // First check if tiles exist
            const tilesResponse = await fetch('/api/map/metadata');
            if (!tilesResponse.ok) {
                setAssemblyProgress('Keine Kacheln gefunden. Bitte stellen Sie sicher, dass PNG-Dateien im Ordner backend/uploads/map/ vorhanden sind.');
                setTimeout(() => {
                    setIsAssembling(false);
                    setAssemblyProgress('');
                }, 3000);
                return;
            }

            setAssemblyProgress('Starte Karten-Zusammenstellung...');
            
            const response = await fetch('/api/map/assemble', { 
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                }
            });

            if (!response.ok) {
                const errorData = await response.json().catch(() => ({}));
                const errorMessage = errorData.error || `Server-Fehler: ${response.status}`;
                const errorDetails = errorData.details || '';
                const errorStack = errorData.stack || '';
                
                console.error('Map assembly error details:', {
                    status: response.status,
                    error: errorMessage,
                    details: errorDetails,
                    stack: errorStack
                });
                
                setAssemblyProgress(`Fehler: ${errorMessage}`);
                
                // Show detailed error in alert for debugging
                if (errorDetails) {
                    alert(`Karten-Zusammenstellung fehlgeschlagen:\n\nFehler: ${errorMessage}\n\nDetails: ${errorDetails}\n\nStack: ${errorStack}`);
                } else {
                    alert(`Karten-Zusammenstellung fehlgeschlagen:\n\nFehler: ${errorMessage}`);
                }
                
                setTimeout(() => {
                    setIsAssembling(false);
                    setAssemblyProgress('');
                }, 5000);
                return;
            }

            const result = await response.json();
            
            if (result.success) {
                setAssemblyProgress('Karte erfolgreich zusammengestellt!');
                
                // Reload map metadata and markers
                setTimeout(async () => {
                    try {
                        const metadataResponse = await fetch('/api/map/metadata');
                        if (metadataResponse.ok) {
                            const metadata = await metadataResponse.json();
                            setMapMetadata(metadata);
                        }
                        
                        const markersResponse = await fetch('/api/map/markers/public');
                        if (markersResponse.ok) {
                            const markerData = await markersResponse.json();
                            setMarkers(markerData);
                        }
                        
                        setIsAssembling(false);
                        setAssemblyProgress('');
                        alert('Weltkarte wurde erfolgreich zusammengestellt!');
                    } catch (err) {
                        console.error('Error reloading map data:', err);
                        setIsAssembling(false);
                        setAssemblyProgress('');
                    }
                }, 1000);
            } else {
                throw new Error(result.message || 'Fehler beim Zusammensetzen der Karte');
            }
        } catch (err) {
            console.error('Error assembling map:', err);
            setAssemblyProgress(`Fehler: ${err.message}`);
            setTimeout(() => {
                setIsAssembling(false);
                setAssemblyProgress('');
            }, 3000);
        }
    };

    if (loading) {
        return (
            <div className="flex items-center justify-center h-screen">
                <div className="text-textMuted">Lade Weltkarte...</div>
            </div>
        );
    }

    if (error) {
        return (
            <div className="flex items-center justify-center h-screen">
                <div className="text-red-500">Fehler: {error}</div>
            </div>
        );
    }

    return (
        <div className="flex h-screen bg-bgPrimary">
            {/* Sidebar */}
            <div className="w-80 bg-bgSecondary border-r border-border p-4 overflow-y-auto">
                <div className="flex items-center justify-between mb-4">
                    <h1 className="text-xl font-bold text-textPrimary">Weltkarte</h1>
                    {user?.isAdmin && (
                        <button
                            onClick={() => setShowAdminPanel(!showAdminPanel)}
                            className="px-3 py-1 bg-accentInfo text-white rounded hover:bg-accentInfo/90"
                        >
                            Admin
                        </button>
                    )}
                </div>

                {/* Map Controls */}
                <div className="mb-4 p-3 bg-bgPrimary rounded">
                    <div className="flex items-center justify-between mb-2">
                        <span className="text-sm text-textMuted">Zoom</span>
                        <div className="flex gap-2">
                            <button
                                onClick={() => setScale(Math.max(0.1, scale - 0.1))}
                                className="px-2 py-1 bg-bgSecondary rounded hover:bg-bgTertiary"
                            >
                                -
                            </button>
                            <button
                                onClick={() => setScale(Math.min(10, scale + 0.1))}
                                className="px-2 py-1 bg-bgSecondary rounded hover:bg-bgTertiary"
                            >
                                +
                            </button>
                        </div>
                    </div>
                    <div className="text-xs text-textMuted">
                        Mausrad zum Zoomen, Klicken zum Verschieben
                    </div>
                </div>

                {/* Origin Controls */}
                <div className="mb-4 p-3 bg-bgPrimary rounded">
                    <div className="flex items-center justify-between mb-2">
                        <span className="text-sm text-textMuted">Origin (0,0)</span>
                        <button
                            onClick={() => {
                                if (mapMetadata && mapContainerRef.current) {
                                    const container = mapContainerRef.current;
                                    const containerRect = container.getBoundingClientRect();
                                    
                                    // Calculate where the origin (0,0) is in the map image pixels
                                    const originXInPixels = mapMetadata.offsetX;
                                    const originYInPixels = mapMetadata.offsetZ;
                                    
                                    // Calculate the center of the viewport
                                    const viewportCenterX = containerRect.width / 2;
                                    const viewportCenterY = containerRect.height / 2;
                                    
                                    // Position the map so that origin (0,0) is in the center of the viewport
                                    const mapX = viewportCenterX - originXInPixels * scale;
                                    const mapY = viewportCenterY - originYInPixels * scale;
                                    
                                    setMapPosition({
                                        x: mapX,
                                        y: mapY
                                    });
                                }
                            }}
                            className={`px-3 py-1 rounded text-sm ${
                                showOriginPin ? 'bg-accentInfo text-white' : 'bg-bgSecondary text-textPrimary'
                            }`}
                        >
                            {showOriginPin ? 'Origin zentrieren' : 'Origin zentrieren'}
                        </button>
                    </div>
                    <div className="text-xs text-textMuted">
                        Positioniert den Ursprung (0,0) in der Mitte der Karte
                    </div>
                </div>

                {/* Layers */}
                <div className="mb-4">
                    <h3 className="text-sm font-semibold text-textPrimary mb-2">Layer</h3>
                    {layers.map(layer => (
                        <label key={layer.id} className="flex items-center gap-2 text-sm text-textPrimary mb-1">
                            <input type="checkbox" defaultChecked={layer.is_active} />
                            {layer.name}
                        </label>
                    ))}
                </div>

                {/* Markers List */}
                <div>
                    <h3 className="text-sm font-semibold text-textPrimary mb-2">Orte</h3>
                    {markers.length === 0 ? (
                        <p className="text-textMuted text-sm">Keine Marker gefunden</p>
                    ) : (
                        markers.map(marker => (
                            <div
                                key={marker.id}
                                onClick={() => handleMarkerClick(marker)}
                                className={`p-2 rounded mb-2 cursor-pointer hover:bg-bgPrimary ${
                                    selectedMarker?.id === marker.id ? 'bg-bgPrimary' : ''
                                }`}
                            >
                                <div className="flex items-center gap-2">
                                    <div
                                        className="w-3 h-3 rounded-full"
                                        style={{ backgroundColor: marker.color }}
                                    ></div>
                                    <div>
                                        <div className="font-medium text-textPrimary">{marker.name}</div>
                                        <div className="text-xs text-textMuted">
                                            {marker.type} • {marker.x_coord}, {marker.z_coord}
                                        </div>
                                    </div>
                                </div>
                                {marker.description && (
                                    <p className="text-xs text-textMuted mt-1">{marker.description}</p>
                                )}
                            </div>
                        ))
                    )}
                </div>
            </div>

            {/* Map Container */}
            <div 
                ref={mapContainerRef}
                className="flex-1 relative overflow-hidden cursor-grab active:cursor-grabbing"
                onMouseDown={user?.isAdmin && isAddingMarker ? handleAddMarker : handleMouseDown}
            >
                {mapMetadata ? (
                    <img
                        ref={mapImageRef}
                        src="/api/map/world-map"
                        alt="Weltkarte"
                        className="absolute"
                        style={{
                            left: mapPosition.x,
                            top: mapPosition.y,
                            transform: `scale(${scale})`,
                            transformOrigin: 'top left',
                            cursor: 'grab'
                        }}
                        onLoad={() => {
                            // Center the map and position origin (0,0) in the center
                            if (mapImageRef.current && mapContainerRef.current && mapMetadata) {
                                const img = mapImageRef.current;
                                const container = mapContainerRef.current;
                                const containerRect = container.getBoundingClientRect();
                                
                                // Calculate where the origin (0,0) is in the map image pixels
                                const originXInPixels = mapMetadata.offsetX;
                                const originYInPixels = mapMetadata.offsetZ;
                                
                                // Calculate the center of the viewport
                                const viewportCenterX = containerRect.width / 2;
                                const viewportCenterY = containerRect.height / 2;
                                
                                // Position the map so that origin (0,0) is in the center of the viewport
                                // We need to position the image so that the origin pixel is at the viewport center
                                const mapX = viewportCenterX - originXInPixels;
                                const mapY = viewportCenterY - originYInPixels;
                                
                                setMapPosition({
                                    x: mapX,
                                    y: mapY
                                });
                            }
                        }}
                    />
                ) : (
                    <div className="absolute inset-0 flex items-center justify-center">
                        <div className="text-center p-8 bg-bgSecondary border border-border rounded-xl">
                            <div className="text-6xl mb-4">🗺️</div>
                            <h3 className="text-xl font-bold text-textPrimary mb-2">Weltkarte nicht verfügbar</h3>
                            <p className="text-textMuted mb-4">
                                Die Weltkarte muss zuerst im Admin-Bereich zusammengestellt werden.
                            </p>
                            {user?.isAdmin ? (
                                <div className="space-y-2">
                                    <p className="text-sm text-textMuted">
                                        1. Klicken Sie auf "Admin" oben rechts
                                    </p>
                                    <p className="text-sm text-textMuted">
                                        2. Klicken Sie auf "Karte neu zusammensetzen"
                                    </p>
                                    <p className="text-sm text-textMuted">
                                        3. Warten Sie, bis die Verarbeitung abgeschlossen ist
                                    </p>
                                </div>
                            ) : (
                                <p className="text-sm text-textMuted">
                                    Bitte wenden Sie sich an einen Administrator, um die Weltkarte zu erstellen.
                                </p>
                            )}
                        </div>
                    </div>
                )}

                {/* Markers Overlay */}
                {markers.map(marker => (
                    <div
                        key={marker.id}
                        className="absolute w-6 h-6 cursor-pointer transform -translate-x-3 -translate-y-3 hover:scale-125 transition-transform"
                        style={{
                            left: `${marker.coordinates?.x || 0}%`,
                            top: `${marker.coordinates?.y || 0}%`,
                            zIndex: 10
                        }}
                        onClick={() => handleMarkerClick(marker)}
                        title={marker.name}
                    >
                        <div
                            className="w-full h-full rounded-full border-2 border-white shadow-lg"
                            style={{ backgroundColor: marker.color }}
                        ></div>
                        <div className="absolute -bottom-6 left-1/2 transform -translate-x-1/2 text-xs bg-black bg-opacity-75 text-white px-2 py-1 rounded whitespace-nowrap">
                            {marker.name}
                        </div>
                    </div>
                ))}

                {/* Admin Panel */}
                {showAdminPanel && user?.isAdmin && (
                    <div className="absolute top-4 right-4 bg-bgSecondary border border-border p-4 rounded shadow-lg max-w-sm">
                        <h3 className="text-sm font-semibold text-textPrimary mb-2">Admin-Tools</h3>
                        
                        {/* Map Assembly Section */}
                        <div className="mb-3 p-3 bg-bgPrimary rounded">
                            <h4 className="text-xs font-semibold text-textPrimary mb-2">Karten-Zusammenstellung</h4>
                            {isAssembling ? (
                                <div className="space-y-2">
                                    <div className="flex items-center gap-2">
                                        <div className="w-4 h-4 border-2 border-accentSuccess border-t-transparent rounded-full animate-spin"></div>
                                        <span className="text-sm text-textPrimary">{assemblyProgress}</span>
                                    </div>
                                    <div className="text-xs text-textMuted">
                                        Bitte warten Sie, bis der Vorgang abgeschlossen ist...
                                    </div>
                                </div>
                            ) : (
                                <div className="space-y-2">
                                    <button
                                        onClick={handleAssembleMap}
                                        disabled={isAssembling}
                                        className="w-full px-3 py-2 bg-accentSuccess text-white rounded text-sm hover:bg-accentSuccess/90 disabled:opacity-50 disabled:cursor-not-allowed"
                                    >
                                        {mapMetadata ? 'Karte neu zusammensetzen' : 'Karte zusammensetzen'}
                                    </button>
                                    <div className="text-xs text-textMuted">
                                        {mapMetadata 
                                            ? 'Aktualisiert die bestehende Weltkarte mit neuen Kacheln'
                                            : 'Erstellt die Weltkarte aus den PNG-Kacheln im Upload-Ordner'
                                        }
                                    </div>
                                </div>
                            )}
                        </div>

                        {/* Marker Management Section */}
                        <div className="space-y-2">
                            <button
                                onClick={() => setIsAddingMarker(!isAddingMarker)}
                                className={`w-full px-3 py-2 rounded text-sm ${
                                    isAddingMarker ? 'bg-accentInfo text-white' : 'bg-bgPrimary text-textPrimary'
                                }`}
                            >
                                {isAddingMarker ? 'Marker hinzufügen (aktiv)' : 'Marker hinzufügen'}
                            </button>
                            <div className="text-xs text-textMuted">
                                Klicken Sie auf die Karte, um neue Marker hinzuzufügen
                            </div>
                        </div>
                    </div>
                )}

                {/* Selected Marker Info */}
                {selectedMarker && (
                    <div className="absolute bottom-4 left-4 bg-bgSecondary border border-border p-4 rounded shadow-lg max-w-sm">
                        <div className="flex items-center justify-between mb-2">
                            <h3 className="font-semibold text-textPrimary">{selectedMarker.name}</h3>
                            <button
                                onClick={() => setSelectedMarker(null)}
                                className="text-textMuted hover:text-textPrimary"
                            >
                                ✕
                            </button>
                        </div>
                        <div className="text-sm text-textMuted mb-2">
                            <div>{selectedMarker.type}</div>
                            <div>Koordinaten: {selectedMarker.x_coord}, {selectedMarker.z_coord}</div>
                        </div>
                        {selectedMarker.description && (
                            <p className="text-sm text-textPrimary mb-3">{selectedMarker.description}</p>
                        )}
                        {user?.isAdmin && (
                            <div className="flex gap-2">
                                <button
                                    onClick={() => navigate(`/admin/edit-marker/${selectedMarker.id}`)}
                                    className="px-3 py-1 bg-accentInfo text-white rounded text-sm hover:bg-accentInfo/90"
                                >
                                    Bearbeiten
                                </button>
                                <button
                                    onClick={() => handleDeleteMarker(selectedMarker.id)}
                                    className="px-3 py-1 bg-red-500 text-white rounded text-sm hover:bg-red-600"
                                >
                                    Löschen
                                </button>
                            </div>
                        )}
                    </div>
                )}
            </div>
        </div>
    );
};

export default WorldMap;
