using UnityEngine;
using UnityEngine.UIElements;
using System.Collections.Generic;

[System.Serializable]
public class MapLocation
{
    public string locationName;
    public LocationType locationType;
    public Vector2 mapPosition;
    public bool isDiscovered = false;
    public bool showName = true;
}

public enum LocationType
{
    Town,
    Village,
    Forest,
    Mountain,
    River,
    Cave,
    Ruins,
    Dungeon,
    Landmark
}

public class MapLocationNaming : MonoBehaviour
{
    [Header("Location Configuration")]
    public List<MapLocation> predefinedLocations = new List<MapLocation>();

    [Header("UI References")]
    public UIDocument mapUI;

    [Header("Visual Settings")]
    public Font locationFont;
    public Color townColor = Color.white;
    public Color villageColor = Color.cyan;
    public Color forestColor = Color.green;
    public Color mountainColor = Color.gray;
    public Color landmarkColor = Color.yellow;

    private VisualElement mapContainer;
    private List<Label> locationLabels = new List<Label>();

    // Conversion settings (adjust based on your map scale)
    [Header("Map Conversion")]
    public Vector2 mapSize = new Vector2(1920, 1080); // UI map size
    public Vector2 worldSize = new Vector2(100, 100); // World coordinates range
    public Vector2 mapOffset = Vector2.zero; // Offset for map positioning

    void Start()
    {
        InitializeLocationNaming();
        CreatePredefinedLocations();
        DisplayLocationNames();
    }

    private void InitializeLocationNaming()
    {
        if (mapUI == null)
            mapUI = GetComponent<UIDocument>();

        if (mapUI != null)
        {
            mapContainer = mapUI.rootVisualElement.Q<VisualElement>("map-container");
            if (mapContainer == null)
            {
                // Create map container if it doesn't exist
                mapContainer = new VisualElement();
                mapContainer.name = "map-container";
                mapContainer.style.position = Position.Absolute;
                mapContainer.style.width = Length.Percent(100);
                mapContainer.style.height = Length.Percent(100);
                mapUI.rootVisualElement.Add(mapContainer);
            }
        }
    }

    private void CreatePredefinedLocations()
    {
        if (predefinedLocations.Count == 0)
        {
            // Create some default locations - adjust coordinates based on your map
            predefinedLocations.AddRange(new MapLocation[]
            {
                // Towns
                new MapLocation { locationName = "Hearthhaven", locationType = LocationType.Town, mapPosition = new Vector2(50, 40), isDiscovered = true },
                new MapLocation { locationName = "Irongate", locationType = LocationType.Town, mapPosition = new Vector2(75, 60), isDiscovered = true },
                new MapLocation { locationName = "Goldmeadow", locationType = LocationType.Town, mapPosition = new Vector2(30, 70), isDiscovered = false },
                
                // Villages
                new MapLocation { locationName = "Millbrook", locationType = LocationType.Village, mapPosition = new Vector2(40, 50), isDiscovered = true },
                new MapLocation { locationName = "Stonehaven", locationType = LocationType.Village, mapPosition = new Vector2(65, 35), isDiscovered = false },
                new MapLocation { locationName = "Riverside", locationType = LocationType.Village, mapPosition = new Vector2(25, 55), isDiscovered = true },
                
                // Forests
                new MapLocation { locationName = "Whispering Woods", locationType = LocationType.Forest, mapPosition = new Vector2(35, 30), isDiscovered = true },
                new MapLocation { locationName = "Darkwood Forest", locationType = LocationType.Forest, mapPosition = new Vector2(80, 25), isDiscovered = false },
                new MapLocation { locationName = "Emerald Grove", locationType = LocationType.Forest, mapPosition = new Vector2(20, 40), isDiscovered = true },
                
                // Mountains
                new MapLocation { locationName = "Frostpeak Mountains", locationType = LocationType.Mountain, mapPosition = new Vector2(85, 80), isDiscovered = true },
                new MapLocation { locationName = "Dragon's Spine", locationType = LocationType.Mountain, mapPosition = new Vector2(90, 50), isDiscovered = false },
                new MapLocation { locationName = "Stormhaven Peaks", locationType = LocationType.Mountain, mapPosition = new Vector2(15, 80), isDiscovered = true },
                
                // Landmarks
                new MapLocation { locationName = "Ancient Ruins", locationType = LocationType.Ruins, mapPosition = new Vector2(55, 25), isDiscovered = false },
                new MapLocation { locationName = "Crystal Cave", locationType = LocationType.Cave, mapPosition = new Vector2(70, 75), isDiscovered = false },
                new MapLocation { locationName = "The Great Bridge", locationType = LocationType.Landmark, mapPosition = new Vector2(45, 65), isDiscovered = true }
            });
        }
    }

    private void DisplayLocationNames()
    {
        ClearLocationLabels();

        foreach (var location in predefinedLocations)
        {
            if (location.showName && (location.isDiscovered || ShouldShowUndiscovered(location)))
            {
                CreateLocationLabel(location);
            }
        }
    }

    private bool ShouldShowUndiscovered(MapLocation location)
    {
        // Show town/village names even if not discovered
        return location.locationType == LocationType.Town || location.locationType == LocationType.Village;
    }

    private void CreateLocationLabel(MapLocation location)
    {
        var label = new Label(location.locationName);
        label.AddToClassList("location-label");
        label.AddToClassList($"location-{location.locationType.ToString().ToLower()}");

        // Convert world position to UI position
        Vector2 uiPosition = WorldToUIPosition(location.mapPosition);

        // Position the label
        label.style.position = Position.Absolute;
        label.style.left = uiPosition.x;
        label.style.top = uiPosition.y;

        // Set color based on location type
        Color labelColor = GetLocationColor(location);
        label.style.color = labelColor;

        // Set opacity based on discovery status
        if (!location.isDiscovered)
        {
            label.style.opacity = 0.6f;
            label.AddToClassList("undiscovered");
        }

        // Add tooltip/hover effects
        label.RegisterCallback<MouseEnterEvent>(evt => OnLocationHover(location, label));
        label.RegisterCallback<MouseLeaveEvent>(evt => OnLocationHoverEnd(location, label));
        label.RegisterCallback<ClickEvent>(evt => OnLocationClick(location));

        mapContainer.Add(label);
        locationLabels.Add(label);
    }

    private Vector2 WorldToUIPosition(Vector2 worldPosition)
    {
        // Convert world coordinates to UI coordinates
        float xPercent = (worldPosition.x + mapOffset.x) / worldSize.x;
        float yPercent = (worldPosition.y + mapOffset.y) / worldSize.y;

        float uiX = xPercent * mapSize.x;
        float uiY = yPercent * mapSize.y;

        return new Vector2(uiX, uiY);
    }

    private Color GetLocationColor(MapLocation location)
    {
        switch (location.locationType)
        {
            case LocationType.Town:
                return townColor;
            case LocationType.Village:
                return villageColor;
            case LocationType.Forest:
                return forestColor;
            case LocationType.Mountain:
                return mountainColor;
            case LocationType.Landmark:
            case LocationType.Ruins:
            case LocationType.Cave:
                return landmarkColor;
            default:
                return Color.white;
        }
    }

    private void ClearLocationLabels()
    {
        foreach (var label in locationLabels)
        {
            if (label.parent != null)
                label.parent.Remove(label);
        }
        locationLabels.Clear();
    }

    #region Event Handlers

    private void OnLocationHover(MapLocation location, VisualElement label)
    {
        // Increase size slightly and add glow effect
        label.style.scale = new Scale(Vector3.one * 1.1f);
        label.AddToClassList("location-hover");

        // Show location info tooltip if desired
        ShowLocationTooltip(location, label);
    }

    private void OnLocationHoverEnd(MapLocation location, VisualElement label)
    {
        label.style.scale = new Scale(Vector3.one);
        label.RemoveFromClassList("location-hover");

        HideLocationTooltip();
    }

    private void OnLocationClick(MapLocation location)
    {
        Debug.Log($"Clicked on {location.locationName} ({location.locationType})");

        // Mark as discovered if not already
        if (!location.isDiscovered)
        {
            location.isDiscovered = true;
            RefreshLocationDisplay(location);
        }

        // Handle location-specific actions
        switch (location.locationType)
        {
            case LocationType.Town:
            case LocationType.Village:
                // Set as travel destination or open location details
                SetTravelDestination(location);
                break;

            case LocationType.Forest:
            case LocationType.Mountain:
                // Show exploration options
                ShowExplorationOptions(location);
                break;

            case LocationType.Ruins:
            case LocationType.Cave:
            case LocationType.Dungeon:
                // Show dungeon/exploration entry
                ShowDungeonEntry(location);
                break;
        }
    }

    #endregion

    #region Location Actions

    private void SetTravelDestination(MapLocation location)
    {
        Debug.Log($"Setting travel destination to {location.locationName}");

        // Find travel system and set destination
        // var travelSystem = FindFirstObjectByType<TravelSystem>();
        // if (travelSystem != null)
        // {
        //     travelSystem.SetDestination(location.mapPosition, location.locationName);
        // }

        // Show confirmation message
        ShowLocationMessage($"Travel destination set to {location.locationName}", Color.green);
    }

    private void ShowExplorationOptions(MapLocation location)
    {
        Debug.Log($"Exploring {location.locationName}");
        ShowLocationMessage($"Exploring {location.locationName}...", Color.cyan);

        // Could trigger random encounters, resource gathering, etc.
    }

    private void ShowDungeonEntry(MapLocation location)
    {
        Debug.Log($"Entering {location.locationName}");
        ShowLocationMessage($"Entering {location.locationName}...", Color.yellow);

        // Could load dungeon scene or start combat encounter
    }

    #endregion

    #region UI Helpers

    private void ShowLocationTooltip(MapLocation location, VisualElement label)
    {
        // Create tooltip showing location details
        var tooltip = new VisualElement();
        tooltip.name = "location-tooltip";
        tooltip.AddToClassList("location-tooltip");

        var nameLabel = new Label(location.locationName);
        nameLabel.AddToClassList("tooltip-name");

        var typeLabel = new Label(location.locationType.ToString());
        typeLabel.AddToClassList("tooltip-type");

        var statusLabel = new Label(location.isDiscovered ? "Discovered" : "Undiscovered");
        statusLabel.AddToClassList("tooltip-status");

        tooltip.Add(nameLabel);
        tooltip.Add(typeLabel);
        tooltip.Add(statusLabel);

        // Position tooltip near the label
        tooltip.style.position = Position.Absolute;
        tooltip.style.left = label.style.left.value.value + 20;
        tooltip.style.top = label.style.top.value.value - 10;

        mapContainer.Add(tooltip);
    }

    private void HideLocationTooltip()
    {
        var tooltip = mapContainer.Q<VisualElement>("location-tooltip");
        if (tooltip != null)
        {
            mapContainer.Remove(tooltip);
        }
    }

    private void ShowLocationMessage(string message, Color color)
    {
        // Create temporary message display
        var messageLabel = new Label(message);
        messageLabel.AddToClassList("location-message");
        messageLabel.style.color = color;
        messageLabel.style.position = Position.Absolute;
        messageLabel.style.bottom = 50;
        messageLabel.style.left = Length.Percent(50);
        messageLabel.style.translate = new Translate(Length.Percent(-50), 0);

        mapContainer.Add(messageLabel);

        // Remove after delay
        StartCoroutine(RemoveMessageAfterDelay(messageLabel, 3f));
    }

    private System.Collections.IEnumerator RemoveMessageAfterDelay(VisualElement message, float delay)
    {
        yield return new WaitForSeconds(delay);
        if (message.parent != null)
            message.parent.Remove(message);
    }

    private void RefreshLocationDisplay(MapLocation location)
    {
        // Find and update the specific location label
        foreach (var label in locationLabels)
        {
            if (label.text == location.locationName)
            {
                label.style.opacity = 1f;
                label.RemoveFromClassList("undiscovered");
                break;
            }
        }
    }

    #endregion

    #region Public Methods

    public void DiscoverLocation(string locationName)
    {
        var location = predefinedLocations.Find(l => l.locationName == locationName);
        if (location != null && !location.isDiscovered)
        {
            location.isDiscovered = true;
            RefreshLocationDisplay(location);
            ShowLocationMessage($"Discovered: {locationName}!", new Color(1f, 0.84f, 0f)); // gold color
        }
    }

    public void AddCustomLocation(string name, LocationType type, Vector2 position, bool discovered = false)
    {
        var newLocation = new MapLocation
        {
            locationName = name,
            locationType = type,
            mapPosition = position,
            isDiscovered = discovered,
            showName = true
        };

        predefinedLocations.Add(newLocation);

        if (mapContainer != null)
        {
            CreateLocationLabel(newLocation);
        }
    }

    public void RefreshAllLocations()
    {
        DisplayLocationNames();
    }

    public MapLocation GetNearestLocation(Vector2 worldPosition, float maxDistance = 10f)
    {
        MapLocation nearest = null;
        float closestDistance = float.MaxValue;

        foreach (var location in predefinedLocations)
        {
            float distance = Vector2.Distance(worldPosition, location.mapPosition);
            if (distance < maxDistance && distance < closestDistance)
            {
                nearest = location;
                closestDistance = distance;
            }
        }

        return nearest;
    }

    #endregion
}
